You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 10:51:02