#31245: "Invalid default value for '<charfield>'" for CharField choices 
migration
generated by Django 1.11 and run on Django 2.2
-----------------------------------------+------------------------
               Reporter:  Tony S Yu      |          Owner:  nobody
                   Type:  Bug            |         Status:  new
              Component:  Uncategorized  |        Version:  2.2
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 = System details =

 - Migrations generated in Django 1.11.28 + Python 2.7
 - Migrations run on Django 2.2.10 + Python 3.6
 - Database backend: `django.db.backends.mysql`

 = Summary =
 We recently upgraded an app from Django 1.11 to 2.2. When a developer on
 the team attempted to re-install the app from scratch some time later,
 they ran into the following exception:
 {{{
 django.db.utils.OperationalError: (1067, "Invalid default value for
 '<charfield>'")
 }}}
 where the `<charfield>` had **`choices` containing //bytestring// db
 values and //unicode// string labels** (i.e. `choices=[(<bytes>,
 <str>),...]`)

 I reproduced this in isolation using a modified version of
 [https://docs.djangoproject.com/en/3.0/ref/models/fields/#choices the
 Students example from the docs]:
 {{{
 #!python
 class Student(models.Model):

     name = models.CharField(max_length=300)

     FRESHMAN = 'FR'
     SOPHOMORE = 'SO'
     JUNIOR = 'JR'
     SENIOR = 'SR'
     GRADUATE = 'GR'
     YEAR_IN_SCHOOL_CHOICES = [
         (FRESHMAN, u'Freshman'),
         (SOPHOMORE, u'Sophomore'),
         (JUNIOR, u'Junior'),
         (SENIOR, u'Senior'),
         (GRADUATE, u'Graduate'),
     ]
     year_in_school = models.CharField(
         max_length=2,
         choices=YEAR_IN_SCHOOL_CHOICES,
         default=FRESHMAN,
     )
 }}}
 The main modification is that the `choices` labels are explicitly unicode,
 but the db values are unprefixed strings (bytestrings in Python 2, unicode
 in Python 3). (Note that the actual code generated choices from an `Enum`,
 which when combined with Python 2 using unicode literals causes bytestring
 db values and unicode labels used above.)

 In practice, I wasn't able to reproduce the error without splitting up the
 `year_in_school` migration from the model creation. (The `name` field was
 added to the model to create an initial migration.)

 Running the `year_in_school` migration using Django 1.11.28 (on Python
 2.7) generates the following migration:
 {{{
 #!python
 # -*- coding: utf-8 -*-
 # Generated by Django 1.11.28 on 2020-02-07 17:07
 from __future__ import unicode_literals

 from django.db import migrations, models


 class Migration(migrations.Migration):

     dependencies = [
         ('djangodebug', '0001_initial'),
     ]

     operations = [
         migrations.AddField(
             model_name='student',
             name='year_in_school',
             field=models.CharField(choices=[(b'FR', 'Freshman'), (b'SO',
 'Sophomore'), (b'JR', 'Junior'), (b'SR', 'Senior'), (b'GR', 'Graduate')],
 default=b'FR', max_length=2),
         ),
     ]
 }}}
 **Running that migration in Django 1.11 (on either Python 2 or 3) works
 fine. Running the migration in Django 2.2 throws the following error**:
 {{{
 django.db.utils.OperationalError: (1067, "Invalid default value for
 'year_in_school'")
 }}}

 = Additional Notes =

 == Workarounds ==
 - Downgrade to Django 1.11 and run migrations, then revert to Django 2.2
 - Manually modify migration files to use unicode strings (i.e. remove `b`
 prefix from strings)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31245>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/050.5a2e7320b2239362d0606f16355dd8b2%40djangoproject.com.

Reply via email to