Oleg Tarasenko
Oleg Tarasenko

Reputation: 9610

django: generic delete view

I want to build a generic delete view for my application. Basically I want to have the same behaviour as the standard django admin. E.g. I want to be able to delete different objects using the same view (and template).

I was looking on django docs, and looks like that DeleteViews are coupled with the models they are supposed to delete. E.g.

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

And I want to create something more generic, e.g.

class AnyDelete(DeleteView):
    model = I want to have a list of models here
    success_url = reverse_lazy('some-remaining-list')

Upvotes: 0

Views: 1626

Answers (1)

Serafeim
Serafeim

Reputation: 15104

The reason CBVs were invented were to solve problems like yours. As you have already written, to create your own delete view you just need to subclass DeleteView and change two properties. I find it very easy and do it all the time (the only non-dry work that I have to do is to hook it to urls.py).

In any case, if you really want to create something more generic (e.g only one view to delete every kind of model) then you'll need to use the content types framework. As you will see in the documentation, the content types framework can be used to work with objects of arbitrary models. So, in your case you can create a simple view that will get three parameters: app_label, model and pk of model to delete. And then you can implement it like this:

from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

def generic_delete_view(request, app_label, pk):
  if request.method == 'POST':
    my_type = ContentType.objects.get(app_label=app_label, model=model)
    get_object_or_404(my_type.model_class(), pk=pk).delete()

    # here you must determine *where* to return to
    # probably by adding a class method to your Models 

Of course in your urls.py you have to hook this view so that it receives three parameters (and then call it like this /generic_delete/application/Model/3). Here's an example of how you could hook it in your urls.py:

urlpatterns = patterns('',
  # ....
  url(
    r'^generic_delete/(?P<app_label>\w+)/(?P<model>\w+)/(?P<pk>\d+)$',
    views.generic_delete_view,  
    name='generic_delete' 
  ) ,
  # ...
)

If you have a list of objects and want to get the app_label and model of each one in order to construct the generic-delete urls you can do something like this:

from django.core.urlresolvers import reverse

object = # ... 
ct = ContentType.objects.get_for_model(object)
generic_delete_url = reverse('generic_delete', kwargs = {
  app_label=ct.app_label,
  model=ct.model,
  pk=object.pk
})
# so generic_delete_url now will be something like /my_app/MyModel/42

Upvotes: 1

Related Questions