What is the easiest way to get custom serialized m

2019-08-30 23:26发布

问题:

I am looking for an easy way to subclass rest_framework.serializers.ModelSerializer from Django REST framework so that it serializes to a special dictionary for foreign key models fields with the name of the model class and the id value instead of just an integer / primary key. This should work for different models.

# models.py
class Author(models.Model):
    name = models.CharField(max_length=255)

class Book(models.Model):
    book_written_by = models.ForeignKey(Author)

class Song(models.Model):
    song_written_by = models.ForeignKey(Author)

# serializers.py
class CustomSerializer(serializers.ModelSerializer):
    # What to do here? #

class BookSerializer(CustomSerializer):
    class Meta:
        model = Book

class SongSerializer(CustomSerializer):
    class Meta:
        model = Song

I would like to get the following result:

kleist = Author.objects.create(name='Kleist')
some_book = Book.objects.create(author=kleist)
BookSerializer(some_book).data == {'id': 1, 'book_written_by': {'Author': 1}}  # Returns True

I tried to override get_related_field() and changed PrimaryKeyRelatedField to a CustomPrimaryKeyRelatedField and there I tried to override to_native() but I don't have access to the model field and its object itself but only to the pk value.

回答1:

What you need is certainly achievable, but it is really breaking convention so personally I'd vote against doing so. Nevertheless, a way to achieve what you need is to use a SerializerMethodField:

class BookSerializer(serializers.ModelSerializer):
    book_written_by = serializers.SerializerMethodField('get_author')

    class Meta:
        model = User

    def get_author(self, obj):
        return {'Author': obj.book_written_by.pk}

This would return the exact output you wanted. If you decide to stick with the conventions, I'd prefer an output like this:

{'id': 1, 'book_written_by': {'id': 1, 'name': 'somebody'}}

The following serializer would return that for you:

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ('id', 'name')

class BookSerializer(serializers.ModelSerializer):
    book_written_by = AuthorSerializer()