Итак, напомню, что виды в Django — основное средство формирования содержимого веб-страниц, которые представляются в виде обычных функций языка Python. Сейчас не буду вдаваться в подробности и описывать принципы работы видов, можно посмотреть официальную документацию (http://docs.djangoproject.com/en/1.3/topics/http/views/).


Допустим, стоит задача создать сайт, каждая страница которого состоит из двух частей: общей части (одинаково выглядит для всех страниц) и специальной части (разная для каждой страницы). То есть каждая специальная часть будет иметь собственный вид, который позаботится о выводе информации.

Первое, что может придти в голову — воспользоваться средством наследования шаблона, которое описано в официальной документации Django (шаблон — это разметка страницы плюс специальные теги шаблонизатора Django).

В этом случае у Вас имеется общий шаблон, от которого нужно будет унаследовать шаблоны Ваших страниц.

Приведём для большей наглядности пример.

Вот так может выглядеть базовый шаблон:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
/>
{% block title %}Мой замечательный сайт{% endblock %}


{% block sidebar %}

{% endblock %}


{% block content %}{% endblock %}




А так — один из шаблонов-наследников (страница Блога):

{% extends "base.html" %}

{% block title %}Мой замечательный блог{% endblock %}

{% block content %}
{% for entry in blog_entries %}

{{ entry.title }}


{{ entry.body }}


{% endfor %}
{% endblock %}


Шаблон был унаследован с помощью тега extends.

Какой явный недостаток предлагаемого метода? В примере базовому шаблону не передаётся параметров из вида. Причина проста — Вашему шаблону-родителю ничего не известно об упомянутых параметрах. Вида, который бы эти параметры ему передал — попросту нет. Конечно же, можно передавать эти параметры из вида, который привязан к шаблону-наследнику, но это не удобно. Придётся одни и те же параметры передавать из всех видов, ведь страниц-то может быть не одна. Это нарушило бы главный принцип платформы Django «DRY» («Don't Repeat Yourself» — проще говоря, «не повторяйся»).

Предлагается следующее решение данной проблемы.
  • Создаём родительский вид, родительский шаблон привязываем к нему.
  • Родительский вид будет представлен не функцией, а классом.
  • Дочерний вид также будет представлен классом, который наследует класс родительского вида. Кроме того, в дочернем виде будет в наличии входная функция, возвращающая контент страницы, которую можно будет прописать в обычном порядке в файле urls.py.

Вот пример данных классов.

Родительский:

from django.shortcuts import render_to_response

from django.template import Context, Template
from django.template.loader import get_template

class BaseParentView:
  def __init__( self ):
    self._baseViewTemplate = "parent.html"

  def _renderChildTemplate( self, **params ):
    template = get_template( self._childTemplate )
    return template.render( Context( params ) )

  def getView( self ):
    text = "Текст из родительского вида, который попадёт в заголовок страницы"
    return render_to_response( self._baseViewTemplate, { 'child_content': self._childContent, 'text': text } )


И сответствующий шаблон:
{{ text }}
{{ child_content }}



Дочерний:

from base_pass.parent.views import BaseParentView

class ChildView( BaseParentView ):
  def __init__( self ):
    BaseParentView.__init__( self )
    self._childTemplate = "child.html"

  def getView( self ):
    text = u"Текст из дочернего вида, который будет размещаться в теле страницы"
    self._childContent = self._renderChildTemplate( content = text )
    return BaseParentView.getView( self )

# Та самая функция, которая вернёт контент страницы на основе дочернего
# класса
def child( request ):
  child = ChildView()
   return child.getView()


И дочерний шаблон:
{{ content }}


Функция, возвращающия контент в каждом классе, имеет имя getView, а соответствующие шаблоны прописаны в членах классов _baseViewTemplate и _childTemplate.

Таким образом, мы можем создавать дочерные классы и соответствующие шаблоны для каждой страницы Вашего сайта, а о передаче параметров в общую часть позаботится наш родительский класс.

При этом мы не использовали предлагаемый платформой Django тег наследования шаблонов extends.

Вы можете попробовать данный подход, создав тестовый проект Django. Не забудьте прописать в urls.py дочернего вида кортеж для функции child.