Python Django rest框架序列化多对多字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33182092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:58:12  来源:igfitidea点击:

Django rest framework serializing many to many field

pythondjangodjango-modelsdjango-rest-frameworkdjango-serializer

提问by kengcc

How do I serialize a many-to-many field into list of something, and return them through rest framework? In my example below, I try to return the post together with a list of tags associated with it.

如何将多对多字段序列化为列表,并通过rest框架返回它们?在下面的示例中,我尝试将帖子连同与其关联的标签列表一起返回。

models.py

模型.py

class post(models.Model):
    tag = models.ManyToManyField(Tag)
    text = models.CharField(max_length=100)

serializers.py

序列化程序.py

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ("text", "tag"??)

views.py

视图.py

class PostViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

采纳答案by Brian

You will need a TagSerializer, whose class Metahas model = Tag. After TagSerializeris created, modify the PostSerializerwith many=Truefor a ManyToManyFieldrelation:

您将需要一个TagSerializer,其class Meta具有model = Tag。之后TagSerializer被创建,修改PostSerializermany=True一个ManyToManyField关系:

class PostSerializer(serializers.ModelSerializer):
    tag = TagSerializer(read_only=True, many=True)

    class Meta:
        model = Post
        fields = (tag, text,)

Answer is for DRF 3

答案适用于 DRF 3

回答by Windsooon

This works for me.

这对我有用。

tag = TagSerializer(source="tag", read_only=True, many=True)

回答by yiyo

In the serializer on initmethod you can pass the queryset to the field and rest_framework valide the ids on that queryset

init方法的序列化程序中,您可以将查询集传递给字段,然后 rest_framework 验证该查询集上的 id

1) first extend your serializer from serializers.ModelSerializer

1)首先从 serializers.ModelSerializer 扩展你的序列化器

class YourSerializer(serializers.ModelSerializer):

2) include the field on the meta class

2) 在元类中包含字段

class YourSerializer(serializers.ModelSerializer):
  class Meta:
        fields = (..., 'your_field',)

3) in the init method:

3)在init方法中:

def __init__(self, *args, **kwargs):
    super(YourSerializer, self).__init__(*args, **kwargs)
    self.fields['your_field].queryset = <the queryset of your field>

You can limit the queryset for that field under any argument using filter or exclude like normally you do. In case that you want include all just use .objects.all()

您可以像往常一样使用 filter 或 exclude 限制任何参数下该字段的查询集。如果您想包含所有内容,请使用 .objects.all()

回答by user5299374

Django 2.0

Django 2.0

For many to many field, if you want specific one:

对于多对多领域,如果你想要特定的一个:

class QuestionSerializer(serializers.ModelSerializer):

    topics_list = serializers.SerializerMethodField()

    def get_topics_list(self, instance):
        names = []
        a = instance.topics.get_queryset()
        for i in a:
            names.append(i.desc)
        return names
    class Meta:
        model = Question
        fields = ('topics_list',)

回答by Jesus Almaral - Hackaprende

This is what I did, let′s suppose a Book can have more than one author and an Author can have more than one book: On Model:

这就是我所做的,假设一本书可以有多个作者,而一个作者可以有多个书: On Model:

class Author(models.Model):
    name = models.CharField(max_length=100, default="")
    last_name = models.IntegerField(default=0)

class Book(models.Model):
    authors = models.ManyToManyField(Author, related_name="book_list", blank=True)
    name = models.CharField(max_length=100, default="")
    published = models.BooleanField(default=True)

On Serializers:

在序列化器上:

class BookSerializer(serializers.ModelSerializer):
    authors = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), many=True)

    class Meta:
        model = Book
        fields = ('id', 'name', 'published', 'authors')


class AuthorSerializer(serializers.ModelSerializer):
    book_list = BookSerializer(many=True, read_only=True)

    class Meta:
        model = Author
        fields = ('id', 'name', 'last_name', 'book_list')

回答by candyfoxxx

Adding to @Brian's answer "tags": [{"name": "tag1"}] can be simplified to "tags": ["tag1", "tag2",...] in this way:

添加到@Brian 的答案 "tags": [{"name": "tag1"}] 可以简化为 "tags": ["tag1", "tag2",...] 以这种方式:

class PostSerializer(serializers.ModelSerializer):
    tag = TagSerializer(read_only=True, many=True)

    class Meta:
        ...

class TagSerializer(serializers.RelatedField):

     def to_representation(self, value):
         return value.name

     class Meta:
        model = Tag

More info here: https://www.django-rest-framework.org/api-guide/relations/#custom-relational-fields

更多信息:https: //www.django-rest-framework.org/api-guide/relations/#custom-relational-fields

回答by mohamed ali Mimouni

The default ModelSerializeruses primary keys for relationships. However, you can easily generate nested representations using the Metadepthattribute:

默认ModelSerializer使用主键作为关系。但是,您可以使用以下Metadepth属性轻松生成嵌套表示:

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ("text", "tag")
        depth = 1 

As mentioned in the documentation:

文档中所述:

The depthoption should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.

depth选项应设置为整数值,该值指示在恢复为平面表示之前应遍历的关系深度。