有没有人知道或能够提供一个Django类的通用DeleteView的简单示例?我想要子类化DeleteView并确保当前登录的用户在删除对象之前拥有它。非常感谢任何帮助。提前致谢。
有没有人知道或能够提供一个Django类的通用DeleteView的简单示例?我想要子类化DeleteView并确保当前登录的用户在删除对象之前拥有它。非常感谢任何帮助。提前致谢。
这是一个简单的例子:
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
注意事项:
DeleteView
不会在GET
请求时执行删除操作;这是您提供确认模板的机会(您可以在template_name
类属性中指定名称),其中包含"Yes I'm sure"按钮,用于向该视图POST
delete
方法,在get_object
调用之后检查权限并返回自定义响应。success_url
类属性匹配的模板,以便用户可以确认对象已被删除。我基本上是继承了一些通用的基于类的视图来实现这个目标。主要区别在于我只过滤了查询集。我不能保证这种方法是否更好或更差,但对我来说更有意义。
可以忽略 "MessageMixin" -- 它只是为了使用Django消息框架轻松地呈现消息,并针对每个视图指定一个变量。以下是我们网站所编写的代码:
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)
然后,您可以轻松地创建自己的视图来使用此类型的功能。例如,我只是在我的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'),
需要注意的是:我重载了get_form_kwargs()方法,以便为我的表单提供'request'实例。如果您不想将请求对象传递给表单,只需删除这些重载方法即可。如果您想使用它们,请参照以下示例:
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
这比你要求的内容多一点,但知道如何对 Create 和 Update 视图执行相同操作很有帮助。这种通用方法还可以应用于 ListView 和 DetailView。
以防万一,如果有人想使用我使用的 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)
django.template.context_processors.request
上下文处理器。 - Risadinhafrom 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)
get_object()
方法,如果所有者没有权限,则返回None
。然后我重写了post()
方法来检查是否为None
值对象,如果是则重定向到另一个页面,并显示有关权限的消息。这个解决方案有点笨拙,但在找到更优雅的解决方案之前它能够工作。 - Nathaniel HoytUserPassesTestMixin
,这将使关注点分离更加清晰。from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DeleteView
class MyDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
def test_func(self):
""" Only let the user access this page if they own the object being deleted"""
return self.get_object().owner == self.request.user
get_queryset
方法。这样做会简单得多:return self.request.user.foo_set.all()
。默认的get_object
方法将从 queryset 进行过滤,该 queryset 仅包含由self.request.user
拥有的项目。如果未找到,则会返回 404。 - NickDeletionMixin.delete
中,get_object
方法总是在代码到达self.object.delete()
之前被调用。直接发布到MyDeleteView
的 URL 是删除的正常方式。 - DrMeers