【问题标题】:Unable to save empty list to Django ArrayField无法将空列表保存到 Django ArrayField
【发布时间】:2020-11-16 18:42:42
【问题描述】:

我有一个 Django 模型

from django.db import models
from django.contrib.postgres.fields import ArrayField


class Website(models.Model):
    id = models.BigAutoField(primary_key=True, verbose_name='ID')
    status = models.BooleanField(default=True)
    meta = ArrayField(base_field=models.CharField(max_length=200, null=True), default=list)

我正在使用以下序列化程序将数据保存到数据库:

class WebsiteConfigSerializer(serializers.ModelSerializer):
    class Meta:
        model = Website
        fields = ('status', 'meta')

当我尝试保存以下数据时,出现错误:

{
    "status": true,
    "meta": []
}

#ERROR:
# "meta : This list may not be empty."

不能将空列表保存到 ArrayField 吗? 当我根本不传递该字段时,存储的值是{NULL}。 同样在初始迁移期间,由于我将 default 值添加为 list,因此我所有现有条目的“元”值都为 {}

如果根本不允许空列表值,那么在初始迁移期间如何保存?

【问题讨论】:

    标签: python-3.x django postgresql django-models django-rest-framework


    【解决方案1】:

    尝试将您的模型更改为

    from django.db import models
    from django.contrib.postgres.fields import ArrayField
    
    
    class Website(models.Model):
        id = models.BigAutoField(primary_key=True, verbose_name='ID')
        status = models.BooleanField(default=True)
        meta = ArrayField(base_field=models.CharField(max_length=200, null=True), default=list, blank=True)
    

    【讨论】:

    • 投了反对票,因为 a) 不要在其他健全的模型定义中修复序列化程序问题,并且 b) 你正在做文档告诉你不要做的事情(在我的回答中引用)。跨度>
    • 您对可调用列表的看法是正确的,但您必须更改模型,即blank=True。我编辑了我的答案以避免误导人们。
    • 我认为你错过了 ModelSerializer 类的要点。
    • blank=True 有效并且与 ModelSerializer 相关。
    【解决方案2】:

    可以保存一个空列表,甚至可以默认为the documentation states

    如果您给字段一个默认值,请确保它是一个可调用的,例如列表(对于空默认值)或返回列表的可调用(例如函数)。错误地使用 default=[] 会创建一个可变的默认值,该默认值在 ArrayField 的所有实例之间共享。

    但是,您的序列化程序不允许空值:

    class WebsiteConfigSerializer(serializers.ModelSerializer):
        meta = serializers.ListField(
            allow_empty=True,
            child=serializers.CharField(
                max_length=200, allow_blank=True
            )
        )
        class Meta:
            model = Website
            fields = ('status', 'meta')
    

    您可以通过创建序列化器字段来简化此操作:

    from rest_framework import serializers
    
    
    class ArrayField(serializers.ListField):
        child = serializers.CharField(max_length=200, allow_blank=True)
    
    class WebsiteConfigSerializer(serializers.ModelSerializer):
        meta = ArrayField(allow_empty=True)
        class Meta:
            model = Website
            fields = ('status', 'meta')
    

    【讨论】:

    • 在不同的实例中添加一个空列表也不应该导致任何与可变性相关的问题。对吗?
    • 如果模型定义正确,则不需要定义序列化程序。如果您使用ModelSerializer,映射将自动生成。见:github.com/encode/django-rest-framework/blob/…
    猜你喜欢
    • 1970-01-01
    • 2017-12-26
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多