【问题标题】:How to make sure users only get to DetailView, Listview and UpdateView their own created objects如何确保用户只能访问自己创建的对象的 DetailView、Listview 和 UpdateView
【发布时间】:2019-05-06 12:47:09
【问题描述】:

我创建了一个简单的应用程序,登录用户可以在其中提交会议会话、查看提交结果、查看提交内容列表以及编辑提交内容(他们不应访问其他用户'提交)。我正在使用 django 的基于类的视图(CreateView、DetailView、ListView、UpdateView)。

但是,我正在为权限而苦苦挣扎。除了 updateview 之外的所有视图都可以工作,但是如果我使用未登录的用户名直接输入 url,我可以看到他们的提交。

我还怀疑权限与我无法让 updateview 工作的原因相同。

我错过了什么?有没有更好的方法来避免在 URL 中使用用户名和 slug?我似乎找不到任何关于如何做这类事情的例子或提示。我是初学者,所以可能会在这里和那里错过对基础知识的一些了解。

我试图了解 User 模型的工作原理,因为我确实设法找到了一种以受保护的方式创建、查看和编辑用户详细信息的方法。虽然我依赖那里的函数视图,但似乎无法将这种方法应用于提交应用程序。

models.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"),
    ]

views.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'

forms.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']

【问题讨论】:

    标签: django django-views


    【解决方案1】:
    from django.contrib.auth.mixins import UserPassesTestMixin
    
    class EditSubmission(LoginRequiredMixin, UserPassesTestMixin, 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):
            self.object = self.get_object()
            if self.request.user == self.object.user:
                return True
            else:
                return False     
    

    我正在像这样使用“UserPassesTestMixin”,它正在工作。

    【讨论】:

      【解决方案2】:

      你应该像这样使用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     
      

      更多信息UserPassesTestMixin

      【讨论】:

      • 谢谢。它现在抛出'WSGIRequest'对象没有属性'args' - 在'username = self.request.kwargs ['username']行中。所以我怀疑我从用户模型访问“用户名”的方式存在另一个问题
      • 伟大的进步谢谢。如果我尝试使用另一个用户名(“fobidden”)访问,detail 和 listview 现在会阻止访问。但是即使我已经登录,更新视图现在总是抛出一个禁止的屏幕。怀疑这与之前阻止它的潜在问题相同。
      • test_func 背后的想法是它返回 true 或 false。,根据您的条件。所以调试查询
      • 您可以在 UserPassesTestMixin 之前传入 LoginRequiredMixin ,并且您不必检查用户是否在您的 test_func() 中进行了身份验证。
      猜你喜欢
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-26
      • 2013-08-30
      • 1970-01-01
      相关资源
      最近更新 更多