DRF视图返回空JSON,无法获取对应用户外键关联的博客数据
问题根因
- 序列化器所有字段配置了
write_only=True:该属性指定字段仅用于反序列化(写入数据)场景,序列化输出数据时会直接跳过所有字段,导致返回空对象 - Blog模型缩进错误:当前Blog定义在CustomUser类内部,属于嵌套类,Django不会将其识别为独立的数据库模型,数据读写逻辑存在异常
- 视图层多余手动序列化:DRF的
Response类会自动完成数据到JSON的渲染,手动调用JSONRenderer会生成字符串格式的JSON内容,再被Response二次封装后格式异常
修复方案
1. 修正模型定义
把Blog类移出CustomUser类,保持平级摆放:
# models.py from django.db import models from django.utils import timezone from datetime import datetime from .validators import validate_allfile_extension from django.contrib.auth.models import AbstractUser CHOICE_GENDER = (('Male', 1), ('Female', 2), ('other', 3)) class CustomUser(AbstractUser): gender = models.TextField(choices=CHOICE_GENDER, null=True) birth_date = models.DateField(null=True, blank=True) # 移出到CustomUser类外,作为独立模型 class Blog(models.Model): title = models.TextField(max_length = 50) author = models.TextField(max_length = 50) description = models.TextField() date = models.DateField(auto_now=True) time = models.DateTimeField(default=datetime.now) image = models.ImageField(null=True, verbose_name="", validators=[validate_allfile_extension]) user = models.ForeignKey(CustomUser, on_delete=models.CASCADE) def __str__(self): return self.title
2. 拆分序列化器
分开定义新增和查询场景的序列化器,避免write_only影响返回结果:
# serializers.py from rest_framework import serializers from .models import Blog # 用于新增博客的序列化器,保留write_only配置 class AddBlogSerializer(serializers.ModelSerializer): title = serializers.CharField(max_length=128, write_only=True, required=True, error_messages={'blank': "Please provide title"} ) author = serializers.CharField(max_length=128, write_only=True, required=True, error_messages={'blank': "Please provide author"}) description = serializers.CharField(max_length=128, write_only=True, required=True, error_messages={'blank': "Please provide description"}) image = serializers.FileField(write_only=True, required=True, error_messages={'invalid': "Please upload image, video or audio file"}) class Meta: model = Blog fields = ["title","author","description","image"] def create(self, validated_data): # 新增时自动注入当前登录用户,不用前端传user_id validated_data['user'] = self.context['request'].user return super().create(validated_data) # 用于查询博客的序列化器,不配置write_only class BlogSerializer(serializers.ModelSerializer): class Meta: model = Blog fields = ["id","title","author","description","date","image"]
3. 修正视图逻辑
GET请求使用查询专用序列化器,去掉手动JSON渲染逻辑:
# views.py from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from .models import Blog from .serializers import AddBlogSerializer, BlogSerializer @api_view(['GET', 'POST']) @authentication_classes([SessionAuthentication, BasicAuthentication]) @permission_classes([IsAuthenticated]) def blog(request): if request.method == 'GET': blogs_by_user = Blog.objects.filter(user=request.user) # 使用查询专用序列化器 serializer = BlogSerializer(blogs_by_user, many=True) # 直接返回serializer.data,DRF会自动完成JSON渲染 return Response(serializer.data, status=200) elif request.method == 'POST': serializer = AddBlogSerializer(data=request.data, context={"request": request}) if serializer.is_valid(): serializer.save() return Response({"status":"success"}, status=201) return Response(serializer.errors, status=400)
内容的提问来源于stack exchange,提问作者English Voice Quotes
相关产品推荐
相关产品推荐

