Home > Back-end >  Django Rest Framework two Serializers for the same Model
Django Rest Framework two Serializers for the same Model

Time:10-02

I'm pretty sure there's a better way to do this:

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

PostSerializer is gonna look like this

    {
        "category": 1,
        "id": 45,
        "title": "Lorem Ipsum - Lorem ipsum dolor sit amet consectetur",
        "image": "http://localhost:8000/media/posts/car_SxXcUTV.jpg",
        "slug": "lorem-ipsum-lorem-ipsum-dolor-sit-amet-consectetur",
        "author": 4,
        "excerpt": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
        "content": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
        "status": "published",
        "published": "2021-10-01T14:46:34.872576Z"
    }

FrontendPostSerializer is gonna look like this

{
        "category": {
            "name": "django"
        },
        "id": 45,
        "title": "Lorem Ipsum - Lorem ipsum dolor sit amet consectetur",
        "image": "http://localhost:8000/media/posts/car_SxXcUTV.jpg",
        "slug": "lorem-ipsum-lorem-ipsum-dolor-sit-amet-consectetur",
        "author": {
            "username": "luigi.verdi"
        },
        "excerpt": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
        "content": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
        "status": "published",
        "published": "2021-10-01T14:46:34.872576Z"
    }

What I'm doing atm is using FrontendPostSerializer for showing data in the frontend, for example in a table with category name, author name and title. Instead, I'm using PostSerializer for the backend CRUD.

These are the viewsets I'm using in the views.py

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

class FrontendPosts(viewsets.ModelViewSet):
    serializer_class = FrontendPostSerializer

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

I already tried to use only one serializer, I had this:

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

but, for example, when I try to create a new post it doesn't work, because category and author are not numbers, but objects.

I'm also gonna put here create.js I have in my React frontend that handles the create submit.

    const handleSubmit = (e) => {
        e.preventDefault();
        let formData = new FormData();
        formData.append('category', 1);
        formData.append('title', postData.title);
        formData.append('slug', postData.slug);
        formData.append('author', userInfo.id);
        formData.append('excerpt', postData.excerpt);
        formData.append('content', postData.content);
        if(postImage.image !== null) {
            formData.append('image', postImage.image);
        } 
        axiosInstance.post('', formData);
        history.push({
            pathname: '/admin/',
        });
        window.location.reload();
    };

Is there a better way? I'm sure I can use only one serializer, but I'm not sure how yet.

Thanks!

CodePudding user response:

Is there any specific reason to use one serializer for you? It is common to use WriteSerializer and ReadSerializer for the same object.

CodePudding user response:

Actually yes. You can add specific fields you want by using the source attribute. Example:

class PostSerializer(serializers.ModelSerializer):
   authorUserName = serializers.CharField(read_only=true, source="author.username")
   categoryName = serializers.CharField(read_only=true, source="category.name"

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

         # Remember add the field that are created

And when you try to get you should get the result like this:

{
    "categoryName": "django",
    "category": 1,
    "id": 45,
    "title": "Lorem Ipsum - Lorem ipsum dolor sit amet consectetur",
    "image": "http://localhost:8000/media/posts/car_SxXcUTV.jpg",
    "slug": "lorem-ipsum-lorem-ipsum-dolor-sit-amet-consectetur",
    "authorName": "luigi.verdi",
    "author": 4,
    "excerpt": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
    "content": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
    "status": "published",
    "published": "2021-10-01T14:46:34.872576Z"
}
  • Related