【问题标题】:Unrequired field error w/ Django REST Framework带有 Django REST 框架的不需要的字段错误
【发布时间】:2016-02-13 06:41:58
【问题描述】:

我正在使用 Django REST 框架在我的数据库/Django 模型上运行 CRUD 进程。我存储客户端数据的模型非常简单,只有一个字段给我带来了问题:用于存储自定义或自动生成的字符串的 CharField。

class Client(models.Model):
    link = models.CharField(max_length=254, default=link_generator())

我使用表单输入向/clients/ 端点发出 POST 请求 - 如果用户通过输入输入自定义字符串,它会按预期存储该字符串。如果他们将此字段留空,那很好 - 我想运行我的 link_generator 函数,该函数会创建一个随机字符串(下面的代码)。 相反,我收到一个错误 - Django REST Framework GUI 告诉我,“此字段可能不是空白的。” 但我没有在任何地方指定它应该是必需的。如果我检查序列化程序,它会明确表示不需要:

>>> from landing.serializers import ClientSerializer
>>> serializer = ClientSerializer()
>>> print(serializer)

ClientSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(max_length=50, required=False)
    email = EmailField(max_length=254, required=False)
    notes = CharField(allow_blank=True, required=False, style={'type': 'textarea'})
    link = CharField(max_length=254, required=False)
    link_expired = BooleanField(required=False)
    created = DateTimeField(read_only=True)
    updated = DateTimeField(read_only=True)

更新:添加带有建议改进的序列化程序代码 - 非常基本:

class ClientSerializer(serializers.ModelSerializer):

    class Meta:
        model = Client
        fields = ('id', 'name', 'email', 'notes', 'link', 'link_expired', 'created', 'updated')
        extra_kwargs = {
        'link': {
            'required': False,
         }
    }

Still, upon submitting I get this error every time. 是什么让它认为该字段是必需的?同样,我想允许用户将此字段留空,如果他们这样做,则运行 link_generator 函数。如果我明确地说blank=True如下:

link = CharField(max_length=254, blank=True, default=link_generator())

...link_generator 没有运行,并且最终存储了一个空白字符串。对于它的价值,这是我想在用户将输入留空的情况下运行的 link_generator 代码(旁注:我在模型上方声明了这个 - 这是不好的做法吗?应该在哪里声明):

def link_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

有什么见解吗?我很难过 - 只是不明白为什么它应该被这样标记。一般来说,我对 Django 和 REST 比较陌生 - 感谢您的帮助。

【问题讨论】:

  • 您可以更新您的帖子并从您的 serializers.py 文件中包含您的 ClientSerializer() 吗?我知道你打印了序列化程序,但以防万一......

标签: python django rest django-rest-framework


【解决方案1】:

尝试将您的序列化程序更改为:

class ClientSerializer(serializers.ModelSerializer):

    class Meta:
        model = Client
        fields = ('id', 'name', 'email', 'notes', 'link', 'link_expired', 'created', 'updated')
        extra_kwargs = {
                'link': {
                    # Tell DRF that the link field is not required.
                    'required': False,
                    'allow_blank': True,
                 }
            }

我真的很惊讶,当您打印序列化程序时,DRF 说 link 字段不是必需的,因为根据您的模型,它应该是必需的(因为未设置 blank=True)。

编辑:allow_blank 用于 CharField 序列化器字段(如果设置为 True,则空字符串应被视为有效值)。取自此处的 DRF 文档:http://www.django-rest-framework.org/api-guide/fields/#charfield

【讨论】:

  • 嗯...我试过了,但没有运气,结果相同。如果我将模型设置为blank=True,它每次都存储一个空白字符串,而不是存储link_generator函数的返回值。不知道发生了什么...还有其他想法吗?
  • @jckstl 等等,你有没有尝试上面的代码没有设置blank=True?不要在您的模型上设置 blank=True 并尝试使您的序列化器与我上面的一样。当您使用我上面的序列化程序而不在您的模型上设置 blank=True 时会出现什么错误?
  • 两种方法都试过了,结果一样:{ "link": [ "This field may not be blank." ] }
  • @jckstl 查看我的更新(我将allow_blank: True 添加到extra_kwargs)。即使设置了allow_blank,它仍然给出同样的错误吗?
  • 想通了!我可以在序列化程序中定义它,而不是在模型中定义默认值,也可以在您之前建议的 extra_kwargs 中定义 - 而不是 allow_blank,我只是更改为 extra_kwargs = { 'link': { 'default': link_generator } } 工作得很好!谢谢您的帮助!我在 DRF 文档中看到了那些额外的序列化器参数,但在通过 fields 定义序列化器时不确定如何添加它们。我很兴奋 - 再次感谢!
【解决方案2】:

在@user2719875 的帮助下,我找到了解决方案。为了获得所需的行为 - 允许用户输入自定义字符串,如果没有给出输入,则默认为字符串生成器函数 - 我需要在序列化程序本身而不是模型中定义默认值。使用extra_kwargs 选择所需的“链接”字段,我在这里声明默认函数:

class ClientSerializer(serializers.ModelSerializer):

class Meta:
    model = Client
    fields = ('id', 'name', 'email', 'notes', 'link', 'link_expired', 'created', 'updated')
    extra_kwargs = {
        'link': {
            'default': link_generator
         }
    }

有趣的是,它在models.py 本身中查找link_generator 函数,因此代码存储在那里,在模型之上。不确定这是否是最佳做法,但它确实有效。从模型本身中删除了default=link_generator,如下所示:

def link_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))


class Client(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField(max_length=254)
    notes = models.TextField(blank=True)
    link = models.CharField(max_length=254)
    link_expired = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)  # added only on creation
    updated = models.DateTimeField(auto_now=True)  # updates each time the object is saved

工作得很好。谢谢大家的帮助!

【讨论】:

    【解决方案3】:

    我在您的代码中看到的第一眼问题是默认选项。它应该是函数本身(不带括号)。把它改成这样:

    class Client(models.Model):
        link = models.CharField(max_length=254, default=link_generator)
    

    希望对你有帮助!

    【讨论】:

    • 这不是他错误的原因,但确实是他的代码中的一个错误。
    • @spectras,我实际上会推荐作者测试它......我想我以前遇到过这样的问题。
    • 谢谢大家。我实际上已经尝试过两种方式,带括号和不带括号,但感谢您解释正确的方法......仍在努力!
    • 正确的方式是没有,因为你想把功能赋予领域。如果加括号,则在导入序列化程序时会调用该函数一次,并且该字段会默认获取结果字符串(ergo 默认值始终是导入时生成的相同字符串)。
    【解决方案4】:

    我的代码是

    class AccountSerializer(serializers.ModelSerializer):
    
        users = serializers.CharField(write_only=True, required=False)
        name = serializers.CharField(write_only=True)
    

    执行时:对于,users='' ,需要序列化程序错误 场地。

    这里 required=False & blank=True 不工作,

    我也想允许空白值..

    【讨论】:

      猜你喜欢
      • 2018-08-09
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2015-05-10
      • 2023-03-17
      相关资源
      最近更新 更多