Instead of Primary Key Send Different Field in Django REST Framework

前端 未结 5 1036
萌比男神i
萌比男神i 2020-12-30 07:27

serializers.py

class MovieSerializer(serializers.ModelSerializer):

    class Meta:
        model = Movie
        fields = [
            \'popular         


        
5条回答
  •  -上瘾入骨i
    2020-12-30 07:46

    Assuming that you used StringRelatedField in your MovieSerializer like this:

    class MovieSerializer(serializers.ModelSerializer):
        genre = serializers.StringRelatedField(many=True)
    
        class Meta:
            model = Movie
            fields = [
                'popularity',
                'director',
                'genre',
                'imdb_score',
                'name',
            ]
    

    the result would look like this when retrieving a list of movies:

    [
        {
            "popularity": 83.0,
            "director": "Victor Fleming",
            "genre": [
                 "Adventure",
                 "Family",
                 "Fantasy",
                 "Musical"
            ],
            "imdb_score": 8.3,
            "name": "The Wizard of Oz"
        }
    ]
    

    But if you want to create a new movie, then it won't work because StringRelatedField is read-only.

    You can however create your custom related field.

    This is the complete serializers.py:

    from rest_framework import serializers
    
    from .models import Genre, Movie
    
    
    class GenreRelatedField(serializers.RelatedField):
        def display_value(self, instance):
            return instance
    
        def to_representation(self, value):
            return str(value)
    
        def to_internal_value(self, data):
            return Genre.objects.get(name=data)
    
    
    class MovieSerializer(serializers.ModelSerializer):
        genre = GenreRelatedField(
            queryset=Genre.objects.all(),
            many=True
        )
    
        class Meta:
            model = Movie
            fields = (
                'popularity',  
                'director',     
                'genre',                         
                'imdb_score',
                'name',
            )   
    

    This is a simple example that can be highly customized in many ways.

    The method display_value defines how the object Genre is displayed, for example in the form. Here it just returns the object Genre i.e. the output of __str__.

    The method to_representation defines how the object Genre is displayed in the output (JSON or XML). It's very similar to the previous method, but here we explicitly have to convert Genre to string. Certainly you can create a more complex output according to your requirements.

    The method to_internal_value solves your actual problem by getting an object Genre for the given value. If you have a more complex method to_representation here you would need expanded logics to get the appropriate object.

    Using this approach you can post a JSON in your desired form, specifying the genre names instead of their ids.

    I hope this example helps other people too.

提交回复
热议问题