vistas createview clases basadas django django-views django-class-based-views

createview - crud django



Ejemplo de DeleteView basado en clases de Django (4)

Aquí hay una simple:

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

Advertencias:

  • El DeleteView no borrará en las solicitudes GET ; esta es su oportunidad de proporcionar una plantilla de confirmación (puede proporcionar el nombre en el atributo de clase template_name ) con un botón "Sí, estoy seguro", que POST está en esta vista
  • Usted puede preferir un mensaje de error a un 404? En este caso, anule el método de delete , verifique los permisos después de la llamada a get_object y devuelva una respuesta personalizada.
  • No olvide proporcionar una plantilla que coincida con el atributo de clase success_url (opcionalmente personalizable) para que el usuario pueda confirmar que el objeto se ha eliminado.

¿Alguien sabe o puede alguien por favor producir un ejemplo simple de DeleteView genérico basado en clase de Django? Quiero crear una subclase de DeleteView y asegurarme de que el usuario que ha iniciado sesión actualmente sea propietario del objeto antes de eliminarlo. Cualquier ayuda sería muy apreciada. Gracias de antemano.


Básicamente, he subclasificado algunas de las Vistas genéricas basadas en clase para hacer exactamente eso. La principal diferencia es que acabo de filtrar los querysets. No puedo responder si este método es mejor o peor, pero tenía más sentido para mí.

Siéntase libre de ignorar el "MessageMixin", que está ahí para presentar fácilmente los Mensajes utilizando el Marco de Mensajería de Django con una variable especificada para cada vista. Aquí está el código que he escrito para nuestro sitio:

Puntos de vista

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)

Uso

Luego, puede crear fácilmente sus propias vistas para utilizar este tipo de funcionalidad. Por ejemplo, solo los estoy creando en mi 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''),

Formas

Importante tener en cuenta: he sobrecargado los métodos get_form_kwargs () para proporcionar a mis Formularios una instancia de "solicitud". Si no desea que el objeto de solicitud se pase al formulario, simplemente elimine los métodos sobrecargados. Si quieres usarlos, sigue este ejemplo:

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

Esto es un poco más de lo que pidió, pero es útil saber cómo hacer lo mismo para las vistas Crear y Actualizar. Esta misma metodología general también podría aplicarse a ListView y DetailView.

MessageMixin

Por si alguien quiere ese MessageMixin que uso.

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)


La forma más sencilla de hacerlo es prefiltrar el queryset:

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)


Propongo que la mejor (y más simple) forma de hacerlo sería utilizar UserPassesTestMixin que le proporciona una separación de preocupaciones más UserPassesTestMixin .

Ejemplo:

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