Django Rest Framework 同一模型的两个序列化器

Django Rest Framework two Serializers for the same Model

我很确定有更好的方法来做到这一点:

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

我在 atm 上做的是使用 FrontendPostSerializer 在前端显示数据,例如在 table 中显示类别名称、作者姓名和标题。相反,我使用 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')

但是,例如,当我尝试创建一个新的 post 时它不起作用,因为类别和作者不是数字,而是 objects.

我也将放在这里 create.js 我在我的 React 前端中处理创建提交。

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

有没有更好的方法?我确定我只能使用一个序列化器,但我还不确定如何使用。

谢谢!

其实是的。您可以使用 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"
}