Django rest framework serializing many to many field

前端 未结 7 1371
旧时难觅i
旧时难觅i 2020-11-28 03:46

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

相关标签:
7条回答
  • 2020-11-28 04:09

    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:

    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')
    
    0 讨论(0)
  • 2020-11-28 04:12

    This works for me.

    tag = TagSerializer(source="tag", read_only=True, many=True)
    
    0 讨论(0)
  • 2020-11-28 04:17

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

    1) first extend your serializer from serializers.ModelSerializer

    class YourSerializer(serializers.ModelSerializer):
    

    2) include the field on the meta class

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

    3) in the init method:

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

    0 讨论(0)
  • 2020-11-28 04:18

    You will need a TagSerializer, whose class Meta has model = Tag. After TagSerializer is created, modify the PostSerializer with many=True for a ManyToManyField relation:

    class PostSerializer(serializers.ModelSerializer):
        tag = TagSerializer(read_only=True, many=True)
    
        class Meta:
            model = Post
            fields = ('tag', 'text',)
    

    Answer is for DRF 3

    0 讨论(0)
  • 2020-11-28 04:22

    The default ModelSerializer uses primary keys for relationships. However, you can easily generate nested representations using the Meta depth attribute:

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

    As mentioned in the documentation :

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

    0 讨论(0)
  • 2020-11-28 04:31

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

    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

    0 讨论(0)
提交回复
热议问题