Saving a model in Django gives me "Warning: Field 'id' doesn't have a default value"

11,477

Solution 1

I'd like to expand on this question as I've ran into it this week. I was getting this same exact error and taking a look at the model definition and SQL definition showed that:

  1. The models affected either had no PK explicitly defined or had a PK explicitly defined (both had problems). This alone seemed unrelated.

  2. The tables affected had the "id" definition as in the OP, i.e. id int(11) NOT NULL AUTO_INCREMENT. The PRIMARY KEY is set as expected.

  3. Looking into the MySQL query log I got something to this extent:

    INSERT INTO `x` (...) VALUES (...)
    SHOW WARNINGS
    ROLLBACK
    

    Running the query individually is successful, and SHOW WARNINGS reflects the warning noted in the OP.

I however came across a MySQL-end fix, http://webit.ca/2012/01/field-id-doesnt-have-a-default-value/ mentioned that resetting the id definition (which at a cursory glance appears to not be any different) fixes the problem. I can't explain why this works, but it addresses the problem without any additional code changes. I believe this may be in some way linked to removing records, but the whole issue seems non-sensical to me.

Solution 2

Do you have a chance to recreate the database? It seems there might be something wrong with it.

As a side note: You don't have to call datetime.now() for created_at if you already set the default of field to be datetime.now.

Solution 3

Your save method is really not necessary, you can use the arguments: DateField.auto_now and DateField.auto_now_add. Those arguments handle your created_at and updated_at attributes:

  1. DateField.auto_now: Automatically set the field to now every time the object is saved. Useful for "last-modified" timestamps.
  2. DateField.auto_now_add: Automatically set the field to now when the object is first created. Useful for creation of timestamps.

Try again just using the default save() method, hope it helps!

More info about auto_now and auto_now_add in: https://docs.djangoproject.com/en/dev/ref/models/fields/#datefield

Solution 4

save method sometimes uses additional arguments and keywors arguments but you dont handle them. I'm not sure but this may fix your problem

def save(self, *args, **kwargs):
    if self.created_at == None:
         self.created_at = datetime.now()
    self.updated_at = datetime.now()
    super(Case, self).save(*args, **kwargs)

Solution 5

Im sure youve probably fixed the issue by now, but I just ran into the same problem.

Turns out auto-increment wasnt set for the primary key, so I fixed the issue by turning auto-increment on for each primary key in my database.

Hope that helps anyone else who gets the same issue.

Share:
11,477
Abhinav Kaushal Keshari
Author by

Abhinav Kaushal Keshari

Updated on August 12, 2022

Comments

  • Abhinav Kaushal Keshari
    Abhinav Kaushal Keshari over 1 year

    I have a very basic model in Django:

    class Case(models.Model):
        name = models.CharField(max_length=255)
        created_at = models.DateTimeField(default=datetime.now)
        updated_at = models.DateTimeField(default=datetime.now)
    
        def save(self):
            if self.created_at == None:
                 self.created_at = datetime.now()
            self.updated_at = datetime.now()
            super(Case, self).save()
    
        class Meta:
            db_table = u'cases'
    

    Because I did not specify the PK, Django took care of that for me. I see the field in my database which is called "id", marked as a primary key and auto-increment. I find odd to be getting that warning since everything is cool on the DB and model end. The error is:

    _mysql_exceptions.Warning
    
    Warning: Field 'id' doesn't have a default value
    

    My work around when saving is to set the id to 0. It kills the warning and the id gets set properly anyway since MySQL handles it.

    case = Case()
    case.id = 0 #ugly workaround for - Warning: Field 'id' doesn't have a default value
    case.name = request.POST[u'case[name]']
    case.save()
    

    The issue with this solution is:

    1. It's ugly
    2. The new PK is inaccessible after saving which makes it impossible to serialize properly

    Does anyone know how to fix this?

    I'm running:

    Python 2.7.2
    django.VERSION (1, 3, 1, 'final', 0)
    mysql  Ver 14.14 Distrib 5.1.45, for apple-darwin10.2.0 (i386) using readline 5.1
    MySQL_python-1.2.3-py2.7-macosx-10.4-x86_64.egg
    

    And my create table looks like this:

    CREATE TABLE `cases` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) NOT NULL,
      `created_at` datetime NOT NULL,
      `updated_at` datetime NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=45 DEFAULT CHARSET=latin1