我有一个网络应用程序,用户可以在其中登录并开始输入 ToDoList 的项目. base.html包裹在 is_authenticated 中检查以便用户在登录之前看不到应用程序中的任何内容。我正在做一些测试:
- 登录为
User2 - 添加一个新的
ToDoListItem - 重定向到
DetailView - 在本例中,URL =
http://localhost:8000/to_do_list/to_do_item/72
此时我意识到 DetailView 将允许 User2查看任何 ToDoListItem 的详细信息对于 User1只需输入现有的 pk进入:http://localhost:8000/to_do_list/to_do_item/<int:pk> .
urls.py 包括
path('to_do_item/<int:pk>', views.ToDoListItemDetail.as_view(), name='todo-item-detail'),
View .py
class ToDoListItemDetail(DetailView):
model = ToDoListItem
todolistitem_detail.html
{% extends 'base.html' %}
{% block content %}
<a href="/">Home</a>
<h1>DetailView for 'ToDoListItem' model</h1>
<p>TaskTitle: '{{ object.title }}'</p>
<p>Complete: '{{ object.is_complete }}'</p>
<p>User: '{{ object.user}}'</p>
{% endblock %}
防止这种情况发生的推荐方法是什么?我正在考虑以下几点:
- 我可以完全删除 DetailView 并定向到另一个只返回用户数据的 URL(使用类似
ToDoListItem.objects.filter(user=request.user)的东西) - 我可以检查登录用户的名称是否与拥有
ToDoListItem的用户的名称匹配. - 我可以覆盖
get_context_data()对于 DetailView 并在那里检查用户所有权(类似于 1,但在 DetailView 内) - >??? (我还不知道比上面更好的东西)
有没有办法限制用户在整个应用程序中只能看到他们自己的数据,而无需在每次需要时都执行此逻辑?
请您参考如下方法:
您也可以通过覆盖 get_queryset method [Django-doc] 在 DetailView 中过滤 :
from django.contrib.auth.mixins import LoginRequiredMixin
class ToDoListItemDetail(<b>LoginRequiredMixin,</b> DetailView):
model = ToDoListItem
def <b>get_queryset</b>(self, *args, **kwargs):
return super(ToDoListItemDetail, self).get_queryset(
*args, **kwargs
).filter(user=self.request.user)
Django 将在幕后始终调用 get_queryset(..)。默认情况下,此函数返回您为所有对象指定的 model 的查询集。但是您因此可以进一步过滤它。
Django 的 get_object method [Django-doc]然后将使用 id 和/或 slug 进一步过滤它,但是如果您已经过滤掉不属于 self.request.user 的元素,那么这只会导致查询不返回任何结果。
在这里添加 LoginRequiredMixin [Django-doc] 也是有意义的到你的类(class),因为万一用户没有登录,你可能想将 hem/her 重定向到登录屏幕。
