Django基于类的DeleteView示例

Loc*_*jaw 54 django django-views django-class-based-views

有谁知道或者任何人都可以生成Django基于类的通用DeleteView的简单示例?我想子类化DeleteView并确保当前登录的用户在删除之前拥有该对象的所有权.任何帮助将非常感谢.先感谢您.

DrM*_*ers 61

这是一个简单的:

from django.views.generic import DeleteView
from django.http import Http404

class MyDeleteView(DeleteView):
    def get_object(self, queryset=None):
        """ Hook to ensure object is owned by request.user. """
        obj = super(MyDeleteView, self).get_object()
        if not obj.owner == self.request.user:
            raise Http404
        return obj
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • DeleteView不会删除GET请求; 这是您提供一个确认模板(您可以在template_name类属性中提供名称)的机会,并POST在此视图中显示"是的我确定"按钮
  • 您可能更喜欢404的错误消息?在这种情况下,请改写delete方法,在get_object调用后检查权限并返回自定义响应.
  • 不要忘记提供与(可选定制的)success_url类属性匹配的模板,以便用户可以确认该对象已被删除.

  • 啊 - 这太有用了!感谢您抽出宝贵时间.它可以在文档中存在,但是几天盯着文档会造成损失. (3认同)
  • @Erik @DrMeers我会覆盖`get_queryset`方法.这样做更简单:`return self.request.user.foo_set.all()`.然后,默认的`get_object`方法将过滤掉查询集,该查询集只有`self.request.user`拥有的项.如果找不到,那将是404. (2认同)

Kur*_*tis 43

我基本上将一些基于通用类的视图分类为完全相同.主要的区别是我刚刚过滤掉了查询集.我不能保证这种方法是好还是坏,但对我来说更有意义.

可以随意忽略"MessageMixin" - 这就是使用Django Messaging Framework轻松呈现消息,并为每个视图指定一个变量.这是我为我们的网站编写的代码:

查看

from django.views.generic import CreateView, UpdateView, \
        DeleteView, ListView, DetailView

from myproject.core.views import MessageMixin

class RequestCreateView(MessageMixin, CreateView):
    """ 
    Sub-class of the CreateView to automatically pass the Request to the Form. 
    """
    success_message = "Created Successfully"

    def get_form_kwargs(self):
        """ Add the Request object to the Form's Keyword Arguments. """
        kwargs = super(RequestCreateView, self).get_form_kwargs()
        kwargs.update({'request': self.request})
        return kwargs

class RequestUpdateView(MessageMixin, UpdateView):
    """
    Sub-class the UpdateView to pass the request to the form and limit the
    queryset to the requesting user.        
    """
    success_message = "Updated Successfully"

    def get_form_kwargs(self):
        """ Add the Request object to the form's keyword arguments. """
        kwargs = super(RequestUpdateView, self).get_form_kwargs()
        kwargs.update({'request': self.request})
        return kwargs

    def get_queryset(self):
        """ Limit a User to only modifying their own data. """
        qs = super(RequestUpdateView, self).get_queryset()
        return qs.filter(owner=self.request.user)

class RequestDeleteView(MessageMixin, DeleteView):
    """
    Sub-class the DeleteView to restrict a User from deleting other 
    user's data.
    """
    success_message = "Deleted Successfully"

    def get_queryset(self):
        qs = super(RequestDeleteView, self).get_queryset()
        return qs.filter(owner=self.request.user)
Run Code Online (Sandbox Code Playgroud)

用法

然后,您可以轻松创建自己的视图以使用此类功能.例如,我只是在我的urls.py中创建它们:

from myproject.utils.views import RequestDeleteView

#...

url(r'^delete-photo/(?P<pk>[\w]+)/$', RequestDeleteView.as_view(
                   model=Photo,
                   success_url='/site/media/photos',
                   template_name='site/media-photos-delete.html',
                   success_message='Your Photo has been deleted successfully.'
                   ), name='fireflie-delete-photo-form'),
Run Code Online (Sandbox Code Playgroud)

形式

需要注意的重要事项:我重载了那些get_form_kwargs()方法,为我的Forms提供了一个'request'实例.如果您不希望将Request对象传递给Form,只需删除那些重载的方法.如果要使用它们,请按照以下示例操作:

from django.forms import ModelForm

class RequestModelForm(ModelForm):
    """
    Sub-class the ModelForm to provide an instance of 'request'.
    It also saves the object with the appropriate user.
    """
    def __init__(self, request, *args, **kwargs):
        """ Override init to grab the request object. """
        self.request = request
        super(RequestModelForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        m = super(RequestModelForm, self).save(commit=False)
        m.owner = self.request.user
        if commit:
            m.save()
        return m
Run Code Online (Sandbox Code Playgroud)

这比您要求的要多一些 - 但它也有助于了解如何对创建和更新视图执行相同操作.这种相同的通用方法也可以应用于ListView和DetailView.

MessageMixin

万一有人想要我使用的MessageMixin.

class MessageMixin(object):
    """
    Make it easy to display notification messages when using Class Based Views.
    """
    def delete(self, request, *args, **kwargs):
        messages.success(self.request, self.success_message)
        return super(MessageMixin, self).delete(request, *args, **kwargs)

    def form_valid(self, form):
        messages.success(self.request, self.success_message)
        return super(MessageMixin, self).form_valid(form)
Run Code Online (Sandbox Code Playgroud)

  • 现在有django.contrib.messages.views.SuccessMessageMixin.https://code.djangoproject.com/ticket/16319 (3认同)

Isr*_*ira 7

最简单的方法是对查询集进行预过滤:

from django.views.generic import DeleteView


class PostDeleteView(DeleteView):
    model = Post
    success_url = reverse_lazy('blog:list_post')

    def get_queryset(self):
        owner = self.request.user
        return self.model.objects.filter(owner=owner)
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案,您只查询一次对象(此页面上的某些解决方案需要双重查找),如果对象被过滤出用户范围之外,它本身就会引发 Http404 错误,不需要额外的用户身份验证逻辑。 (2认同)