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

Django按author过滤条目报错Field 'id' expected a number 求助

问题根源

报错核心原因是index视图里author = DiaryEntry.author拿到的不是实际用户对象,是模型层的外键字段描述符(也就是报错信息里提到的ForwardManyToOneDescriptor对象)。ORM执行filter时要求外键参数传实际的用户实例/用户ID,传入字段描述符自然会触发类型不匹配错误。
另外现有代码还有两个隐藏问题:一是详情视图没做权限校验,用户只要知道条目ID就能查看其他人的日记,存在越权风险;二是所有和用户数据相关的视图没加登录限制,未登录状态访问会触发额外报错。

修复方案

1. 修正首页视图过滤逻辑

从请求对象request中获取当前登录用户作为过滤条件,同时加上登录校验:

# 先导入登录校验装饰器
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from .models import DiaryEntry
from django.views import generic
from django.views.generic.edit import CreateView
# 导入类视图用的登录校验mixin
from django.contrib.auth.mixins import LoginRequiredMixin

@login_required
def index(request):
    """View function for MyDiary."""
    # 直接用当前登录用户作为过滤条件
    diary_entry = DiaryEntry.objects.filter(author=request.user).order_by('-created_on')
    context = {
         "diary_entry": diary_entry,
    }
    return render(request, 'diary_index.html', context=context)

2. 修复详情视图的越权漏洞

你原来写的get_data是不存在的方法,Django通用视图的上下文获取方法是get_context_data,这里直接重写查询集限制只能访问自己的条目,同时加上登录校验:

class EntryDetailView(LoginRequiredMixin, generic.DetailView):
    model = DiaryEntry
    def get_queryset(self):
        # 强制查询范围限定为当前用户自己创建的条目
        return super().get_queryset().filter(author=self.request.user)

3. 补全创建视图的登录限制

给创建视图加上登录校验mixin,避免未登录用户访问报错:

class EntryCreate(LoginRequiredMixin, CreateView):
    model = DiaryEntry
    fields = ['title', 'content']
    def form_valid(self, form):
       form.instance.author = self.request.user
       return super().form_valid(form)
配置注意

记得在项目settings.py中补充两个配置:

  • LOGIN_URL:填写你的登录页路由名,未登录用户访问受限页面时会自动跳转到这里
  • LOGIN_REDIRECT_URL:填写日记首页路由名,用户登录成功后默认跳转到日记页

补充说明:DiaryEntry.author是定义在模型类上的字段引用,只有通过请求上下文拿到的request.user才是当前访问者对应的真实用户实例,传入过滤条件才能正确匹配数据库中关联的作者记录。

内容的提问来源于stack exchange,提问作者AllyZ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:51:19