需要帮助的串行理解许多和源领域(Need help understanding many and s

2019-09-28 16:59发布

我目前正在与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呢领域?

Answer 1:

通过@neverwalkaloner添加到上面的答案

许多=真

many=True信号有多于一个的对象(一个可迭代)被传递到串行器。 反过来传递这一领域将触发many_initBaseSerializer ,自动将创建一个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('.')

最后的值被得到利用如下sourcesource_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')


Answer 2:

也许不是最好的解释,有人可以添加更多的细节,但简单many=True告诉给序列化器,它将采取的对象列表serilizing proccess。 换句话说,它只是一个触发,使您可以指定将序列化,那么, 许多对象一次,或者只是单个对象。

source在另一侧上指定对象的属性应与当前串行的字段被序列化。

在实践中,这行

answers = EmbeddedAnswerSerializer(many=True, source='answer_set')

意味着你要序列answer_set的属性Question的对象与EmbeddedAnswerSerializer 。 由于answer_set 为对象的名单,你应该添加 many=True作为参数,使串行知道它会与对象而不是单个对象名单的工作。



文章来源: Need help understanding many and source fields in a serializer