Пример Django на основе классов DeleteView - PullRequest
52 голосов
/ 03 апреля 2011

Кто-нибудь знает или может кто-нибудь привести простой пример универсального DeleteView на основе классов в Django?Я хочу создать подкласс DeleteView и убедиться, что зарегистрированный в данный момент пользователь владеет объектом до его удаления.Любая помощь будет очень высоко ценится.Заранее спасибо.

Ответы [ 4 ]

58 голосов
/ 04 апреля 2011

Вот простой пример:

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) с кнопкой «Да, я уверен», которую POST s для этого представления
  • Вы можете предпочестьсообщение об ошибке на 404?В этом случае вместо этого переопределите метод delete, проверьте разрешения после вызова get_object и верните настроенный ответ.
  • Не забудьте предоставить шаблон, который соответствует (необязательно настраиваемому) success_urlАтрибут класса, чтобы пользователь мог подтвердить, что объект был удален.
43 голосов
/ 05 июня 2012

Я в основном подклассифицировал некоторые из базовых представлений на основе классов, чтобы сделать именно это.Основное отличие состоит в том, что я просто отфильтровал наборы запросов.Я не могу поручиться за то, является ли этот метод лучше или хуже, но он стал для меня более логичным.

Не стесняйтесь игнорировать «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)

Использование

Затем вы можете легко создавать свои собственные представления для использования этого типа функциональности.Например, я просто создаю их в своем 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

Важное замечание: Я перегрузил эти методы 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

Это немного больше, чем вы просили - но это помогает узнать, как сделать то же самое для представлений Создать и Обновить.Эту же общую методологию можно применить к 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)
4 голосов
/ 11 сентября 2017

Самый простой способ сделать это - предварительно отфильтровать набор запросов:

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 голосов
/ 25 мая 2017

Я бы предложил, что лучший (и самый простой) способ сделать это - использовать UserPassesTestMixin, который дает вам более четкое разделение проблем.

Пример:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...