Django Rest Framework:序列化程序中的get_FOO_display不允许我POST

w7t8yxp5  于 2023-10-21  发布在  Go
关注(0)|答案(3)|浏览(173)

我最近添加了一个source='get_fieldname_display到我的序列化器。它在获取choices元组的显示值时工作得很好,但现在我不能再使用API端点POST数据而不会得到错误:

TypeError: 'get_fieldname_display' is an invalid keyword argument for this function

为了清楚起见,对序列化器的添加是专门的这一行:

fieldName = serializers.CharField(source='fieldName_display')

我知道这一行是导致问题的原因,因为当我注解掉它时,我可以毫无问题地发布数据。但是,我需要这一行,这样当我获取数据时,我就可以从choices元组中获取显示名称。
我认为如果我使用两个不同的序列化器,一个用于GET,另一个用于POST,这个问题可能会得到解决,但我不确定如何做到这一点--我在views.py中使用的是generics.ListCreateAPIView
编辑:
我的模型看起来像这样:

class MakeObjects(models.Model):

    FIELD_NAME_CHOICES = (
        ("01", "Choice 1"), 
        ("02", "Choice 2"), 
    )

    fieldname = CharField(choices = FIELD_NAME_CHOICES)

我的序列化器看起来像这样:

class ObjectSerializer(serializers.ModelSerializer): 
       fieldname = serializers.CharField(source='get_fieldname_display')
       class Meta:
           model = MakeObjects
           fields = ('__all__')
42fyovps

42fyovps1#

要实现这一点,您需要自定义序列化器字段。
下面是Python 3的代码片段:

class DisplayNameWritableField(serializers.ChoiceField):
    def __init__(self, **kwargs):
        self.html_cutoff = kwargs.pop('html_cutoff', self.html_cutoff)
        self.html_cutoff_text = kwargs.pop('html_cutoff_text', self.html_cutoff_text)

        self.allow_blank = kwargs.pop('allow_blank', False)
        super(ChoiceField, self).__init__(**kwargs)

    def to_representation(self, value):
        return self.choices.get(value, value)

    def bind(self, field_name, parent):
        super().bind(field_name, parent)
        self.choices = parent.Meta.model._meta.get_field(field_name).choices

然后又道:

class YourModelSerializer(serializers.ModelSerializer):
    your_choiced_model_field = DisplayNameWritableField()

这是一个有点黑客虽然,所以不是所有的自动文档引擎检测正确的选择,即使这工作得很好。
您可能也喜欢https://github.com/encode/django-rest-framework/issues/1755

qgzx9mmu

qgzx9mmu2#

您可以尝试在以下位置添加新字段:

read_only_fields = ['fieldName']
byqmnocz

byqmnocz3#

对于任何人来说,这可能仍然有帮助,我最喜欢的方法是创建一个新的字段来显示人类可读的名称,并使新字段只读。
您的序列化程序现在看起来类似于

class ObjectSerializer(serializers.ModelSerializer): 
   fieldname_full = serializers.CharField(source='get_fieldname_display')
   class Meta:
       model = MakeObjects
       fields = ('fieldname', 'fieldname_full')
       read_only_fields = ('fieldname_full',)

你的回答看起来像是

{
    "country": "GM",
    "country_full": "The Gambia"
}

一个字段具有简短、明确的值,非常适合创建和更新操作,另一个字段是只读的,人类可读。

相关问题