20 сентября 2013 г.

Добавляем некоторые "плюшки" в FeinCMS

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

Расширения FeinCMS

Первое, что хотелось бы отметить, это расширения самой модели Page - модули расширения. В комплекте идет changedate, ct_tracker, datepublisher, excerpt, featured, navigation, relatedpages, seo, sites, symlinks, titles, translations. Обо всех них можно прочитать в документации. При добавлении

Page.register_extensions('navigation', 'seo', 'titles',)

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

Второе - то что будет предметом этой статьи - типы содержимого. Это отдельные таблицы, поэтому после добавления какого-нибудь типа достаточно родной джанговской syncdb. В первой статье был добавлен самый простейший тип feincms.content.raw.models.RawContent, который позволяет добавлять к странице "сырое", необрабатываемое ничем содержимое. Т.е. чистый HTML, CSS, Javascript.

RichTextContent

Это не всегда нужно. Иногда мы создаем управление содержимым для обычных пользователей, которые не искушены в вопросах web-технологий. Для них подойдет feincms.content.richtext.models.RichTextContent. По сути - то же содержимое, но вводимое через дружественный интерфейс WYSIWYG'а. В комплекте FeinCMS идет поддержка TinyMCE.

Давайте добавим RichTextContent содержимое. Качаем 3 версию TinyMCE. Разархивируем её в feinpro/static/js/tinymce (т.е. файл tiny_mce.js должен быть именно в этой директории). В feinpro/feinpro/settings.py добавляем

FEINCMS_RICHTEXT_INIT_CONTEXT = {
    'TINYMCE_JS_URL': STATIC_URL + 'js/tinymce/tiny_mce.js',
}

В feinpro/feinpro/models.py добавляем:

#...
from feincms.content.richtext.models import RichTextContent
#...
Page.create_content_type(RichTextContent)

Создаем таблицу:

python feinpro/manage.py syncdb

Теперь можно зайти в админку и добавить содержимое через WYSIWYG.

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

TemplateContent

Еще одним полезным типом содержимого я посчитал для себя TemplateContent. Здесь всё очень просто. В папке шаблонов создаем папку content/template в которой приложение будет "шарить" шаблоны и при добавлении данного типа содержимого вы можете выбрать любой из них. Не забываем syncdb.

Замечу, что не все шаблоны имен файлов распознаются (фича) и шаблонный контекст в них общий. А вот если вам нужно какое-то особенное поведение, то здесь уже стоит посмотреть в сторону типа содержимого feincms.content.application.models.ApplicationContent, которое позволяет интегрировать любое ваше (и не только) приложение (в терминах джанги).

ApplicationContent

Для того, чтобы разобраться с тем, как работает этот тип содержимого, давайте создадим стандартное для джанги минимальное приложение - entries:

$ cd /path/to/devarea/feincookie
$ source bin/activate # for win: Scripts\activate
$ mkdir feinpro/entries feinpro/templates/entries
$ touch feinpro/entries/__init__.py feinpro/entries/models.py feinpro/entries/admin.py feinpro/entries/views.py feinpro/entries/urls.py feinpro/templates/entrie/list.html feinpro/templates/entrie/detail.html

Содержимое py файлов:

# models.py ############################################
from django.db import models

class Entry(models.Model):
    title = models.CharField(max_length=255)
    created = models.DateTimeField(auto_now_add=True)

    __unicode__ = lambda: self.title

# admin.py #############################################
from .models import Entry
from django.contrib import admin

admin.site.register(Entry)

# views.py #############################################
from django.views.generic import DetailView, ListView
from .models import Entry

class EntryList(ListView):
    queryset = Entry.objects.order_by('-created')[:100]
    context_object_name = 'entry_list'
    template_name = 'entries/list.html'

class EntryDetail(DetailView):
    model = Entry
    context_object_name = 'entry'
    template_name = 'entries/detail.html'

# urls.py ##############################################
from django.conf.urls import patterns, url
from .views import EntryList, EntryDetail

urlpatterns = patterns('entries.views',
    url(r'^$', EntryList.as_view(), name='entry-list'),
    url(r'^(?P<pk>\d+)/$', EntryDetail.as_view(), name='entry-detail'),
)

Содержимое html файлов:

<!-- list.html -->
<h1>Entries</h1>
<ul>
{% for entry in entry_list %}
    <li><a href="{% url entry-detail entry.pk %}">{{ entry.title }} <small>{{ entry.created }}</small></a></li>
{% endfor %}
</ul>

<!-- detail.html -->
<h1>{{ entry.title }}</h1>
<p>{{ entry.created }}</p>

Не забудем добавить приложение entries в settings.py в INSTALLED_APPS и сделать syncdb. А также добавить url(r'^entries/', include('entries.urls')), в основной urls.py.

Проверьте, что новое приложение работает. Если всё "ок", то для встраивания типа содержимого ApplicationContent будет достаточно в моделях feinpro/models.py добавить:

#...
from feincms.content.application.models import ApplicationContent
#...
Page.create_content_type(ApplicationContent, APPLICATIONS=(
    ('entries.urls', u'Записи'),
))

и сделать syncdb. Теперь, например, если страница FeinCMS находится по URL /home/ и вы добавите содержимое ApplicationContent, то по /home/ будет доступен список записей, а по /home/{pk}/ детализация каждой из записей. Здесь надо оговориться, что урлы приложения etries будут по-прежнему доступны, т.е. при использовании шаблонного тега url всё будет работать, но если вы хотите зароутить подурлы приложения entries в путь страницы, на которой размещается приложение, то вам нужно использовать наборы из applicationcontent_tags.

Другие типы содержимого

Также, можно создать свой тип содержимого. Достаточно определить абстрактную модель с переопределенным методом render, возвращающим юникод и не выбрасывающим исключений и присоеденить эту модель к Page:

Page.create_content_type(YourCustomContentModel)

Есть еще несколько готовых полезных "батареек" типов содержимого: ContactFormContent, FileContent, ImageContent, MediaFileContent, RSSContent, SectionContent, TableContent, VideoContent полезных в той или иной степени. Каждый из них можно и нужно использовать, там где это требуется.

Комментариев нет:

Отправить комментарий