Fixed #22962 -- Default values for ArrayField with migrations.
Fields normally try to force the default value to a string. As translatable strings are not valid default values for ArrayField, we can remove this behaviour which was causing issues with some migrations. Thanks to @schinckel for the report.
This commit is contained in:
parent
e5619330e2
commit
ef9f109013
|
@ -94,6 +94,14 @@ class ArrayField(Field):
|
||||||
value = [self.base_field.to_python(val) for val in vals]
|
value = [self.base_field.to_python(val) for val in vals]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def get_default(self):
|
||||||
|
"""Overridden from the default to prevent string-mangling."""
|
||||||
|
if self.has_default():
|
||||||
|
if callable(self.default):
|
||||||
|
return self.default()
|
||||||
|
return self.default
|
||||||
|
return ''
|
||||||
|
|
||||||
def value_to_string(self, obj):
|
def value_to_string(self, obj):
|
||||||
values = []
|
values = []
|
||||||
vals = self._get_val_from_obj(obj)
|
vals = self._get_val_from_obj(obj)
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
import django.contrib.postgres.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CharArrayModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('field', django.contrib.postgres.fields.ArrayField(models.CharField(max_length=10), size=None)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DateTimeArrayModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('field', django.contrib.postgres.fields.ArrayField(models.DateTimeField(), size=None)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='IntegerArrayModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('field', django.contrib.postgres.fields.ArrayField(models.IntegerField(), size=None)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='NestedIntegerArrayModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('field', django.contrib.postgres.fields.ArrayField(django.contrib.postgres.fields.ArrayField(models.IntegerField(), size=None), size=None)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='NullableIntegerArrayModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('field', django.contrib.postgres.fields.ArrayField(models.IntegerField(), size=None, null=True, blank=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
import django.contrib.postgres.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('postgres_tests', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='integerarraymodel',
|
||||||
|
name='field_2',
|
||||||
|
field=django.contrib.postgres.fields.ArrayField(models.IntegerField(), default=[], size=None),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -4,10 +4,11 @@ import unittest
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.contrib.postgres.forms import SimpleArrayField, SplitArrayField
|
from django.contrib.postgres.forms import SimpleArrayField, SplitArrayField
|
||||||
from django.core import exceptions, serializers
|
from django.core import exceptions, serializers
|
||||||
|
from django.core.management import call_command
|
||||||
from django.db import models, IntegrityError, connection
|
from django.db import models, IntegrityError, connection
|
||||||
from django.db.migrations.writer import MigrationWriter
|
from django.db.migrations.writer import MigrationWriter
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.test import TestCase
|
from django.test import TestCase, override_settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from .models import IntegerArrayModel, NullableIntegerArrayModel, CharArrayModel, DateTimeArrayModel, NestedIntegerArrayModel
|
from .models import IntegerArrayModel, NullableIntegerArrayModel, CharArrayModel, DateTimeArrayModel, NestedIntegerArrayModel
|
||||||
|
@ -226,6 +227,13 @@ class TestMigrations(TestCase):
|
||||||
statement, imports = MigrationWriter.serialize(field)
|
statement, imports = MigrationWriter.serialize(field)
|
||||||
self.assertEqual(statement, 'django.contrib.postgres.fields.ArrayField(models.CharField(max_length=20), size=None)')
|
self.assertEqual(statement, 'django.contrib.postgres.fields.ArrayField(models.CharField(max_length=20), size=None)')
|
||||||
|
|
||||||
|
@override_settings(MIGRATION_MODULES={
|
||||||
|
"postgres_tests": "postgres_tests.array_default_migrations",
|
||||||
|
})
|
||||||
|
def test_adding_field_with_default(self):
|
||||||
|
# See #22962
|
||||||
|
call_command('migrate', 'postgres_tests', verbosity=0)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL required')
|
@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL required')
|
||||||
class TestSerialization(TestCase):
|
class TestSerialization(TestCase):
|
||||||
|
|
Loading…
Reference in New Issue