Django. Своя CMS. Часть 3

Дата публикации:29 апреля 2013 г. 1:33:38

Здравствуйте! Продолжим создание своей CMS на Django. В этой статье мы сделаем шаблонные теги и шаблоны. Итак, приступим.

Нам нужно сделать пару шаблонных тегов для вывода меню и вывода META информации страницы. Идем в каталог templatetags каталога pages и создаем там файл app_pages_tags.py.

Файл app_pages_tags.py

#! /usr/bin/python
# -*- coding: utf-8 -*-

from django import template
from django.template import Library, loader, Context
from django.core.exceptions import ObjectDoesNotExist

from app.pages.models import Page, PageMetaInf

register = template.Library()

@register.simple_tag(takes_context = True)
def display_menu(context, menu, template_name, page = None):
    request = context['request']
    path = request.path
    if path == '':
        path = '/'
    t = loader.get_template(template_name)
    if page is None:
        pages = Page.objects.filter(menu__contains = menu, publish = True)
        return t.render(Context({
            'pages': pages,
            'current': path,
        }))
    pages = Page.objects.filter(
        menu__contains = menu,
        tree_id = page.tree_id,
        level__gte = page.level,
        parent_id = page.id,
publish = True, ).exclude( level = page.level ) return t.render(Context({ 'title': page.title, 'pages': pages, 'current': path, })) # Функция для извлечения META информации def get_meta_inf(page, domain): try: meta_inf = PageMetaInf.objects.get( page__id = page, site__domain = domain ) except ObjectDoesNotExist: meta_inf = False return meta_inf @register.assignment_tag(takes_context = True) def page_meta_inf(context, page): request = context['request'] meta_inf = get_meta_inf(page, request.META['SERVER_NAME']) return meta_inf

Теперь пояснения. Меню будет показываться для текущего уровня или же, если не передавать страницу, то для всех страниц, которые выбраны для показа в этом меню. Вы можете изменить это поведение, но по мне - это наиболее правильные варианты. Что касается META информации, то она будет выводится через assignment_tag. Мне показалось, что это хороший вариант. Может это не совсем удобно, но мне так нравится :)

Теперь о том, как мы будем это использовать в шаблонах. Следующим образом. Создаем файл шаблона. У меня он будет base.html, который будет базовым для текущего сайта.

Файл base.html

<!DOCTYPE html>
<html>
<head>
{% load url from future %}
{% load app_tags %}
{% load app_pages_tags %}
<meta http-equiv = "Content-Type" content = "text/html; charset = utf-8" />
<meta name = "keywords" content = "{% block meta_keywords %}{% endblock %}" />
<meta name = "description" content = "{% block meta_description %}{% endblock %}" />

<link href = "" rel = "shortcut icon" type = "image/vnd.microsoft.icon" />

<link rel = "stylesheet" type = "text/css" media = "all" href = "{{ STATIC_URL }}css/style.css?v=1.0.0" />
{% block extra_head %}{% endblock %}

<title>{% block meta_title %}{% endblock %} | {% site_title %}</title>
</head>
<body>
<ul class = "top-menu">
    {% display_menu '0' 'top_menu.html' %}
</ul>
{% block content %}{% endblock %}
</body>
</html>

Как видно в base.html в меню будут показываться все страницы, независимо от того, к какому родителю они относятся. Если нужно передать текущий уровень, то добавьте в тег еще страницу. Также, здесь мы заботливо подготовили блоки для будущих файлов index.html и page.html. Я не буду описывать файл index.html, так как он может быть таким же как и page.html. Приведу лишь для примера файл page.html.

Файл page.html

{% extends 'base.html' %}

{% load app_tags %}
{% load app_pages_tags %}

{% block meta_keywords %}{% page_meta_inf page.id as meta_inf %}{{ meta_inf.meta_keywords }}{% endblock %}
{% block meta_description %}{% page_meta_inf page.id as meta_inf %}{{ meta_inf.meta_description }}{% endblock %}
{% block meta_title %}{% page_meta_inf page.id as meta_inf %}{% if meta_inf %}{{ meta_inf.meta_title }}{% else %}{{ page.title }}{% endif %}{% endblock %}

{% block content %}
<div id = "wrapper">
<h2>{{ page.title }}</h2>
{{ page.content|safe }}
</div>
{% endblock %}

Как видно, вызов META информации происходит не совсем удобным способом, но я уже писал выше, что мне так больше нравится. :)

Осталось привести код файла меню top_menu.html. Вот он.

Файл top_menu.html

{% load app_pages_tags %}
{% load mptt_tags %}

    {% recursetree pages %}
        <li><a href = "{{ node.get_absolute_url }}" {% if current == node.get_absolute_url %}class = "current"{% endif %}>{{ node.title }}</a>
        {% if not node.is_leaf_node %}
            <ul>
                {{ children }}
            </ul>
        {% endif %}
        </li>
    {% endrecursetree %}

Здесь мы используем шаблонные теги mptt. Это удобно и избавляет нас от необходимости много писать руками. На сегодня все. В следующей(заключительной) части мы добавим карту сайта и переведем наше приложение, также добавим то, о чем я позабыл в самом начале. Спасибо за внимание!

Метки:django, cms, система управления, python