I need to define a Django model field with the name in, which is a Python language keyword. This is a syntax error:
class MyModel(models.Model):
    in = jsonfield.JSONField()
How can I make this work?
The reason I need this name is when I use django-rest-framework's ModelSerializer class, field name is used as the key for serialization output, and I thought it might be easier to manipulate django's Model class instead of ModelSerializer class to get the output I want.
Generally speaking, you don't. Avoid the use of keywords in your identifiers. The general Python convention is to add an underscore to such names; here that'd be in_:
class MyModel(models.Model):
    in_ = jsonfield.JSONField()
However, Django prohibits names ending in an underscore because the underscore clashes with their filter naming conventions, so you have to come up with a different name still; pick one that still describes your case; I picked contained in rather than in, as a guess to what you want to do here:
class MyModel(models.Model):
    contained_in = jsonfield.JSONField()
If you are trying to match an existing database schema, use the db_column attribute:
class MyModel(models.Model):
    contained_in = jsonfield.JSONField(db_column='in')
If you want to be stubborn, in normal classes you could use setattr() after creating the class to use a string instead of an identifier:
class Foo:
    pass
setattr(Foo, 'in', 'some value')
but you'll have to use setattr(), getattr(), delattr() and/or vars() everywhere in your code to be able to access this.
In Django you'll have the added complication that a models.Model subclass uses a metaclass to parse out your class members into others structures, and adding an extra field with setattr() doesn't work without (a lot of) extra work to re-do what the metaclass does. You could instead use the field.contribute_to() method, calling it after the class has been prepared by Django (technique taken from this blog post):
from django.db.models.signals import class_prepared
def add_field(sender, **kwargs):
    if sender.__name__ == "MyModel":
        field = jsonfield.JSONField('in')
        field.contribute_to_class(sender, 'in')
class_prepared.connect(add_field)
but you have to make sure this hook is registered before you create your model class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With