Class-Based Views – A ListView Example

I put this here mostly for my own documentation.

Before:

@permission_required('training.view_signupdetail') 
def class_history_attend(request,class_id):
    
    tc = get_object_or_404(TrainingClass,id=class_id)
            
    queryset = SignupDetail.objects.filter(schedule__training_class = tc,attended = True).order_by('session__user__username')
    
    params = {'queryset': queryset,
              'template_name': 'class_history.html',
              'extra_context': {'tc': tc}}
    return object_list(request, **params)    

After:

class ClassHistoryAttendView(ListView):
    ## Set the template name
    template_name = 'class_history.html'  

    ## Override dispatch to apply the permission decorator
    @method_decorator(permission_required('training.view_trainingclass'))
    def dispatch(self, *args, **kwargs):
        return super(ClassHistoryAttendView, self).dispatch(*args, **kwargs)  
    
    ## Define get_queryset to bring in the supplied class number and build the query
    def get_queryset(self):
        self.tc = get_object_or_404(TrainingClass,id=self.kwargs.get('class_id',None))
        return SignupDetail.objects.filter(schedule__training_class = self.tc,attended = True).order_by('session__user__username')
    
    ## Override get_context_data to add the class number to the context for use by the template
    def get_context_data(self, **kwargs):
        context = super(ClassHistoryAttendView, self).get_context_data(**kwargs)
        context['tc'] = self.tc
        return context

UPDATE:

The override of dispatch allows the application of the permission decorator. Note the @method_decorator wrapper around the traditional view decorator for permission use.

The other two method overrides are necessary to access the self instance of the object.

An easier example still uses the permission override, but others are not needed.

Before:

@permission_required('b2c.view_event')
def list_event(request):
    params = {'queryset': Event.objects.all(),
              'paginate_by': DEFAULT_PAGINATION,
              'template_name': 'event_list.html'}
    return object_list(request, **params)

After:

class ListEventView(ListView):
    ## The basics
    template_name = 'event_list.html'  
    paginate_by = DEFAULT_PAGINATION
    queryset = Event.objects.all()

    ## Override dispatch to apply the permission decorator
    @method_decorator(permission_required('b2c.view_event'))
    def dispatch(self, *args, **kwargs):
        return super(ListEventView, self).dispatch(*args, **kwargs) 

Note that the paginate_by variable is set in this example.

Also

These are the imports needed:

from django.views.generic import ListView
from django.utils.decorators import method_decorator

In urls.py, adjust the definition to call the as_view method of the class:

url(r'^list_event/$',ListEventView.as_view(),name='event_list')