kansiho
kansiho

Reputation: 532

Django MySQL IntegrityError: ("Field 'created_at' doesn't have a default value")

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.

version

Django==1.11.5 
mysqlclient==1.3.12                                                                                                                                                                                                
Python 3.6.1

Thanks in advance.

Upvotes: 1

Views: 3416

Answers (3)

an0o0nym
an0o0nym

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

cezar
cezar

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

Johannes Reichard
Johannes Reichard

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

Related Questions