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


80

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

models.py

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

serializers.py

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

views.py

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

使用@Brian的帮助,我设法以以下形式列出项目:“标签”:[{“名称”:“ tag1”}]。我想将其简化为列表,是否可能:“ tags”:[“ tag1”,“ tag2”,...]
kengcc 2015年

2
在PostSerializers中使用`tag = serializers.SlugRelatedField(many = True,read_only = True,slug_field ='title',//要显示allow_null = True的标签的对象)
M. Dhaouadi

Answers:


102

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

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

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

答案是针对DRF 3


有用!!!:D任何想法如何将这个序列化器变成一个逗号分隔的列表?class TagSerializer(serializers.ModelSerializer):类Meta:模型=标签字段=(“名称”)
kengcc 2015年

1
现在,我得到:“ tags”:[{“ name”:“ tag1”}]我想将其简化为:“ tags”:[“ tag1”,“ tag2”,...]
kengcc

标签= serializers.ListField(source ='tag')。这将为您提供标签每个对象的str表示形式的列表
Sachin Gupta

2
如果您希望能够通过帖子更新标签怎么办?(例如,不是read_only)当我拿走read_only并尝试修补对标签字段的更新时,我得到了奇怪的行为(我收到有关已存在标签的错误)
getup8 2016年

1
read_only=True:一部分是这里解释django-rest-framework.org/api-guide/relations/...
帕维尔Vergeev

23

这就是我所做的,假设一本书可以有多个作者,而一个作者可以有多个本书:关于模型:

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)

在序列化器上:

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')

知道如何在创建Book实体时创建作者吗?
Kishan Mehta,

2
是的,它必须是在视图类完成,请如果你想有一个更详细的回答后一个问题
耶稣Almaral - Hackaprende

7

在@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

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


4

Django 2.0

对于多对多字段,如果要特定字段:

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',)

对于get_topics_list您可以简化为return list(instance.topics.values_list('desc', flat=True))
bdoubleu

2

这对我有用。

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

2

init方法的序列化器中,您可以将queryset传递给字段,并且rest_framework验证该queryset上的ID

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

class YourSerializer(serializers.ModelSerializer):

2)在meta类上包含字段

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

3)在init方法中:

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

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


1

默认ModelSerializer使用关系的主键。但是,您可以使用Meta depth属性轻松生成嵌套表示:

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

文档中所述:

depth选项应设置为一个整数值,该值指示在还原为平面表示形式之前应遍历的关系的深度。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.