Django 需要帮助了解序列化程序中的许多字段和源字段吗
我目前正在尝试熟悉DRF,并且在学习使用这些序列化程序的教程时Django 需要帮助了解序列化程序中的许多字段和源字段吗,django,django-rest-framework,Django,Django Rest Framework,我目前正在尝试熟悉DRF,并且在学习使用这些序列化程序的教程时 class EmbeddedAnswerSerializer(serializers.ModelSerializer): votes = serializers.IntegerField(read_only=True) class Meta: model = Answer fields = ('id', 'text', 'votes',) class QuestionSerial
class EmbeddedAnswerSerializer(serializers.ModelSerializer):
votes = serializers.IntegerField(read_only=True)
class Meta:
model = Answer
fields = ('id', 'text', 'votes',)
class QuestionSerializer(serializers.ModelSerializer):
answers = EmbeddedAnswerSerializer(many=True,source='answer_set')
class Meta:
model = Question
fields = ('id', 'answers', 'created_at', 'text', 'user_id',)
这些是模型
class Question(models.Model):
user_id = models.CharField(max_length=36)
text = models.CharField(max_length=140)
created_at = models.DateTimeField(auto_now_add=True)
class Answer(models.Model):
question = models.ForeignKey(Question,on_delete=models.PROTECT)
text = models.CharField(max_length=25)
votes = models.IntegerField(default=0)
我的问题在问题序列化程序中的语句中
answers = EmbeddedAnswerSerializer(many=True,source='answer_set')
many=True
和source='answer\u set'的目的是什么?
我从文档中阅读了以下关于many=True
您还可以使用many=True参数来序列化类。
值得注意的是,many=True参数透明地创建了
ListSerializer实例,允许列表和
要在REST框架代码库中干净分隔的非列表数据
我对这意味着什么感到困惑?如果我从代码中删除many=True
,我会得到错误
AttributeError at /api/quest/1/2/
Got AttributeError when attempting to get a value for field `text` on serializer `EmbeddedAnswerSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `RelatedManager` instance.
Original exception text was: 'RelatedManager' object has no attribute 'text'.
有人能解释一下
many=True
做了什么以及source
字段做了什么吗?可能不是最好的解释,有人可以添加更多细节,但简短地告诉序列化程序它将使用对象列表来序列化过程。换句话说,它只是一个触发器,允许您指定是同时序列化多个对象,还是只序列化单个对象
另一侧的source
指定应使用当前序列化程序的字段序列化对象的哪个属性
实际上,这一行
answers = EmbeddedAnswerSerializer(many=True, source='answer_set')
表示您希望使用
EmbeddedAnswerSerializer
序列化Question
对象的answer\u集
属性。由于answer\u set
是对象列表,您应该添加many=True
作为参数,以使序列化程序意识到它将使用对象列表而不是单个对象。通过@neverboner添加到上面的答案中
多=真
many=True
表示有多个对象(一个iterable)被传递到序列化程序。依次传递此字段将触发BaseSerializer
中的many_init
,以自动创建ListSerializer
实例
源代码片段:
def __new__(cls, *args, **kwargs):
# We override this method in order to automagically create
# `ListSerializer` classes instead when `many=True` is set.
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)
# self.source should default to being the same as the field name.
if self.source is None:
self.source = field_name
# self.source_attrs is a list of attributes that need to be looked up
# when serializing the instance, or populating the validated data.
if self.source == '*':
self.source_attrs = []
else:
self.source_attrs = self.source.split('.')
Source=“xyz”
这将告诉DRF哪个对象属性为字段提供值。默认假设是序列化程序上声明的字段名与提供值的对象实例上的字段相同。在不正确的情况下,source
允许您显式提供序列化程序将在其中查找值的对象实例。下面是对def绑定(self,field\u name,parent)
内部serializers.fields
的一个初步了解
源代码片段:
def __new__(cls, *args, **kwargs):
# We override this method in order to automagically create
# `ListSerializer` classes instead when `many=True` is set.
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)
# self.source should default to being the same as the field name.
if self.source is None:
self.source = field_name
# self.source_attrs is a list of attributes that need to be looked up
# when serializing the instance, or populating the validated data.
if self.source == '*':
self.source_attrs = []
else:
self.source_attrs = self.source.split('.')
最后,使用bind
中声明的source
和source\u attrs
获得如下值:
def get_attribute(self, instance):
"""
Given the *outgoing* object instance, return the primitive value
that should be used for this field.
"""
try:
return get_attribute(instance, self.source_attrs)
except (KeyError, AttributeError) as exc:
假设一个问题
可以有多个答案
,您的方法是正确的
问题似乎是您提供的源是RelatedManager
实例本身,而不是Answer
对象的查询集。我假设DRF能准确地解决这个问题,你能试着把它改成source='answer\u set.all'吗
answer\u set
是Django提供的默认RelatedManager
名称。在Django模型中使用相关的_名称来命名向后关系可能是明智的。这可以通过改变:
question = models.ForeignKey(Question,on_delete=models.PROTECT, related_name='answers')
似乎这仅适用于一对多关系如果存在一对一关系,则无需指定多和源字段,前提是序列化程序中使用的字段名称与模型中的字段名称相同。我说的对吗?假设一个问题可以有多个答案,你的方法是正确的。问题是,您假定的来源是经理,而不是答案的查询集。将其更改为
source='answer\u set.all'
。在django模型中,使用related\u name
命名向后关系可能是明智的。