Django Rest Framework два сериализатора для одной модели

Я уверен, что есть лучший способ сделать это:

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 будет выглядеть так

    {
        "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 будет выглядеть так

{
        "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"
    }

В настоящее время я использую FrontendPostSerializer для отображения данных во фронтенде, например, в таблице с названием категории, именем автора и названием. Вместо этого я использую PostSerializer для CRUD бэкенда.

Вот наборы представлений, которые я использую в 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()

Я уже пытался использовать только один сериализатор, у меня получилось следующее:

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

но, например, когда я пытаюсь создать новый пост, это не работает, потому что категория и автор - это не числа, а объекты.

Я также собираюсь поместить сюда create.js У меня есть в моем React фронтенд, который обрабатывает 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();
    };

Есть ли лучший способ? Я уверен, что могу использовать только один сериализатор, но пока не уверен как.

Спасибо!

Есть ли какая-то конкретная причина использовать один сериализатор? Обычно принято использовать WriteSerializer и ReadSerializer для одного и того же объекта.

На самом деле да. Вы можете добавить определенные поля, которые вам нужны, используя атрибут source. Пример:

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

И когда вы попытаетесь получить, вы должны получить результат, подобный этому:

{
    "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"
}
Вернуться на верх