Kennt jemand etwas oder kann jemand ein einfaches Beispiel für Djangos generisches DeleteView generieren? Ich möchte DeleteView subclass und sicherstellen, dass der aktuell angemeldete Benutzer das Eigentum des Objekts besitzt, bevor es gelöscht wird. Jede Hilfe wäre sehr dankbar. Danke im Voraus.
Hier ist eine einfache:
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
Vorsichtsmaßnahmen:
DeleteView
wird bei GET
-Anforderungen nicht gelöscht. Dies ist Ihre Gelegenheit, eine Bestätigungsvorlage (Sie können den Namen im Klassenattribut template_name
angeben) mit einer Schaltfläche "Ja, ich bin sicher" anzugeben, die POST
s für diese Ansicht enthältdelete
-Methode, überprüfen Sie die Berechtigungen nach dem get_object
-Aufruf und geben Sie eine angepasste Antwort zurück.success_url
-Klassenattribut entspricht, damit der Benutzer bestätigen kann, dass das Objekt gelöscht wurde.Ich habe im Grunde einige der generischen klassenbasierten Ansichten dahingehend klassifiziert, dass sie genau das tun. Der Hauptunterschied besteht darin, dass ich nur die Querysets herausgefiltert habe. Ich kann nicht dafür bürgen, ob diese Methode besser oder schlechter ist, aber für mich war es sinnvoller.
Sie können das "MessageMixin" einfach ignorieren. Hier können Sie Nachrichten einfach mit dem Django Messaging Framework mit einer für jede Ansicht angegebenen Variablen präsentieren. Hier ist der Code, den ich für unsere Site geschrieben habe:
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)
Sie können dann leicht eigene Ansichten erstellen, um diese Art von Funktionalität zu verwenden. Zum Beispiel erstelle ich sie in meiner 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'),
Wichtig zu beachten: Ich habe diese get_form_kwargs () - Methoden überladen, um meine Formulare mit einer Instanz von 'request' zu versehen. Wenn das Request-Objekt nicht an das Formular übergeben werden soll, entfernen Sie einfach diese überladenen Methoden. Wenn Sie sie verwenden möchten, folgen Sie diesem Beispiel:
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
Dies ist etwas mehr als Sie gefragt haben - aber es ist hilfreich zu wissen, wie Sie dies auch für die Erstellungs- und Aktualisierungsansicht tun. Dieselbe allgemeine Methodik könnte auch auf ListView & DetailView angewendet werden.
Nur für den Fall, dass jemand das MessageMixin möchte, das ich verwende.
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)
Am einfachsten ist es, das Abfrageset vorzufiltern:
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)
Ich würde vorschlagen, dass der beste (und einfachste) Weg, dies zu tun, die Verwendung der UserPassesTestMixin
wäre, die eine sauberere Trennung der Bedenken ermöglicht.
Beispiel:
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