Django Class-Based Generic Views

After working with Paypouy on a quick project using the php-based, shared-hosting-friendly CodeIgniter, I’m back to the more familiar waters of Python/Django.

I was asked to create a small organizer/calendar type app for a client to be used mainly from a smart phone. The app seemed very straight forward, so I thought I’d rely on the generic views for most of the work.

Check out some of the code after the break
Here’s a bit of code:

# urls.py
from django.conf.urls import patterns, include, url
from django.views.generic import ListView, DetailView
from app.views import \
    CalendarView, DeleteCalView, UpdateCalView, CreateCalView

urlpatterns = patterns('',
    url(r'^calendar/create/$', CreateCalView.as_view(), name="cal_create"),
    url(r'^calendar/(?P[0-9]+)/$', DetailView.as_view(model=Presentation, slug_field='number'), name='presentation'),
    url(r'^calendar/$', ListView.as_view(model=Presentation, context_object_name='presentation'), name='presentation_list'),
    url(r'^calendar/upcoming/$', CalendarView.as_view(), {'as': 'upcoming'}, name='upcoming'),
    url(r'^calendar/presented/$', CalendarView.as_view(), {'as': 'presented'}, name='presented'),
    url(r'^calendar/unconfirmed/$', CalendarView.as_view(), {'as': 'unconfirmed'}, name='unconfirmed'),
    url(r'^calendar/confirm/(?P[0-9]+)/$', UpdateCalView.as_view(), {'as': 'confirm'}, name="cal_confirm"),
    url(r'^calendar/delete/(?P[0-9]+)/$', DeleteCalView.as_view(), name="cal_del"),
)

and some code from the Views:

# views.py
class CalendarView(ListView):
    template_name = "calendar/calendar.html"
    
    def get_queryset(self):
        called_as = self.kwargs['as']
        if (called_as in ["home", "upcoming"]):
            return Calendar.objects.order_by('scheduled_on').filter(scheduled_on__gt=datetime.now())
        if (called_as=="presented"):
            return Calendar.objects.order_by('scheduled_on').filter(scheduled_on__lt=datetime.now(), status="P")
        if (called_as=="unconfirmed"):
            return Calendar.objects.order_by('scheduled_on').filter(scheduled_on__gt=datetime.now(), status="R")
        
    def get_context_data(self, **kwargs):
        called_as = self.kwargs['as']
        context = super(CalendarView, self).get_context_data(**kwargs)
        if (called_as in ["home", "upcoming"]):
            context['title'] = "Upcoming Presentations"
        if (called_as=="presented"):
            context['title'] = "Done"
        if (called_as=="unconfirmed"):
            context['title'] = "Unconfirmed Presentations"
            context['actions'] = ['confirm', 'delete']
        return context
        
class DeleteCalView(DeleteView):
    model = Calendar
    template_name = "calendar/delete.html"
    success_url = "/" 
    
class UpdateCalView(UpdateView):
    model = Calendar
    template_name = "calendar/update.html"
    success_url = "/" 
    
    def get_context_data(self, **kwargs):
        called_as = self.kwargs['as']
        context = super(UpdateCalView, self).get_context_data(**kwargs)
        if (called_as=="confirm"):
            context['confirm_form'] = True   
        return context
        
class CreateCalView(CreateView):
    model = Calendar
    template_name = "calendar/update.html"
    success_url = "/"
    
    def get_initial(self):
        initial = super(CreateView, self).get_initial()
        initial = initial.copy()
        initial['status'] = 'R'
        return initial

I should mention that most of the code in the views.py could simply be removed and the equivalent added in the urls.py file. For example:

class DeleteCalView(DeleteView):
    model = Calendar
    template_name = "calendar/delete.html"
    success_url = "/" 

could be replaced by editing the line in urls.py:

url(r'^calendar/delete/(?P[0-9]+)/$', 
        DeleteView.as_view(model=Calendar, template_name="calendar/delete.html", success_url="/"),
        name="cal_del"),

Note also that you can simply use the default template_name instead of adding your own (less code!).

Since the app would mostly be used from smart phones, I used jQueryMobile for most of the template work (and its DateBox plugin. Here’s a bit of code from that:

Tagged , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *