需要帮助了解序列化器中的许多字段和源字段 [英] Need help understanding many and source fields in a serializer
问题描述
我当前正在尝试使自己熟悉DRF,并在学习教程时使用了这些序列化器
I am currently trying to familiarize myself with DRF and while going through a tutorial these serializers were used
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)
我的问题在问题序列化器的语句中
My question is in the statement in the Question serializer
answers = EmbeddedAnswerSerializer(many=True,source='answer_set')
<$ c的目的是什么$ c>许多=真和source ='answer_set'吗?
我从文档中读取了有关 many = True
what is the purpose of many = True
and source='answer_set' ?
I read from the documentation the following regarding many=True
的以下内容您仍然可以对序列化程序类使用many = True参数。
值得注意的是,many = True参数透明地创建了
ListSerializer实例,从而允许列表和
非列表数据的验证逻辑在REST框架代码库中清晰地分开。
You can also still use the many=True argument to serializer classes. It's worth noting that many=True argument transparently creates a ListSerializer instance, allowing the validation logic for list and non-list data to be cleanly separated in the REST framework codebase.
我被这意味着什么感到困惑?如果我从代码中删除 many = True
,我会得到错误
I am confused by what that means ? If I remove many=True
from the code I get the error
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
字段的作用是什么?
Can anyone explain what many=True
does and what source
field does ?
推荐答案
@neverwalkaloner
Adding to the answer above by @neverwalkaloner
很多=真实
表示有多个对象(可迭代)传递给串行器。依次传递此字段会触发 BaseSerializer
中的 many_init
自动创建 ListSerializer
实例。
many=True
signals that there is more than one object (an iterable) being passed to the serializer. Passing this field in turn triggers the many_init
within BaseSerializer
to automagically create a ListSerializer
instance.
源代码段:
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)
Source = xyz
这告诉DRF哪个对象属性为该字段提供值。默认假设是在序列化器上声明的字段名称与提供值的对象实例上的字段相同。在不正确的情况下, source
允许您显式提供对象实例,序列化程序将在该对象实例中寻找该值。窥视 serializers.fields
内的 def绑定(自己,field_name,父对象)
Source = "xyz"
This tells DRF which object attribute supplies the value for the field. The default assumption is that the field name declared on the serializer is the same as the field on the object instance that supplies the value. In cases where this is not true, source
allows you to explicitly supply the object instance where the serializer will look for the value. Here's a peek into the def bind(self, field_name, parent)
inside serializers.fields
where this happens
源代码段:
# 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_attrs
:
Finally the value is gotten as follows using the source
and source_attrs
declared in bind
:
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:
假设一个问题
可以有多个答案
,您的方法是正确的。
Assuming a Question
can have multiple Answers
, your approach is correct.
问题似乎是您提供的源是 RelatedManager
实例本身,而不是答案
对象。我认为DRF可以正确解决此问题,您可以尝试将其更改为source = answer_set.all。
The problem appears to be that the source you supplied is the RelatedManager
instance itself, and not the queryset of Answer
objects. I assumed DRF resolves this accurately, can you try changing it to source='answer_set.all'.
answer_set
是Django给出的默认 RelatedManager
名称。在Django模型中使用related_name命名您的向后关系可能是明智的。这可以通过更改来实现:
answer_set
is the default RelatedManager
name given by Django. It might be wise to name your backward relationship using related_name in the Django model. This can be achieved by changing:
question = models.ForeignKey(Question,on_delete=models.PROTECT, related_name='answers')
这篇关于需要帮助了解序列化器中的许多字段和源字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!