提问人:AncientSwordRage 提问时间:2/27/2015 更新时间:10/9/2019 访问量:11985
Mixin Django Rest 框架中序列化器之间的公共字段
Mixin common fields between serializers in Django Rest Framework
问:
我有这个:
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,然后在所有类型的角色(法师是一种角色)之间,希望这将增加我的网络应用程序中的 DRYness。
问题出在模型上,我有这个:
class NWODCharacter(models.Model):
class Meta:
abstract = True
ordering = ['updated_date', 'created_date']
name = models.CharField(max_length=200)
player = models.ForeignKey('auth.User', related_name="%(class)s_by_user")
....
def save(self, *args, **kwargs):
...
attributes = GenericRelation('CharacterAttributeLink')
skills = GenericRelation('CharacterSkillLink')
这意味着我收到此错误:
TypeError at /characters/api/mages
<django.contrib.contenttypes.fields.create_generic_related_manager.<locals>.GenericRelatedObjectManager object at 0x00000000051CBD30> is not JSON serializable
Django Rest 框架认为我想序列化我的泛型关系。
如果我重命名模型中的字段(,),那么我会得到一个不同的(不太清楚?)错误:s/attributes/foos/g
s/skills/bars/g
ImproperlyConfigured at /characters/api/mages
Field name `attributes` is not valid for model `ModelBase`.
如何在不混淆 DRF 的情况下将这些方法和字段拉入 mixin?
答:
3赞
user1376455
10/6/2015
#1
我遇到了同样的问题,我的谷歌搜索把我带到了这里。我设法解决了它。 由于您在 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
24赞
Nikolay Fominyh
10/24/2016
#2
解决方案很简单,就像改变一样
class GenericCharacterFieldMixin():
自
class GenericCharacterFieldMixin(serializers.Serializer):
评论
0赞
AncientSwordRage
10/24/2016
这是新事物吗?
0赞
Nikolay Fominyh
10/24/2016
@Pureferret,这是对问题的简短回答。我今天遇到了同样的问题,发现这个解决方案比 user1376455 的答案更干净。
37赞
tbitai
10/9/2019
#3
设置:SerializerMetaclass
from rest_framework import serializers
class GenericCharacterFieldMixin(metaclass=serializers.SerializerMetaclass):
# ...
这是 DRF 作者推荐的解决方案。
前面的答案中建议的解决方案是有问题的:
- user1376455 的解决方案通过在子项上将 mixin 的字段声明为不同的字段来破解 DRF 以注册它们。此 hack 在框架的后续版本中可能不起作用。
_declared_fields
- Nikolay Fominyh 的解决方案将 mixin 更改为一个成熟的序列化程序(请注意,由于这个原因,对于一个不是 mixin,而是序列化程序的类来说,这个名字是非常不幸的!这是有问题的,因为它将整个类带入多重继承,请参阅 DRF 问题以获取示例,说明为什么这是一个坏主意。
GenericCharacterFieldMixin
Serializer
评论