Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 需要帮助了解序列化程序中的许多字段和源字段吗_Django_Django Rest Framework - Fatal编程技术网

Django 需要帮助了解序列化程序中的许多字段和源字段吗

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

我目前正在尝试熟悉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
和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
命名向后关系可能是明智的。