3
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.