Django Rest Fram中序列化程序之间的公共字段混合

2024-04-28 11:20:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这个:

class GenericCharacterFieldMixin():
    attributes = serializers.SerializerMethodField('character_attribute')
    skills = serializers.SerializerMethodField('character_skill')

    def character_attribute(self, obj):
        character_attribute_fields = {}
        character_attribute_fields['mental'] = {str(trait_item.get()): trait_item.get().current_value
                                                for trait_item in obj.mental_attributes}
        character_attribute_fields['physical'] = {str(trait_item.get()): trait_item.get().current_value
                                                  for trait_item in obj.physical_attributes}
        character_attribute_fields['social'] = {str(trait_item.get()): trait_item.get().current_value
                                                for trait_item in obj.social_attributes}
        return character_attribute_fields

    def character_skill(self, obj):
        character_skill_fields = {}
        character_skill_fields['mental'] = {str(trait_item.get()): trait_item.get().current_value
                                            for trait_item in obj.mental_skills}
        character_skill_fields['physical'] = {str(trait_item.get()): trait_item.get().current_value
                                              for trait_item in obj.physical_skills}
        character_skill_fields['social'] = {str(trait_item.get()): trait_item.get().current_value
                                            for trait_item in obj.social_skills}
        return character_skill_fields


class MageSerializer(GenericCharacterFieldMixin, serializers.ModelSerializer):
    player = serializers.ReadOnlyField(source='player.username')
    arcana = serializers.SerializerMethodField()

    def get_arcana(self, obj):
        if obj:
            return {str(arcana): arcana.current_value for arcana in obj.linked_arcana.all()}

    class Meta:
        model = Mage
        fields = ('id', 'player', 'name', 'sub_race', 'faction', 'is_published',
                  'power_level', 'energy_trait', 'virtue', 'vice', 'morality', 'size',
                  'arcana', 'attributes', 'skills')
        depth = 1

GenericCharacterFieldMixin是字符字段的混合体,这些字符是通用的,即所有类型的字符都是通用的。在

我希望我的法师序列化程序有这些'混合'而不是c/p然后在所有类型的字符(法师是一种字符类型)希望这将增加我的网络应用程序干燥。在

问题出在车型上我有这个:

^{pr2}$

这意味着我得到了这个错误:

TypeError at /characters/api/mages
<django.contrib.contenttypes.fields.create_generic_related_manager.<locals>.GenericRelatedObjectManager object at 0x00000000051CBD30> is not JSON serializable

Django Rest Framework认为我想序列化我的泛型关系。

如果我重命名模型中的字段(s/attributes/foos/gs/skills/bars/g),那么我得到一个不同的(不太清楚?)错误:

ImproperlyConfigured at /characters/api/mages
Field name `attributes` is not valid for model `ModelBase`.

如何在不混淆DRF的情况下将这些方法和字段拉入mixin?在


Tags: inobjfieldsforgetvalueattributecurrent
3条回答

{cd1>}集:

from rest_framework import serializers

class GenericCharacterFieldMixin(metaclass=serializers.SerializerMetaclass):
    # ...

这是解决方案recommended by DRF's authors。在

前面的答案中建议的解决方案是有问题的:

  1. user1376455的解决方案通过在子级上将mixin的字段声明为不同的字段,将它们注册到_declared_fields中。这种黑客攻击可能在框架的后续版本中不起作用。在
  2. Nikolay Fominyh的解决方案将mixin更改为一个完全成熟的序列化程序(请注意,由于这个原因,GenericCharacterFieldMixin对于一个不是mixin而是序列化器的类来说是非常不幸的!)。这是有问题的,因为它将完整的Serializer类引入多重继承,请参见DRF issue中的示例,以说明这是一个坏主意。在

我也有同样的问题,我的谷歌搜索把我带到了这里。我设法解决了。 因为您在serialiser中包含属性和技能字段,所以需要为其提供序列化方法。在

这对我有用

class MageSerializer(GenericCharacterFieldMixin, serializers.ModelSerializer):
    player = serializers.ReadOnlyField(source='player.username')
    arcana = serializers.SerializerMethodField()


    attributes = serializers.PrimaryKeyRelatedField(many=True, 
                                read_only= True)
    skills = serializers.PrimaryKeyRelatedField(many=True, 
                                read_only= True)


    def get_arcana(self, obj):
      if obj:
        return {str(arcana): arcana.current_value for arcana in obj.linked_arcana.all()}

    class Meta:
        model = Mage
        fields = ('id', 'player', 'name', 'sub_race', 'faction', 'is_published',
                  'power_level', 'energy_trait', 'virtue', 'vice', 'morality', 'size',
                  'arcana', 'attributes', 'skills')
        depth = 1

解决办法很简单,就是改变

class GenericCharacterFieldMixin():

^{pr2}$

相关问题 更多 >