web-dev-qa-db-ja.com

DjangoクラスベースのDeleteViewの例

Djangoのクラスベースの汎用DeleteViewの簡単な例を作成できる人はいますか? DeleteViewをサブクラス化し、現在ログインしているユーザーがオブジェクトを削除する前に所有権を持っていることを確認します。どんな助けも大歓迎です。前もって感謝します。

53
Lockjaw

以下に簡単なものを示します。

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要求では削除されません。これは、POSTsをこのビューに表示する「Yes I's sure」ボタンを使用して、確認テンプレート(template_nameクラス属性で名前を指定できます)を提供する機会です。
  • 404よりもエラーメッセージを好む場合がありますか?この場合、代わりにdeleteメソッドをオーバーライドし、get_object呼び出しの後に許可を確認し、カスタマイズされた応答を返します。
  • ユーザーがオブジェクトが削除されたことを確認できるように、(オプションでカスタマイズ可能な)success_urlクラス属性に一致するテンプレートを提供することを忘れないでください。
60
DrMeers

基本的に、これを行うために、いくつかの汎用クラスベースビューをサブクラス化しました。主な違いは、クエリセットを除外しただけです。この方法が良いか悪いかを保証することはできませんが、私にとってはより意味がありました。

「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'),

フォーム

重要: Formsに 'request'のインスタンスを提供するために、これらの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)
43
Kurtis

これを行う最も簡単な方法は、クエリセットを事前フィルタリングすることです。

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)
4
Israel Teixeira

これを行うための最良の(そして最も簡単な)方法は、 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
0
Inti