当对字段使用自定义序列化程序时,为什么下拉字段在 Django Rest Framework 中消失?

问题描述 投票:0回答:1

我正在尝试使用 Django、DRF、ViewSet 和 Serializers 构建一个简单的博客。 我有一个主应用程序及其内部:

主\models.py:

from django.db import models
from django.contrib.auth.models import User

class TimeStampMixin(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Category(TimeStampMixin):
    name=models.CharField(max_length=255)
    parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)

    def __str__(self):
        return self.name

class PostStatus(models.Model):
    status = models.CharField(max_length=50)

    def __str__(self):
        return self.status
    
def get_draft_status():
    return PostStatus.objects.get_or_create(status='draft')[0].id

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    title = models.CharField(max_length=200)
    description = models.TextField()
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
    status = models.ForeignKey(PostStatus, on_delete=models.CASCADE, default=get_draft_status)

    def __str__(self):
        return self.title

class RelatedPost(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='related_posts')
    related_post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='related_to')

    def __str__(self):
        return f"{self.post.title} related to {self.related_post.title}"

主\序列化器.py:

from rest_framework import serializers, status
from rest_framework.response import Response
from .models import Post, RelatedPost, PostStatus, Category

class PostStatusSerializer(serializers.ModelSerializer):
    class Meta:
        model = PostStatus
        fields = '__all__'

class RelatedPostSerializer(serializers.ModelSerializer):
    class Meta:
        model = RelatedPost
        fields = '__all__'

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'

class PostSerializer(serializers.ModelSerializer):
    related_posts = serializers.SerializerMethodField()
    category = serializers.SerializerMethodField()

    class Meta:
        model = Post
        fields = '__all__'
    
    def get_related_posts(self, obj):
        related_posts = obj.related_posts.all()
        return [{'id': rp.related_post.id, 'title': rp.related_post.title} for rp in related_posts]
    
    def get_category(self, obj):
        if obj.category:
            return {'id': obj.category.id, 'name': obj.category.name}
        else:
            return {}

主要视图.py:

from .models import PostStatus, Post, RelatedPost, Category
from .serializers import PostSerializer, RelatedPostSerializer, PostStatusSerializer, CategorySerializer

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

class PostStatusViewSet(viewsets.ModelViewSet):
    queryset = PostStatus.objects.all()
    serializer_class = PostStatusSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

class RelatedPostViewSet(viewsets.ModelViewSet):
    queryset = RelatedPost.objects.all()
    serializer_class = RelatedPostSerializer

主\urls.py:

from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import PostStatusViewSet, PostViewSet, RelatedPostViewSet, CategoryViewSet

router = DefaultRouter()
router.register(r'category', CategoryViewSet, basename='category')
router.register(r'post-status', PostStatusViewSet, basename='post-status')
router.register(r'posts', PostViewSet, basename='post')
router.register(r'related-posts', RelatedPostViewSet, basename='related-post')

urlpatterns = [
    #path('admin/', admin.site.urls),
    path('', include(router.urls)),
]

问题:

我需要返回类别,包括它的 id 和名称 (GET /posts/1),所以我添加了

category = serializers.SerializerMethodField()

def get_category(self, obj):
    if obj.category:
        return {'id': obj.category.id, 'name': obj.category.name}
    else:
        return {}

进入

PostSerializer
并且它工作正常,正如您在此屏幕截图中看到的那样(第 1 节): enter image description here

在添加这些部分之前,它就像下面的截图: enter image description here

问题是,当我在 HTML 表单中使用

category = serializers.SerializerMethodField()
类别的下拉列表时,它会消失(第一张图片中的第 2 部分)。我如何才能同时包含第 1 部分和第 4 部分,以具有自定义类别响应和 HTML 表单中的类别下拉列表?

django django-rest-framework django-serializer
1个回答
0
投票

您可以简单地覆盖序列化器序列化方法并将类别值替换为“正确”的格式。

class PostSerializer(serializers.ModelSerializer):
    related_posts = serializers.SerializerMethodField()

    class Meta:
        ...

    def get_related_posts(self, obj):
        ...

    def to_representation(self, instance):
        new_cat_repr = {
            'id': instance.category.id, 
            'name': instance.category.name
        }
        representation = super().to_representation(instance)
        representation.pop("category")
        representation['category'] = new_cat_repr
        return representation
© www.soinside.com 2019 - 2024. All rights reserved.