Reputation: 532
I am new to Django.
IntegrityError: (1364, "Field 'created_at' doesn't have a default value")
occurred when I didn't write created_at
for models I defined at models.py.
Every time I face such error, I add
created_at = models.DateTimeField(default=timezone.now, null=True)
to models.py and then run python manage.py makemigrations; python manage.py migrate --fake
.
Is that OK? (I mean, does it follow Django best practice or not? )
When I was using Rails, I've never faced such issues. Why doesn't Django automatically handle created_at
column?
Also, I'd like to know why --fake
option removes this error.
Django==1.11.5
mysqlclient==1.3.12
Python 3.6.1
Thanks in advance.
Upvotes: 1
Views: 3416
Reputation: 1516
I've encountered similar issue, where my DB state was out of sync with the repository (probably some leftover fields remained in DB from migrations from another repository branch).
I was getting crazy seeing this error:
IntegrityError: (1364, "Field 'open' doesn't have a default value")
when I did not have field open
in my model.
Make sure to inspect your DB schema and look for table definitions, then compare it with your Django model definitions.
Upvotes: 0
Reputation: 12032
From your comments I think I can reproduce your steps. You had a model class in your models.py
:
from django.db import models
class YourModel(models.Model):
one_field = models.CharField()
another_field = models.CharField()
Then you ran:
python manage.py makemigrations
python manage.py migrate
After that you added to your model class:
from django.db import models
class YourModel(models.Model):
one_field = models.CharField()
another_field = models.CharField()
created_at = models.DateTimeField(default=timezone.now, null=True)
but forgot to run the migrations and got the error message.
This is because Django ORM is looking for the property created_at
, which it can't find in the DB.
You have to run the commands:
python manage.py makemigrations
python manage.py migrate
again. Remember that the option --fake
won't change the DB. It just marks the migration as run. Use it only when you're sure what are you doing.
As Johannes Reichard has suggested you should better use auto_now_add
(and there is also auto_now
) for this purpose. Check the official documentation.
The drawback is that this field won't be shown in the admin. A workaround is to overwrite the save method:
def save(self, *args, **kwargs):
if not self.pk:
self.created_at = timezone.now() # import it from django.utils
super(YourModel, self).save(*args, **kwargs)
Upvotes: 3
Reputation: 947
It seems that you want to have an attribute created_at
which is set on every creation of a model instance. There is an easier way for that:
created_at = models.DateTimeField(auto_now_add=True)
Here the docs explaining it in detail https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.DateField.auto_now_add
Upvotes: 4