Home > Back-end >  Serializer with Foreign Keys, how to handle frontend view and backend queries?
Serializer with Foreign Keys, how to handle frontend view and backend queries?

Time:10-02

I'm new to Django Rest Framework and I'm trying to understand how to handle the serializer both for frontend view and backend queries.

I'll try to explain it better. I have these serializers:

    class AuthorSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('username', )
    
    
    class CategorySerializer(serializers.ModelSerializer):
        class Meta:
            model = Category
            fields = ('name', )
    
    
    class PostSerializer(serializers.ModelSerializer):
        author = AuthorSerializer(many=False, read_only=True)
        category = CategorySerializer(many=False, read_only=True)    
    
        class Meta:
            model = Post
            fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')

When I retrieve a post it looks like this:

    {
        "category": {
            "name": "django"
        },
        "id": 2,
        "title": "Learn Django - Class-Based Permission Checks",
        "image": "http://localhost:8000/media/posts/laptop_SWf7fkV.jpg",
        "slug": "learn-django-class-based-permission-checks",
        "author": {
            "username": "admin"
        },
        "excerpt": "Sed ut quam quis tellus pulvinar maximus. Nulla sodales, felis sed interdum lobortis, mi turpis dictum libero, at imperdiet justo eros a sem. Etiam et laoreet eros, quis gravida neque. Pellentesque vitae sollicitudin erat. Donec faucibus quis diam vitae pellentesque. Proin interdum justo vitae magna pretium egestas. Morbi tortor tortor, vestibulum a sagittis non, vestibulum at dolor. Etiam vulputate bibendum elit, id fermentum dui laoreet a. In ac porttitor lectus, eget tempor massa. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur imperdiet eu ipsum sit amet aliquet. Integer pharetra metus purus, a porttitor nunc bibendum eu. Aenean magna tellus, consectetur nec est vitae, placerat dapibus neque. Cras et venenatis mauris.",
        "content": "Sed ut quam quis tellus pulvinar maximus. Nulla sodales, felis sed interdum lobortis, mi turpis dictum libero, at imperdiet justo eros a sem. Etiam et laoreet eros, quis gravida neque. Pellentesque vitae sollicitudin erat. Donec faucibus quis diam vitae pellentesque. Proin interdum justo vitae magna pretium egestas. Morbi tortor tortor, vestibulum a sagittis non, vestibulum at dolor. Etiam vulputate bibendum elit, id fermentum dui laoreet a. In ac porttitor lectus, eget tempor massa. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur imperdiet eu ipsum sit amet aliquet. Integer pharetra metus purus, a porttitor nunc bibendum eu. Aenean magna tellus, consectetur nec est vitae, placerat dapibus neque. Cras et venenatis mauris.",
        "status": "published",
        "published": "2021-09-30T16:37:05.233816Z"
    }

And for displaying the data on a frontend interface is perfect, I can easily get the category name and author name. The problem is when I have to pass these data to a "create new post" endpoint. The DB is expecting a number for author and category, but this way it's getting an object and it doesn't work of course.

If I change the PostSerializer serializer to this:

 class PostSerializer(serializers.ModelSerializer):   
    
        class Meta:
            model = Post
            fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')

it works, but then I have problems with the frontend.

How should I do this? Should I have two different serializers, one for handling frontend data and one for backend? Or is there a way to handle it?

Thanks!

EDIT: I'm gonna add the ModelViewSet responsible for the create post endpoint. It might be useful.

class ManagePosts(viewsets.ModelViewSet):
    serializer_class = PostSerializer
    parser_classes = [MultiPartParser, FormParser]

    def get_object(self, queryset=None, **kwargs):
        item = self.kwargs.get('pk')
        return get_object_or_404(Post, slug=item)

    # Define Custom Queryset
    def get_queryset(self):        
        return Post.objects.all()

CodePudding user response:

You can add 'id' field in the list of fields displayed by foreign key

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username')


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('id', 'name')

# Others serializers 

CodePudding user response:

I don't think this is the best way to do this, but it works. I used one serializer for backend calls and one serializer for frontend calls. This way I always have the correct data.

class PostSerializer(serializers.ModelSerializer):
class Meta:
    model = Post
    fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')


class FrontendPostSerializer(serializers.ModelSerializer):
author = AuthorSerializer(many=False, read_only=True)
category = CategorySerializer(many=False, read_only=True)

class Meta:
    model = Post
    fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')

I'm sure there's a better way to do this, so if anyone knows it, please go ahead and show it.

  • Related