我正在尝试使用 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 节):
问题是,当我在 HTML 表单中使用
category = serializers.SerializerMethodField()
类别的下拉列表时,它会消失(第一张图片中的第 2 部分)。我如何才能同时包含第 1 部分和第 4 部分,以具有自定义类别响应和 HTML 表单中的类别下拉列表?
您可以简单地覆盖序列化器序列化方法并将类别值替换为“正确”的格式。
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