Feincms. Подключение новых модулей

9 Июн
2012

Хотя эта тема и раскрыта в документации, у меня ушло некоторое время чтобы разобраться и всё понять.

Вся структура сайта, созданного на feincms, состоит из страниц. У страницы может быть родитель. Если его нет то это страница верхнего уровня, отобразится в навигации с level=1. Страница может быть “В навигации”, что означает её появление на сайте в месте тэгов:
{% feincms_navigation of feincms_page as toplevel level=1 %}
{% for p in toplevel %}{% endfor %}, где p — экземпляр объекта-страницы со всеми его полями (например, get_absolute_url и title).
feincms_page, как можно понять, текущая страница. Похожим образом можно делать навигацию для дочерних страниц текущей или любой другой.
Приложения добавляются не напрямую в структуру URLов сайта, а через страницы. То есть мы добавляем страницу /blog/, через админку добавляем туда элемент “содержимое из приложения” и выбираем из какого именно. Попытаюсь объяснить что происходит уже при отображении этой страницы.
Допустим, адрес нашей страницы /blog/. На эту страницу мы добавили приложение blog, поставляемое в комплекте с cms. Feincms откроет urls.py этого приложения (как его подключить — дальше) и начнёт проходить по нему в поисках подходящего адреса, при этом обрезав от текущего URL адрес этой страницы. Например, при переходе на страницу /blog/ адрес, который она ищет, будет “”, а при /blog/entry1/ — “entry1/”. После нахождения нужной строки выполняется соответствующая вьюшка и результат вставляется на нужное место на странице.
Пример типичного urls.py для такого приложения:

from feincms.module.blog.models import Entry
info_dict = {
'queryset': Entry.objects.all(),
}
urlpatterns = patterns('',
url(r'^(?P<object_id>\d+)/', # эта строка выберется на адресах вроде /blog/entry-olala/
'feincms.views.generic.list_detail.object_detail',
info_dict, name = 'blog_entry_details'),
url(r'^$', # а эта только на /blog/
'feincms.views.generic.list_detail.object_list',
info_dict, name = 'blog_entry_list'),
)

По умолчанию он будет искать шаблоны templates/app_name/entry_detail.html & templates/app_name/entry_list.html. Можно их открыть и посмотреть что там пишут для приложения-блогов. В их варианте там кусок HTML без заголовков, готовый к вставке в нужное место страницы.
Важная мысль, которую надо отсюда вывести — нельзя подключать urls.py приложений напрямую, и надо писать в них относительные адреса, а не полные. Эти адреса будут отсчитаны от URL страницы, на которую добавлено приложение, и могут охватывать любую глубину — но вверх лезть не могут.
Подключение модулей. Инициализация конктретного сайта обычно выполняется из models.py в корне проекта. По умолчанию там загружается модель для всех простых страниц, им назначаются типы содержимого (простой текст, картиночка, rich text) и на них навешиваются приложения. Из коробки это только приложение blog, но можно добавлять и свои.
Делается это так:
Page.create_content_type(ApplicationContent, APPLICATIONS=(
('news.urls', 'News', {'admin_fields': get_admin_fields}),
('blog_urls', 'Blog', {'admin_fields': get_admin_fields}),
….
))

Тут как раз и надо указать путь до urls.py с нашими относительными урлами.
Потом каждое созданное приложение надо немножечко инициализировать, для блога это:
from feincms.module.blog.models import Entry, EntryAdmin
Entry.register_regions(
('main', 'Main region'),
)
Entry.create_content_type(RawContent)
Entry.create_content_type(RichTextContent)
Entry.create_content_type(ImageContent, POSITION_CHOICES=(
('default', 'Default position'),
))

Этот код:
1) Указывает, что у каждого объекта-блога будет один регион для пользовательских данных (замечу что в самой модели нету ничего похожего на поле text, пользователь добавляет свой контент именно в эти регионы). Можно создать два. Например, для страницы их два — тело страницы и sidebar, а для моего приложения новостей — текст новости и кратенькая аннотация для отображения в списке новостей. Feincms полностью берёт на себя работу с этими регионами, думать как пользователь туда будет добавлять текст/картинки нам не надо. И это очень радует.
2) Указывает, какие типы содержимого будут на странице. В примере мы разрешаем использовать простой текст, форматированный текст (к которому привяжется WYSWYG-редактор tinymce с минималистичным интерфейсом) и картинки.
Обращаю внимание на то что здесь Entry — это модель конкретной записи блога. По-уму оно должно называться BlogEntrу.
После запуска на страницах (Page) можно будет добавлять приложения (blog, news в данном случае), которые смогут возвращать свой контент пользователю.
Теперь к созданию собственного приложения. Там надо соблюсти некоторые формальности, описанные в документации www.feinheit.ch/media/labs/feincms/integration.html.
Это:
1. urls.py с относительными адресами
2. models.py — модели c объявленными get_absolute_url и декоратром @app_models.permalink
views, на которые ссылаются строки urls.py, могут вернуть или текст, или полноценный HttpResponse. В первом случае текст вставится в нужное место на странице, во втором — ответ вернётся клиенту без каких-либо изменений.
Для того чтобы вновь созданные модели появились в админке admin.py нужно тоже писать по-своему. Вот пример для приложения с новостями:
from django.contrib import admin
from feincms.admin import item_editor
from models import NewsEntry
class NewsEntryAdmin(item_editor.ItemEditor):
date_hierarchy = 'published_on'
list_display = ('__unicode__', 'published', 'published_on')
list_filter = ('published',)
search_fields = ('title', 'slug',)
prepopulated_fields = {
'slug': ('title',),
}
raw_id_fields = []
admin.site.register(NewsEntry, NewsEntryAdmin)

Разницу можно заметить в наследовании класса от feincms.admin.item_editor.ItemEditor, он-то и должен обеспечить подключение всего необходимого для редактирования регионов в нашей модели.

По материалам Хабрахабр.



загрузка...

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

Наверх