Pull to refresh

Django: наследование видов при создании сайта

Итак, напомню, что виды в 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.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.