Django Class Demo Example

Does anyone know or can anyone create a simple example of a universal DeleteView based on Django? I want to subclass DeleteView and make sure that the user who is currently logged in has ownership of the object before deleting it. Any help would be much appreciated. Thank you in advance.

+46
django django-views django-class-based-views
Apr 03 2018-11-11T00:
source share
4 answers

Here's a simple one:

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 

Cautions:

  • DeleteView will not delete GET requests; this is your opportunity to provide a confirmation template (you can specify a name in the attribute of the template_name class) with the "Yes, I'm sure" button, which is the POST for this view
  • Can you prefer the 404 error message? In this case, override the delete method, check permissions after calling get_object and return the configured response.
  • Remember to specify a template that matches the (optionally customizable) attribute of the success_url class success_url that the user can confirm that the object has been deleted.
+50
Apr 03 2018-11-11T00:
source share

I basically subclassed some of the Generic Class-Based-Views to do just that. The main difference is that I just filtered the requests. I cannot vouch for whether this method is better or worse, but for me it made more sense.

Remember to ignore the "MessageMixin" - just there to easily send messages using the Django Messaging Framework with the variable specified for each view. Here is the code I wrote for our site:

representation

 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 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 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 data. """ success_message = "Deleted Successfully" def get_queryset(self): qs = super(RequestDeleteView, self).get_queryset() return qs.filter(owner=self.request.user) 

Using

Then you can easily create your own views to use this type of function. For example, I just create them in my 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'), 

Forms

Important to note: I overloaded these get_form_kwargs () methods to provide my Forms with an instance of the "request". If you do not want the Request object to be submitted to the form, simply remove these overloaded methods. If you want to use them, run the following example:

 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 

This is a little more than what you asked for - but it helps to learn how to do the same for Create and Update views. The same general methodology can also be applied to ListView and DetailView.

MessageMixin

Just in case, someone wants to use 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) 
+42
Jun 05 '12 at 19:50
source share

I would suggest that the best (and easiest) way to do this would be to use UserPassesTestMixin , which gives you a cleaner separation of concerns.

Example:

 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 
+1
May 25 '17 at 12:07
source share

The easiest way to do this is with a preliminary set of queries:

 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) 
0
Sep 11 '17 at 16:22
source share



All Articles