views:

566

answers:

3

The first two paragraphs of this page explain that generic views are supposed to make my life easier, less monotonous, and make me more attractive to women (I made up that last one):

http://docs.djangoproject.com/en/dev/topics/generic-views/#topics-generic-views

I'm all for improving my life, but what do generic views actually do? It seems like lots of buzzwords are being thrown around, which confuse more than they explain.

Are generic views similar to scaffolding in Ruby on Rails? The last bullet point in the intro seems to indicate this. Is that an accurate statement?

+6  A: 

Django generic views are just view functions (regular old python functions) that do things that are very common in web applications.

Depending on the type of app you are building, they can save you from writing a lot of very simple views.

For example, the direct_to_template generic view simply renders a template with the RequestContext (which means the template has access to information on the request, like the current user, etc).

As a simple example, you can go from writing things like this:

# urls.py
url('^some-url/$', some_view)

# views.py
def some_view(request):
    return render_to_response('template_name.html', context_instance=RequestContext(request))

To just this:

# urls.py
url('^some-url/$', direct_to_template, {'template': 'template_name.html'})

# views.py doesn't need any code for this view anymore

There are also more complicated generic views for common actions such as "showing a list of models", or "adding a model to the db".

Also, because generic views are just functions, you can call them within your own view functions to do "most of the work", when you need something that is a bit different from the generic cases.

TM
Thanks, TM. They should add this to the documentation :). I'm not completely sold on generic views though. Your example involving direct_to_template does not save much code (2 lines), and you still have to manually specify the template. The bad part is that it makes your application a little harder to understand, because it requires that I know more about Django than is necessary to get this simple task done.
allyourcode
@allyourcode With more complicated views you stand to save a lot more code, I chose a very quick example. Also, for those views that operate on models, they will automatically select a template based on a naming convention (or it can be overridden if you don't want to to follow the convention). See http://docs.djangoproject.com/en/1.1/ref/generic-views/ for more examples. I recommend writing some of these views from scratch and then comparing. None of them are huge and complicated, it's just one less thing to write and debug.
TM
Thanks again, TM. I was already looking at the docs for the development version of Django.
allyourcode
+2  A: 

To answer your second question: no, generic views are not related to scaffolding in RoR. Scaffolding, as the name indicates, is akin to code generation. Generic views are something else.

My main usage of generic view is as a higher level replacement of the very basic render_to_response functions. This is how you could write a simple view with render_to_response:

def my_view(request):
    return render_to_response('my_template.html')

But this is very basic! For example the template will not have access to the request context, unless you pass it on explicitly.

I thus prefer to use a generic view instead:

def my_view(request):
    return direct_to_template(request, template='my_template.html')

Now the request context will be passed on! And that's just a start. Generic views come in handy when you want to display lists, or detail views, for instance. They will manage querying the database, and messaging the user, among other.

So generic views are high level functions to help you creating a response from a view.

Olivier
Generic views might involve code generation, but they seem to play a similar role. In an older version of Rails, it was possible to declare scaffolding in a controller (view in Django jargon). This would dynamically give the controller a bunch of methods that would allow a user to perform basic CRUD operations on the corresponding model.
allyourcode
I assume you meant "Generic views might **not** involve code generation, but they play a similar role". I would rather say that generic view... help to create a response from a view, as I said. One possible application is for CRUD operations. Note however that you still have to write the rest of the code, so it's definitely not scaffolding. Also, it would make sense to write your own generic views, if you have repetitiveness in the response creations.
Olivier
+1 for mentioning how a generic view can be used in your function. Esp. calling the `update_object` view makes it the best of both worlds for me: clear code, and still short.
vdboor
+1  A: 

Generic views allow you to write much shorter code.

Compare:

from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response, get_object_or_404, redirect
from myapp.models import Context

def edit(request, item_id):
    object = get_object_or_404(Context, pk=item_id)

    if request.method == 'POST':
        form = ContextForm(request.POST, instance=object)
        if form.is_valid():
            form.save()
            return redirect('myapp-context-index')
    else:
        form = ContextForm(instance=object)

    return render_to_response("myapp/context/edit.html", {'object': object, 'form': form})

with:

from django.core import urlresolvers
from django.views.generic.create_update import update_object
from myapp.models import Context

def edit(request, item_id):    
    return update_object(request, object_id=item_id,              
                                  form_class=ContextForm,            
                                  template_name="myapp/context/edit.html",
                                  post_save_redirect=urlresolvers.reverse("myapp-context-index"))

Like your normal views, they are just normal functions. It is possible to configure the view completely in the URLconf if you like, through I find this usage above a bit more clear.

As a BONUS, you also get:

  • Login authentication checks (pass login_required=True)
  • Success status message from django.contrib.messages.
  • Less code to check for errors.
  • A default ModelForm when you provide a model parameter instead of form_class.

The template_name has a default of "appname/model_form.html", but that's a bit too much for me.


Here is the form class they both share:

class ContextForm(forms.ModelForm): 
    """The form for a context"""
    class Meta:
        model = Context
        exclude = ('collection',)

    def save(self, commit=True):
        """Overwritten save to force collection_id to a value"""
        model = super(ContextForm, self).save(commit=False)
        model.collection_id = 1
        if commit:
            model.save()
        return model
vdboor