How to migrate from function-based generic views to class-based analogs in Django

Last week I’ve migrated a Django application from version 1.04 to 1.6.

Among the many methods deprecated, starting from version 1.5 all generic views based on functions have been eliminated (they were already deprecated in the previous release (https://docs.djangoproject.com/en/1.4/topics/generic-views-migration/)

In my application, the generic view was used in the views.py file in this way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@cache_page()
from django.views.generic.list_detail import object_list

def user_comments(request, username):
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise Http404

comments = Comment.objects.filter(user=user).order_by('-submit_date')
return object_list(request,
queryset=comments,
template_name="infosite/comments_user.html",
template_object_name="comments",
extra_context={'comments_count':comments.count()},
paginate_by=5,
allow_empty=True,
)

As we can see, our method in the view creates a generic list of comments, further adding an extra_context.

During the migration to version 1.6 of Django, I had to face two problems:

- To migrate from function-based generic views to class-based analogs
- The impossibility to add an extra_context in the new ListView class.

First of all, I’ve extended the ListView class this way (in order to add an extra_context parameter):

1
2
3
4
5
6
7
8

from django.views.generic import ListView

class SubListView(ListView):
extra_context = {}
def get_context_data(self, **kwargs):
context = super(SubListView, self).get_context_data(**kwargs)
context.update(self.extra_context)
return context

Then, I’ve changed the view as follow:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

@cache_page(CACHE_MIDDLEWARE_SECONDS)
def user_comments(request, username):

try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise Http404

comments = Comment.objects.filter(user=user).order_by('-submit_date')
callable = SubListView.as_view( queryset=comments,
template_name="infosite/comments_user.html",
template_object_name="comments",
extra_context={'comments_count':comments.count()},
paginate_by=5,
allow_empty=True,
)
return callable(request)

What do you think of this solution?