我目前正在与DRF熟悉自己,同时通过教程去使用这些序列化
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
和源=“answer_set”? 我从文档阅读了有关以下many=True
您也仍然可以使用很多= TRUE参数串类。 值得一提的是许多= 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
呢领域?
通过@neverwalkaloner添加到上面的答案
许多=真
many=True
信号有多于一个的对象(一个可迭代)被传递到串行器。 反过来传递这一领域将触发many_init
内BaseSerializer
,自动将创建一个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)
来源= “XYZ”
这告诉DRF哪个对象属性的字段提供值。 默认的假设是,在串行声明的字段名称相同的是提供值的对象实例字段。 在情况下,这是不正确的, source
可以让你明确供应对象的实例,其中串行器将寻找价值。 这里有一个不期而遇的def bind(self, field_name, parent)
内serializers.fields
下这个现象发生
源代码片段:
# 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
和source_attrs
中声明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:
假设一个Question
可以有多个Answers
,你的做法是正确的。
这个问题似乎是,你提供的来源是RelatedManager
实例本身,而不是的queryset的Answer
对象。 我以为DRF准确地解决了这个,你可以尝试将其更改为源=“answer_set.all”。
answer_set
是默认RelatedManager
Django在给定的名称。 这可能是明智的名称Django的模型中使用related_name你落后的关系。 这可以通过改变来实现:
question = models.ForeignKey(Question,on_delete=models.PROTECT, related_name='answers')
也许不是最好的解释,有人可以添加更多的细节,但简单many=True
告诉给序列化器,它将采取的对象列表serilizing proccess。 换句话说,它只是一个触发,使您可以指定将序列化,那么, 许多对象一次,或者只是单个对象。
source
在另一侧上指定对象的属性应与当前串行的字段被序列化。
在实践中,这行
answers = EmbeddedAnswerSerializer(many=True, source='answer_set')
意味着你要序列answer_set
的属性Question
的对象与EmbeddedAnswerSerializer
。 由于answer_set
为对象的名单,你应该添加 many=True
作为参数,使串行知道它会与对象而不是单个对象名单的工作。