需要帮助了解序列化器中的许多字段和源字段 [英] Need help understanding many and source fields in a serializer

查看:144
本文介绍了需要帮助了解序列化器中的许多字段和源字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前正在尝试使自己熟悉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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆