Django休息框架序列化很多到很多领域

时间:2015-10-17 02:24:27

标签: python django django-models django-rest-framework django-serializer

如何将多对多字段序列化为某些列表,并通过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

7 个答案:

答案 0 :(得分:54)

您需要TagSerializer,其class Metamodel = Tag。创建TagSerializer后,使用PostSerializer修改many=True以获得ManyToManyField关系:

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

    class Meta:
        ...

Answer is for DRF 3

答案 1 :(得分:6)

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

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

答案 2 :(得分:3)

添加到@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

答案 3 :(得分:2)

init 方法的序列化程序中,您可以将查询集传递给字段,rest_framework将该查询集上的ID保存为

1)首先从serializers.ModelSerializer

扩展序列化程序
class YourSerializer(serializers.ModelSerializer):

2)在元类

中包含该字段
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>

您可以使用过滤器或排除限制任何参数下该字段的查询集,就像通常那样。如果你想要包括所有只是使用.objects.all()

答案 4 :(得分:2)

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

答案 5 :(得分:1)

这适合我。

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

答案 6 :(得分:1)

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

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

documentation中所述:

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