• en
  • Language: ru
  • 3.7.x
  • Documentation version: 3.9

Как использовать заполнители за пределами CMS

Placeholders - это специальные поля модели, которые django CMS использует для отображения редактируемого пользователем контента (плагинов) в шаблонах. То есть, это место, где пользователь может добавить текст, видео или любой другой плагин на веб-страницу, используя то же фронтенд-редактирование, что и страницы CMS.

Placeholders можно рассматривать как контейнеры для экземпляров CMSPlugin, и их можно использовать вне CMS в пользовательских приложениях, используя PlaceholderField.

Определив один (или несколько) PlaceholderField в пользовательской модели, вы можете воспользоваться всеми возможностями CMSPlugin.

Приступить к работе

Вам необходимо определить PlaceholderField на модели, которую вы хотите использовать:

from django.db import models
from cms.models.fields import PlaceholderField

class MyModel(models.Model):
    # your fields
    my_placeholder = PlaceholderField('placeholder_name')
    # your methods

У PlaceholderField есть один обязательный параметр - строка slotname.

slotname используется в шаблонах, чтобы определить, в каком месте страницы должны появиться плагины placeholder, и в конфигурации placeholder CMS_PLACEHOLDER_CONF, которая определяет, какие плагины могут быть вставлены в этот placeholder.

Вы также можете использовать вызываемую переменную для slotname, как в:

from django.db import models
from cms.models.fields import PlaceholderField

def my_placeholder_slotname(instance):
    return 'placeholder_name'

class MyModel(models.Model):
    # your fields
    my_placeholder = PlaceholderField(my_placeholder_slotname)
    # your methods

Предупреждение

В целях безопасности имя related_name для PlaceholderField не может быть подавлено с помощью '+'; это позволяет cms правильно проверять разрешения. Попытка сделать это вызовет ошибку ValueError.

Примечание

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

Интеграция администратора

Изменено в версии 3.0.

Ваша модель с PlaceholderFields все еще может быть отредактирована в админке. Однако, любые поля PlaceholderFields в ней будут только доступны для редактирования из фронтенда. PlaceholderFields должен не присутствовать ни в одном атрибуте определения поля fieldsets, fields, form или другого ModelAdmin.

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

from django.contrib import admin
from cms.admin.placeholderadmin import PlaceholderAdminMixin
from myapp.models import MyModel

class MyModelAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
    pass

admin.site.register(MyModel, MyModelAdmin)

I18N Placeholders

Из коробки PlaceholderAdminMixin поддерживает несколько языков и отображает языковые вкладки. Если вы расширите свою модель класса администратора, полученного из PlaceholderAdminMixin и перепишите change_form_template, посмотрите admin/placeholders/placeholder/change_form.html, чтобы увидеть, как отображать языковые вкладки.

Если вам нужно перевести и другие поля, в django CMS есть поддержка django-hvad. Если вы используете модель TranslatableModel, убедитесь, что не включаете поля-заполнители в число переведенных полей:

class MultilingualExample1(TranslatableModel):
    translations = TranslatedFields(
        title=models.CharField('title', max_length=255),
        description=models.CharField('description', max_length=255),
    )
    placeholder_1 = PlaceholderField('placeholder_1')

    def __unicode__(self):
        return self.title

Убедитесь, что при регистрации модели в админке вы объединили оба значения TranslatableAdmin и PlaceholderAdminMixin:

from cms.admin.placeholderadmin import PlaceholderAdminMixin
from django.contrib import admin
from hvad.admin import TranslatableAdmin
from myapp.models import MultilingualExample1

class MultilingualModelAdmin(TranslatableAdmin, PlaceholderAdminMixin, admin.ModelAdmin):
    pass

admin.site.register(MultilingualExample1, MultilingualModelAdmin)

Шаблоны

Для отображения заполнителя в шаблоне используется тег render_placeholder из библиотеки тегов шаблонов cms_tags:

{% load cms_tags %}

{% render_placeholder mymodel_instance.my_placeholder "640" %}

Тег render_placeholder принимает следующие параметры:

  • PlaceholderField экземпляр

  • width параметр для контекстно-зависимых плагинов (необязательно)

  • language ключевое слово плюс language-code строка для отображения содержимого на указанном языке (необязательно)

Представление, в котором вы отображаете ваше поле-заполнитель, должно возвращать объект request в контексте. Обычно это достигается в приложениях Django с помощью RequestContext:

from django.shortcuts import get_object_or_404, render

def my_model_detail(request, id):
    object = get_object_or_404(MyModel, id=id)
    return render(request, 'my_model_detail.html', {
        'object': object,
    })

Если вы хотите выводить плагины с определенного языка, вы можете использовать тег следующим образом:

{% load cms_tags %}

{% render_placeholder mymodel_instance.my_placeholder language 'en' %}

Добавление содержимого к заполнителю

Изменено в версии 3.0.

Placeholders можно редактировать из фронтенда, посетив страницу, отображающую вашу модель (где вы поместили тег render_placeholder), затем добавив ?edit к URL страницы.

Это приведет к появлению верхнего баннера редактора фронтенда (и при необходимости потребует входа в систему).

В режиме фронтенд-редактирования интерфейс для PlaceholderFields вашего приложения будет работать примерно так же, как и для CMS Pages, с переключением режимов Structure и Content и так далее.

Для общих моделей Django не существует функции автоматического черновика/оживления, поэтому содержимое обновляется мгновенно, когда вы добавляете/редактируете его.

Опции

Если вам нужно изменить ?edit на пользовательскую строку (скажем, ?admin_on), вы можете установить переменную CMS_TOOLBAR_URL__EDIT_ON в вашей settings.py на "admin_on".

Вы также можете изменить другие URL-адреса с аналогичными настройками:

  • ?edit_off (CMS_TOOLBAR_URL__EDIT_OFF)

  • ?build (CMS_TOOLBAR_URL__BUILD)

  • ?toolbar_off (CMS_TOOLBAR_URL__DISABLE)

При изменении этих параметров, пожалуйста, будьте осторожны, поскольку вы можете случайно заменить зарезервированные строки в системе (например, ?page). Мы рекомендуем вам использовать безопасные уникальные строки для этой опции (например, secret_admin или company_name).

Разрешения

Чтобы иметь возможность редактировать заполнитель, пользователь должен быть членом staff и должен иметь права на редактирование модели, которая содержит PlaceholderField, или права для конкретного экземпляра этой модели. Необходимыми разрешениями для действий редактирования являются:

  • к add: требуется add или change разрешение на связанную Модель или экземпляр.

  • к change: требуется add или change разрешение на связанную Модель или экземпляр.

  • к delete: требуется add или change или delete разрешение на связанную Модель или экземпляр.

С помощью этой логики пользователь, который может change экземпляр Модели, но не может add новый экземпляр Модели, сможет добавить некоторые заполнители или плагины к существующим экземплярам Модели.

Разрешения модели обычно добавляются через стандартное приложение Django auth и его интерфейс администратора. Разрешения на уровне объектов могут быть обработаны путем написания пользовательского бэкенда аутентификации, как описано в django docs.

Например, если есть UserProfile модель, которая содержит PlaceholderField, то пользовательский бэкенд может обратиться к has_perm методу (на модели), который предоставляет все права только текущему пользователю на основе UserProfile объекта пользователя:

def has_perm(self, user_obj, perm, obj=None):
    if not user_obj.is_staff:
        return False
    if isinstance(obj, UserProfile):
        if user_obj.get_profile()==obj:
            return True
    return False