django - 如何确保用户只能访问自己创建的对象的 DetailView、Listview 和 UpdateView
问题描述
我创建了一个简单的应用程序,登录的用户可以在其中提交会议会话、查看提交结果、查看提交列表和编辑提交(他们不应访问其他用户的提交) . 我正在使用 django 的基于类的视图(CreateView、DetailView、ListView、UpdateView)。
但是,我正在为权限而苦苦挣扎。除了 updateview 之外的所有视图都可以工作,但是如果我使用未登录的用户名直接输入 url,我可以看到他们的提交。
我还怀疑权限与我无法让 updateview 工作的原因相同。
我错过了什么?有没有更好的方法来避免在 URL 中使用用户名和 slug?我似乎找不到任何关于如何做这类事情的例子或提示。我是一个初学者,所以可能会在这里和那里错过一些对基础知识的理解。
我试图了解 User 模型是如何工作的,因为我确实设法找到了一种以受保护的方式创建、查看和编辑用户详细信息的方法。虽然我依赖那里的功能视图,但似乎无法将该方法应用于提交应用程序。
模型.py
class Hsession(models.Model):
submitter = models.ForeignKey(User, related_name="submittersessions", on_delete=models.CASCADE)
submission_date = models.DateTimeField(auto_now=True)
session_title = models.CharField("session title", max_length=40, default='')
session_description = models.TextField("session description", max_length=350, default='')
slug = models.SlugField(allow_unicode=True, unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.session_title)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("submission:detail-single", kwargs={"username": self.submitter.username, "slug": self.slug})
网址:
urlpatterns = [
path("", views.CreateSubmission.as_view(), name="create"),
path("by/<username>/<slug>",views.SubmissionDetail.as_view(),name="detail-single"),
path("by/<slug>/edit",views.EditSubmission.as_view(), name="edit"),
path("by/<username>/",views.SubmissionList.as_view(), name="list"),
]
视图.py
class CreateSubmission(LoginRequiredMixin, generic.CreateView):
fields = ('session_title', 'session_description', 'subject_category')
model = models.Hsession
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.submitter = self.request.user
self.object.save()
return super().form_valid(form)
class SubmissionList(LoginRequiredMixin, generic.ListView):
model = models.Hsession
template_name = "submission/user_hsession_list.html"
def get_queryset(self):
try:
self.hsession_submitter = User.objects.prefetch_related("submittersessions").get(
username__iexact=self.kwargs.get("username")
)
except User.DoesNotExist:
raise Http404
else:
return self.hsession_submitter.submittersessions.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["hsession_submitter"] = self.hsession_submitter
return context
class SubmissionDetail(LoginRequiredMixin, generic.DetailView):
model = models.Hsession
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(
submitter__username__iexact=self.kwargs.get("username")
)
class EditSubmission(LoginRequiredMixin, generic.UpdateView):
model = models.Hsession
fields = ('session_title', 'session_description', 'subject_category')
template_name = 'submission/hsession_update.html'
success_url = 'submission/hsession_detail.html'
表格.py
class UserSubmissionForm(ModelForm):
class Meta:
model = Hsession
fields = ['session_title','session_description', 'subject_category']
class EditSubmissionForm(ModelForm):
class Meta:
model = Hsession
fields = ['session_title','session_description', 'subject_category']
解决方案
你应该UserPassesTestMixin
这样使用
from django.contrib.auth.mixins import UserPassesTestMixin
class EditSubmission(UserPassesTestMixin,LoginRequiredMixin, generic.UpdateView):
model = models.Hsession
fields = ('session_title', 'session_description', 'subject_category')
template_name = 'submission/hsession_update.html'
success_url = 'submission/hsession_detail.html'
def test_func(self):
//should return true if he have access
if self.request.user.is_authenticated:
slug = self.kwargs['slug']
obj = self.model.objects.get(slug=slug)
login_user = self.request.user
return login_user.pk == obj.submitter.pk
else:
return False
推荐阅读
- c++ - 无法更新作为列表中节点一部分的对象内的值
- python - tf.estimator.EvalSpec 中参数“throttle_secs”的行为,用于 tf.estimator.train_and_evaluate
- javascript - 同步函数中promise的返回值
- php - mysql根据select更新多行,根据当前行值
- ruby-on-rails - 编写传递额外信息的 Cucumber 测试
- html - bootstrap navbar-brand 将链接文本与 svg 对齐
- php - bootstrap 和 codeIgniter 数据显示在表格中
- python - 使用 Python 比较 JSON 中的值
- c# - MailKit - 将信件移至垃圾箱
- c# - C#当添加一个引用的程序集时,它会抛出一个找不到文件的错误