There are several questions on StackOverflow regarding a field that is defined in a model, but does not appear in the database after making migrations and migrating.
What are the symptoms?
If we inspect the migration file that was constructed by the makemigrations
command [Django-doc], we see that only a subset of the fields (or none at all) are mentioned, and some fields that have been defined in the model are thus missing.
What is a possible fix?
Usually this is caused because we did not define that field correctly in the model. There are typically three variants to that problem.
Variant 1: Trailing comma
Some people tend to end the line of a field with a comma, for example:
from django.db import models
class MyModel(models.Model):
# a trailing comma ↓
name = models.CharField(max_length=128),
This will wrap the CharField
in a singleton tuple (a tuple with one element). Django will look for items in the class that are subclasses of the Field
class [Django-doc]. While the tuple wraps a CharField
that is a subclass of Field
, a singleton tuple that contains such element is not, so Django will not recognize it.
In that case you thus drop the trailing comma, and work with:
from django.db import models
class MyModel(models.Model):
# no trailing comma ↓
name = models.CharField(max_length=128)
Variant 2: Using a colon between the name of the field and the field
Often people write classes like one writes a dictionary literal: with a colon (:
) between the key and the value. This thus can look like:
from django.db import models
class MyModel(models.Model):
# ↓ a colon
name : models.CharField(max_length=128)
This is not a way to define a class attribute. The colon is used for annotations. Indeed, if we inspect MyModel
, we see:
>>> MyModel.name
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: type object 'MyModel' has no attribute 'name'
Colons are here used to create type annotations. Indeed, if we inspect the __annotations__
attribute of MyModel
, we see:
>>> MyModel.__annotations__
{'name': <django.db.models.fields.CharField>}
We here thus made an annotation to specify that name
will have a certain type, but we never define name
at the class level.
We thus should replace the colon with an equals sign (=
):
from django.db import models
class MyModel(models.Model):
# ↓ equals sign instead of a colon
name = models.CharField(max_length=128)
Variant 3: mixing form fields and model fields
Another common variant is mixing model fields with form fields. It is easy to make such mistake, since a lot of form fields have the same class name as their model field. Especially if one uses an IDE, and then for example writes CharField
, it is possible that the IDE will propose to import the wrong module. This thus could look like:
from django.db import models
from django.forms import CharField
class MyModel(models.Model):
# ↓ CharField from the django.forms module
name = CharField(max_length=128)
Since this CharField
does not inherit from the Field
of the django.db.models
module, again Django will not see this as a field that should be included in the migration.
In Django model fields focus in storing data in the database, whereas form fields help to process data when a form is submitted. It thus makes no sense that model fields appear in forms, or that form fields appear in models.
Therefore it might be better to import the django.db.models
module, and always use models.CharField
in that case it gives a visual hint that it is using the correct field:
from django.db import models
class MyModel(models.Model):
# ↓ import from the models module.
name = models.CharField(max_length=128)