我在Django Rest Framework上很新,而且我一直试图为我的一个模型编写一个序列化器。对于我的项目,我打算根据JSON API标准输出json结果,为此,我使用SerializerMethodField,我在其中调用方法get_data()
,如下所示:
class Level(MPTTModel):
name = models.CharField(max_length=100)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
class MPTTMeta:
order_insertion_by = ['name']
class Group(models.Model):
name = models.CharField(max_length=100)
level_set = models.ManyToManyField(Level, blank=True)
class LevelSerializer(serializers.ModelSerializer):
data = serializers.SerializerMethodField()
class Meta:
model = Level
fields = ('data',)
def get_data(self, instance):
return {
"type": "Level",
"uuid": instance.id_key(),
"attributes": {
"name": instance.name,
},
"relationships": {
"children": self.get_children_recursive(),
},
}
def get_children_recursive(self, child=None):
"""
Generates a tree of levels structured according to JSON API standards.
"""
if not child:
children = self.instance.get_children()
level = self.instance
else:
children = child.get_children()
level = child
tree = {
'data': {
'type': 'Level',
'uuid': level.id_key(),
'attributes': {
'name': level.name,
},
'relationships': {
'children': [],
'parents': [],
}
}
}
for child in children:
tree['data']['relationships']['children'].append(self.get_children_recursive(child))
return tree
class GroupSerializer(serializers.ModelSerializer):
root_level_set = LevelSerializer(many=True)
class Meta:
model = Group
fields = ('id_key', 'name', 'root_level_set')
奇怪的是,如果我转到shell并尝试序列化Level的实例,它可以正常工作,但是尝试序列化一个组会在get_children_recursive()
处与if not child statement
一致时出错}说'NoneType' object has no attribute 'get_children'
。输出如下:
执行命令
from core.serializers import LevelSerializer
from core.models import Level
lvl = Level.objects.all()[0]
serializer = LevelSerializer(lvl)
print(serializer.data)
根据我按照JSON API标准设计的JSON结构输出嵌套级别及其子级别。
虽然如果我跑:
from core.serializers import GroupSerializer
from core.models import Group
grp = Group.objects.all()[0]
serializer = GroupSerializer(grp)
print(serializer.data)
输出:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/serializers.py", line 239, in data
self._data = self.to_representation(self.instance)
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/serializers.py", line 614, in to_representation
self.child.to_representation(item) for item in iterable
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/serializers.py", line 614, in <listcomp>
self.child.to_representation(item) for item in iterable
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/home/maumau/.virtualenvs/olist/lib/python3.5/site-packages/rest_framework/fields.py", line 1653, in to_representation
return method(value)
File "/mnt/SHARED-DRIVE/Workspace/interview-tests/work-at-olist/core/serializers.py", line 20, in get_data
"children": self.get_children_recursive(),
File "/mnt/SHARED-DRIVE/Workspace/interview-tests/work-at-olist/core/serializers.py", line 29, in get_children_recursive
children = self.instance.get_children()
AttributeError: 'NoneType' object has no attribute 'get_children'
对我来说似乎没有意义,Level it self的序列化拥有属性实例集,而Group的序列化也调用了Level的序列化。任何线索?
答案 0 :(得分:1)
为什么要自己设计一切?让djrf做一些魔术:)
ReactNative.findNodeHandle(component)
为什么你的代码不起作用?因为错误的代码:
class LevelSerializer(serializers.ModelSerializer):
type = serializers.SerializerMethodField()
attributes = serializers.SerializerMethodField()
relationships = serializers.SerializerMethodField()
def get_type(self, instance):
return "Level"
def get_attributes(self, instance):
return {
"name": instance.name
}
def get_relationships(self, instance):
return {
"children": self.__class__(instance.get_children(), many=True).data,
"parents": []
}
class Meta:
model = Level
fields = ('type', 'attributes', 'relationships')
class GroupSerializer(serializers.ModelSerializer):
level_set = LevelSerializer(many=True)
class Meta:
model = Group
fields = ('name', 'level_set')
有什么不同 - 一个参数 - LevelSerializer
; many=True
时 - 序列化程序没有many=True
属性instance
将第一个元素复制为第一个孩子get_children_recursive
,因为所有操作都是手动完成的 - 在这种情况下,简单ModelSerializer
会更好Serializer
字段 - 您使代码更复杂,为什么不直接使用数据来避免使用一个data
密钥的字典我的示例代码缺少data
字段 - 您没有在此处记录,但添加它应该是一个breze
使用额外的模块id_key
,可以简化代码:
rest_framework_recursive
答案 1 :(得分:0)
serialzier中的属性名称:root_level_set
。在模型中:level_set
。
DRF尝试在组中查找属性root_level_set
,找不到它并将其替换为None
。这就是为什么你会遇到这样的错误。
修正:
root_level_set
- &gt;序列化程序中的level_set
。source
添加到字段:root_level_set = LevelSerializer(source='level_set', many=True)