带有默认字段的Django模型序列化问题

时间:2018-11-05 12:06:59

标签: python django postgresql django-models django-admin

在我的应用程序模型中,我使用 IntegerRangeField 字段:

from django.db import models
from django.contrib.postgres.fields import IntegerRangeField
from django.contrib.postgres.validators import RangeMinValueValidator, RangeMaxValueValidator
from psycopg2.extras import NumericRange


class MyModel(models.Model):
    ...

    field = IntegerRangeField(default=NumericRange(400, 600), validators=[
        RangeMinValueValidator(1),
        RangeMaxValueValidator(1000)
    ])
    ...

默认”属性仅在管理面板用户界面中使用,在其他任何地方都不需要。

如果我在迁移后添加它们,它们将正常运行。但是,如果我在运行makemigrations之前添加它们,则会收到以下消息:

  

ValueError:无法序列化:NumericRange(400,600,'[)')有   Django无法将某些值序列化为迁移文件。

我什至不希望将默认值保存到我的PostgreSQL数据库中,我只想不必每次运行makemigrations时都将其删除并恢复。

有什么想法吗?

(无效:具有“ lower”和“ higher”属性,单个整数,字符串,元组的自定义对象)

Python:3.6.6,Django:2.1.2,PostgreSQL:11.0

3 个答案:

答案 0 :(得分:0)

尝试将默认值计算移至单独的函数中:

def get_default_range():
    return NumericRange(400, 600)

class MyModel(models.Model):
    field = IntegerRangeField(default=get_default_range, validators=[
        RangeMinValueValidator(1),
        RangeMaxValueValidator(1000)
    ])

在这种情况下,迁移已成功生成:

   operations = [
       migrations.AddField(
            model_name='comment',
            name='field',
            field=django.contrib.postgres.fields.ranges.IntegerRangeField(
                default=play.models.get_default_range,
                validators=[django.contrib.postgres.validators.RangeMinValueValidator(1),
                            django.contrib.postgres.validators.RangeMaxValueValidator(1000)]),
        ),
    ]

答案 1 :(得分:0)

我能够使用范围的字符串表示来解决此问题:

IntegerRangeField(default='[400, 600]')

django == 3.0.5 psycopg2 == 2.8.5

答案 2 :(得分:0)

编辑我应该指出最初的问题是 2 岁,但至少在 django 3.1 中,它们是一个序列化程序,您必须单独注册。

需要注册django提供的serializer。

from psycopg2.extras import NumericRange
from django.contrib.postgres.serializers import RangeSerializer
from django.db.migrations.writer import MigrationWriter

MigrationWriter.register_serializer(NumericRange, RangeSerializer)

这部分不在文档中,但是您可以按预期添加默认值:

class AgeDivision(models.Model):
    name = models.CharField(max_length=50, unique=True)
    age_range = fields.IntegerRangeField(
        unique=True, blank=True, default=NumericRange(None, None))

至于把它放在哪里,它只需要放在任何只加载一次的模块旁边。该文档没有指定自定义序列化程序的放置位置(至少我能找到),但我想说将它们放在 migrations/__init__.py 文件中,以用于任何需要序列化程序的应用程序。这是有关迁移序列化的文档:https://docs.djangoproject.com/en/3.1/topics/migrations/#custom-serializers