I am working on a simple "to do list" app in Django (two models: List
and Item
). I'm trying to learn and make use of class-based generic views. I have the following three display views working, but am requesting a quick code review to see if there's anything I can do to improve my usage/understanding of Django's ListView
and DetailView
before I move on to creating, updating and deleting.
# class-based generic views for my lists, a list's items, and item detail...
class MyListsView(ListView):
"""Display the current user's Lists"""
template_name = 'cmv_app/my_lists.html'
context_object_name = 'my_lists'
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(MyListsView, self).dispatch(*args, **kwargs)
def get_queryset(self):
return List.objects.filter(user=self.request.user).order_by('-last_modified')
class ListItemsView(ListView):
"""Display a list's items"""
template_name = 'cmv_app/list_items.html'
context_object_name = 'list_items'
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
self.list = get_object_or_404(List, pk=kwargs['list_id'])
request = list_valid_for_user(request, self.list) # security check
return super(ListItemsView, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
return Item.objects.filter(list=self.list).order_by('-created_date')
def get_context_data(self, **kwargs):
context = super(ListItemsView, self).get_context_data(**kwargs)
context['list'] = self.list
return context
class ItemDetailView(DetailView):
"""Display detail for one list item"""
template_name = 'cmv_app/item_detail.html'
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
self.list = get_object_or_404(List, pk=kwargs['list_id'])
self.item = get_object_or_404(Item, pk=kwargs['item_id'])
request = list_valid_for_user(request, self.list) # security check
request = item_valid_for_list(request, self.item, self.list) # security check
return super(ItemDetailView, self).dispatch(request, *args, **kwargs)
def get_object(self):
return self.item
def get_context_data(self, **kwargs):
context = super(ItemDetailView, self).get_context_data(**kwargs)
context['list'] = self.list
return context
2 Answers 2
This looks pretty good -- views should generally be pretty minimal. These seem pretty short, and most of what you've done so far seems appropriate.
One pattern you might think about is using a mixin to dry things out a touch more. Eg, you have all your dispatch
methods decorated login_required
. If you created a LoginMixin, with and just decorated the dispatch
method there, you could loose a few repetitions. Mixins are also nice to have, as you can stash other repetitive elements in them as needed.
If you want to cut it down you could do something like:
class MyListsView(ListView):
model = List
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(MyListsView, self).dispatch(*args, **kwargs)
def get_queryset(self):
queryset = super(MyListsView, self).get_queryset(self)
return queryset.filter(user=self.request.user).order_by('-last_modified')
You would then make a template under the app folder with a template called list_list.html such as
List/templates/list/list_list.html
You would also use 'list_list' as the context object in your template.