Commit ef9f1090 authored by Marc Tamlyn's avatar Marc Tamlyn
Browse files

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.
parent e5619330
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -94,6 +94,14 @@ class ArrayField(Field):
            value = [self.base_field.to_python(val) for val in vals]
        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):
        values = []
        vals = self._get_val_from_obj(obj)
+64 −0
Original line number Diff line number Diff line
# -*- 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,),
        ),
    ]
+21 −0
Original line number Diff line number Diff line
# -*- 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,
        ),
    ]
+0 −0

Empty file added.

+9 −1
Original line number Diff line number Diff line
@@ -4,10 +4,11 @@ import unittest
from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.forms import SimpleArrayField, SplitArrayField
from django.core import exceptions, serializers
from django.core.management import call_command
from django.db import models, IntegrityError, connection
from django.db.migrations.writer import MigrationWriter
from django import forms
from django.test import TestCase
from django.test import TestCase, override_settings
from django.utils import timezone

from .models import IntegerArrayModel, NullableIntegerArrayModel, CharArrayModel, DateTimeArrayModel, NestedIntegerArrayModel
@@ -226,6 +227,13 @@ class TestMigrations(TestCase):
        statement, imports = MigrationWriter.serialize(field)
        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')
class TestSerialization(TestCase):