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

Django类视图Todo应用:用户任务未隔离问题求助

Django Todo应用用户任务隔离问题排查与修复

核心问题定位

你的代码存在三个关键问题,导致任务未按用户隔离:

  1. 任务列表视图过滤逻辑无效:TaskList在get_context_data中过滤了当前用户的任务,但模板渲染时仍使用未过滤的原始查询集object_list,而非过滤后的tasks变量。
  2. 详情/更新/删除视图无用户限制:TaskDetail、TaskUpdate、DeleteTask未限制只能访问当前用户的任务,任何登录用户可通过URL直接操作他人任务。
  3. 任务创建表单暴露敏感字段:TaskCreate的表单包含user选择框,虽在form_valid中自动设置当前用户,但存在被篡改的风险,且不符合业务逻辑。

修复方案

1. 修复TaskList视图的查询集过滤(推荐做法)

重写get_queryset方法直接返回当前用户的任务,确保模板使用的object_list或tasks都是过滤后的结果:

class TaskList(LoginRequiredMixin, ListView):
    model = Task
    context_object_name = 'tasks'

    def get_queryset(self):
        # 只返回当前登录用户的任务
        return super().get_queryset().filter(user=self.request.user)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['count'] = context['tasks'].filter(complete=False).count()
        return context

2. 为详情/更新/删除视图添加用户过滤

重写这三个视图的get_queryset方法,限制只能访问当前用户的任务:

class TaskDetail(LoginRequiredMixin, DetailView):
    model = Task
    context_object_name = 'task'
    template_name = 'todo_app/task.html'

    def get_queryset(self):
        return Task.objects.filter(user=self.request.user)


class TaskUpdate(LoginRequiredMixin, UpdateView):
    model = Task
    # 移除user字段,用户无需修改任务所属者
    fields = ['title', 'description', 'complete']
    success_url = reverse_lazy('tasks')

    def get_queryset(self):
        return Task.objects.filter(user=self.request.user)


class DeleteTask(LoginRequiredMixin, DeleteView):
    model = Task
    context_object_name = 'task'
    success_url = reverse_lazy('tasks')

    def get_queryset(self):
        return Task.objects.filter(user=self.request.user)

3. 优化TaskCreate视图,隐藏user字段

移除表单中的user字段,避免用户手动选择:

class TaskCreate(LoginRequiredMixin, CreateView):
    model = Task
    # 只保留用户需要填写的字段
    fields = ['title', 'description']
    success_url = reverse_lazy('tasks')

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

4. 模板优化(可选)

在task_list.html中,将循环变量从object_list改为tasks,与视图的context_object_name保持一致:

{% for task in tasks %}
<tr>
    <td>{{ task.title }}</td>
    <td><a href="{% url 'task' task.id %}">View</a></td>
    <td><a href="{% url 'update_task' task.id %}">Edit</a></td>
    <td><a href="{% url 'delete_task' task.id %}">Delete</a></td>
</tr>
{% empty %}
<h3>No items in list</h3>
{% endfor %}

验证步骤

  1. 重启Django服务,登录第一个用户创建任务后退出。
  2. 登录第二个用户,此时任务列表应为空,仅能看到自己创建的任务。
  3. 尝试直接访问第一个用户任务的详情/更新/删除URL,会返回404错误,确保任务无法被其他用户访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:45:55