Django UpdateView中的对象所有权验证



编辑:

对我来说,更好的解决方案是使用权限系统,尤其是因为我需要对对象进行其他类型的受控访问。我现在使用Django守护程序来帮助处理这样的对象级权限。

原件:

我在标准的django图书指南上做了一些扩展,允许用户上传故事,以及让作者、出版商等。我试图只让故事的作者(创作者)使用updateview,而其他用户则被重定向。

在UpdateStory视图中修改get_object会使其失效,但由于某种原因,回溯会通过我的StoryForminit。错误为'HttpResponseRedirect' object has no attribute '_meta'

views.py

class UpdateStory(LoginRequiredMixin, UpdateView):
    model = Story
    template_name = 'stories/story_update.html'
    form_class = StoryForm
    def get_object(self, queryset=None):
        obj = super(UpdateStory, self).get_object()
        if not obj.author == self.request.user:
            return redirect(obj)
        return obj

forms.py

class StoryForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(StoryForm,self).__init__(*args, **kwargs)

我还是新人,所以这可能很明显,但我已经找了几个小时了,我被难住了。

最好的方法是使用另一个mixin,如下所示:

class AuthorRequiredMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if self.object.author != self.request.user:
            return HttpResponseForbidden()
        return super(AuthorRequiredMixin, self).dispatch(request, *args, **kwargs)

当然,您可以返回另一个HttpResponse,但请记住此处的正确用法。

http://ccbv.co.uk/projects/Django/1.5/django.views.generic.edit/UpdateView/

通过以上链接了解UpdateView的工作原理。get_object应该返回模型实例,而不应该返回HttpResponseRedirect对象,这就是为什么会出现错误的原因。

尝试在dispatch方法中执行检查,如下所示。

def dispatch(self, request, *args, **kwargs):
    """ Making sure that only authors can update stories """
    obj = self.get_object()
    if obj.author != self.request.user:
        return redirect(obj)
    return super(UpdateStory, self).dispatch(request, *args, **kwargs)

附言:我想不建议覆盖调度。但作为你必须对get和post方法进行检查,覆盖dispatch会更容易。

Django反模式中考虑了这个特定问题。

我们鼓励过滤QuerySet,只检索用户是作者的对象,而不是UserPassesTestMixin

在OP的情况下,它实际上与非常相似

from django.contrib.auth.mixins import LoginRequiredMixin
class UpdateStory(LoginRequiredMixin, UpdateView):
    model = Story
    # …
    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            author=self.request.user
        )

最新更新