Расширение страниц - заголовки моделей

15 May 2014 г. 17:25:35

Новое в версии 3.0

Вы можете расширить страницу и заголовки моделей при помощи своих собственных полей (Например добавить картинку на каждую страницу) используя модели расширения cms.extensions.PageExtension и cms.extensions.TitleExtension соответственно

Руководство

Привязывание расширений в панели администратора

Добавление элемента Toolbar Menu при расширении страницы

Использование расширений и меню

Использование расширений в шаблонах

Обработка отношений

Руководство

Для добавления полей в модель страницы, надо создать класс который наследуется от cms.extensions.PageExtension. Убедитесь что модель cms.extensions.PageExtension импортирована. Ваш класс должен находится в файле models.py в виде приложения или модуля. Так как PageExtensionTitleExtension) наследуются из django.db.models.Model, вы можете свободно добавлять любые поля, которые захотите, но убедитесь что не используете никакие уникальные ограничения во всех полях. Потому что уникальность препятствует корректной работе механизма копирования расширений. Это зачит что вы не можете использовать отношения один к одному в модели расшенерия. Наконец вам надо зарегистрировать модель при помощи extension_pool.

Вот небольшой пример который добавляет поле icon на страницу.

from django.db import models

from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool

class IconExtension(PageExtension):
    image = models.ImageField(upload_to='icons')

extension_pool.register(IconExtension)

Привязывание расширений в панели администратора

Чтобы сделать Ваше расширение редактируемым, вы должны сначала создать класс admin, наследуя его от cms.extensions.PageExtensionAdmin. Этот класс обрабатывает права доступа к страницам. Если вы хотите использовать собственный класс admin, убедитесь что исключили текущую версию расширения используя в запросе filter(extended_page__publisher_is_draft=True)ю

Продолжая пример модели выше, создадим соответствующий простой класс PageExtensionAdmin класс: from django.contrib import admin from cms.extensions import PageExtensionAdmin

from .models import IconExtension

class IconExtensionAdmin(PageExtensionAdmin):
    pass

admin.site.register(IconExtension, IconExtensionAdmin)

Так как PageExtensionAdmin наследуется от ModelAdmin, Вы можете использовать обычный набора свойств Django из модели ModelAdmin, в зависимости от ваших нужд.

После регистрации класса admin, модель появится на верхнему уровне в списке панели администратора.

Стоит заметить что поле, которое связывает отношение между расширением и CMSPage не редактируемое, поэтому оно не появится в панели администратора. К сожалению это оставляет оператор без связывания как такового, пр расширении конкретной страницы. Способом решения данной проблемы является использование CMSToolbar.

Добавление элемента Toolbar Menu при расширении страницы

Вы так-же можете захотеть сделать вашу модель редактируемой из панели инструментов cms, чтобы связать каждый экземпляр расширения модели со страницей. (По умолчанию страница в панели администратора является не редактируемым атрибутом). Код из примера ниже должен находиться cms_toolbar.py, в одном из ваших приложений и добавляет меню для расширение на каждую страницу:

from cms.api import get_page_draft
from cms.toolbar_pool import toolbar_pool
from cms.toolbar_base import CMSToolbar
from cms.utils import get_cms_setting
from cms.utils.permissions import has_page_change_permission
from django.core.urlresolvers import reverse, NoReverseMatch
from django.utils.translation import ugettext_lazy as _
from .models import IconExtension

@toolbar_pool.register
class IconExtensionToolbar(CMSToolbar):
    def populate(self):
        # always use draft if we have a page
        self.page = get_page_draft(self.request.current_page)

        if not self.page:
            # Nothing to do
            return

        # check global permissions if CMS_PERMISSIONS is active
        if get_cms_setting('PERMISSION'):
            has_global_current_page_change_permission = has_page_change_permission(self.request)
        else:
            has_global_current_page_change_permission = False
            # check if user has page edit permission
        can_change = self.request.current_page and self.request.current_page.has_change_permission(self.request)
        if has_global_current_page_change_permission or can_change:
            try:
                icon_extension = IconExtension.objects.get(extended_object_id=self.page.id)
            except IconExtension.DoesNotExist:
                icon_extension = None
            try:
                if icon_extension:
                    url = reverse('admin:myapp_iconextension_change', args=(icon_extension.pk,))
                else:
                    url = reverse('admin:myapp_iconextension_add') + '?extended_object=%s' % self.page.pk
            except NoReverseMatch:
                # not in urls
                pass
            else:
                not_edit_mode = not self.toolbar.edit_mode
                current_page_menu = self.toolbar.get_or_create_menu('page')
                current_page_menu.add_modal_item(_('Page Icon'), url=url, disabled=not_edit_mode)

Теперь, при вызове оператора “Edit this page” из панели инструментов, там будет дополнительный элемент меню (в нашем случае Page Icon), который будет использован для открытия диалога, где оператор может изменить поле icon

Обратите внимание, когда расширение сохранено, страница будет отмечена что у нее есть неопубликованные изменения. Чтобы увидеть изменения необходимо опубликовать страницу.

Использование расширений и меню

Если вы хотите расширить возможности отображаемого меню (например, если вы создали расширение которое добавляет изображение на страницу) используйте свойства меню. Каждое свойство node.id соответствует связанному page.id. Чтобы получить объект страницы можно воспользоваться Page.objects.get(pk=node.id). Каждое расширение страницы имеет отношение один-к-одному со страницей, к которой у вас есть доступ при помощи обратного отношения, например: extension = page.yourextensionlowercased. Теперь вы можете связать расширение сохраняя его в узле node.extension = extension. У вас есть доступ к изображению в шаблоне меню из дочернего объекта child.extension.icon.

Использование расширений в шаблонах

Чтобы получить доступ к расширению из шаблона вы можете просто воспользоваться соответствующим полем related_name которое теперь доступно в объекте Page.

Как и в обычном механизме имен в Django, соответствующее поле имеет такое-же название как и PageExtension, в нижнем регистре. Таким образом, модель вашего расширения называется IconExtension, и из оно страницы будет доступно через *page.iconextension, поэтому вы можете использовать что-то вроде:

{% load staticfiles %}

{# rest of template omitted ... #}

{% if request.current_page.iconextension %}
    <img src="{% static request.current_page.iconextension.url %}">
{% endif %}

Где для получения доступа к текущей странице, из которой был вызван шаблон, получаем через request.current_page

Важно помнить что пока оператор используемый на странице не связан со всеми страницами, у страницы может не быть доступа к отношению iconexension, используемого в блоке {% if ... %}...{% endif %} выше.

Обработка отношений

Если ваше расширение PageExtension или TitleExtension использует внешний ключ из другой модели или использует отношение многий-ко-многим через поле ManyToMan, то вы также должны переопределить метод copy_relations(self, oldinstance, language), чтобы поля были скопированы соответствующим образом, когда CMS выполняет копирование вашего расширения при поддержке версионности и т.д.

from django.db import models
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool

class MyPageExtension(PageExtension):

    page_categories = models.ManyToMany('categories.Category', blank=True, null=True)

    def copy_relations(self, oldinstance, language):
        for page_category in oldinstance.page_categories.all():
            page_category.pk = None
            page_category.mypageextension = self
            page_category.save()

extension_pool.register(MyPageExtension)

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

comments powered by Disqus
Меню

Cult of digits 2014 Яндекс.Метрика