Sunday, May 1, 2011

Basic MVT issue in Django

I have a Django website as follows:

  • site has several views
  • each view has its own template to show its data
  • each template extends a base template
  • base template is the base of the site, has all the JS/CSS and the basic layout

So up until now it's all good. So now we have the master head of the site (which exists in the base template), and it is common to all the views.

But now I want to make it dynamic, and add some dynamic data to it. On which view do I do this? All my views are basically render_to_response('viewtemplate.html', someContext). So how do add a common view to a base template?

Obviously I will not duplicate the common code to each separate view...

I think I'm missing something fundamental in the MVT basis of Django.

From stackoverflow
  • You want to use context_instance and RequestContexts.

    First, add at the top of your views.py:

    from django.template import RequestContext
    

    Then, update all of your views to look like:

    def someview(request, ...)
        ...
        return render_to_response('viewtemplate.html', someContext, context_instance=RequestContext(request))
    

    In your settings.py, add:

    TEMPLATE_CONTEXT_PROCESSORS = (
        'django.core.context_processors.auth',
        ...
        'myproj.app.context_processors.dynamic',
        'myproj.app.context_processors.sidebar',
        'myproj.app.context_processors.etc',
    )
    

    Each of these context_processors is a function takes the request object and returns a context in the form of a dictionary. Just put all the functions in context_processors.py inside the appropriate app. For example, a blog might have a sidebar with a list of recent entries and comments. context_processors.py would just define:

    def sidebar(request):
        recent_entry_list = Entry.objects...
        recent_comment_list = Comment.objects...
        return {'recent_entry_list': recent_entry_list, 'recent_comment_list': recent_comment_list}
    

    You can add as many or as few as you like.

    For more, check out the Django Template Docs.

    Yuval A : wonderful! thanks! fixed a small typo in the import...
    Carl Meyer : Just don't go overboard with context processors - only data that really is used on _every single page load_ belongs in a context processor, otherwise you're wasting DB queries.
  • or use a generic view, because they are automatically passed the request context.

    a simple direct to template generic view can be used to avoid having to import/pass in the request context.

  • Context processors and RequestContext (see Tyler's answer) are the way to go for data that is used on every page load. For data that you may need on various views, but not all (especially data that isn't really related to the primary purpose of the view, but appears in something like a navigation sidebar), it often makes most sense to define a custom template tag for retrieving the data.

0 comments:

Post a Comment