Spec-Zone.ru › Wagtail 2

Сниппеты

Сниппеты — это фрагменты контента, для отображения которых не требуется полная веб-страница. Их можно использовать для создания вторичного контента, такого как заголовки, подвалы и боковые панели, которые можно редактировать в админке Wagtail. Сниппеты — это модели Django, которые не наследуют класс Page и поэтому не организованы в дереве Wagtail. Однако их можно сделать редактируемыми, назначив панели и определив модель как сниппет с помощью декоратора класса register_snippet.

У сниппетов отсутствуют многие функции страниц, такие как возможность упорядочения в админке Wagtail или определение URL. Тщательно решите, подходит ли тип контента, который вы хотите создать в виде сниппета, для страницы.

Модели сниппетов

Вот пример модели сниппета:

from django.db import models

from wagtail.admin.edit_handlers import FieldPanel
from wagtail.snippets.models import register_snippet

...

@register_snippet
class Advert(models.Model):
    url = models.URLField(null=True, blank=True)
    text = models.CharField(max_length=255)

    panels = [
        FieldPanel('url'),
        FieldPanel('text'),
    ]

    def __str__(self):
        return self.text

Модель Advert использует базовый класс модели Django и определяет два свойства: текст и URL. Интерфейс редактирования очень похож на интерфейс для моделей, наследуемых от Page, с полями, заданными в свойстве panels. Сниппеты не используют несколько вкладок с полями, а также не предоставляют функций «сохранить как черновик» или «отправить на модерацию».

@register_snippet сообщает Wagtail, что модель должна обрабатываться как сниппет. Список panels определяет поля, которые должны отображаться на странице редактирования сниппета. Также важно предоставить строковое представление класса через def __str__(self):, чтобы объекты сниппетов были понятны при отображении в админке Wagtail.

Включение сниппетов в теги шаблонов

Самый простой способ сделать ваши сниппеты доступными для шаблонов — это использование тега шаблона. Это в основном делается с помощью стандартного Django, поэтому, возможно, будет полезно ознакомиться с документацией Django по настраиваемым тегам шаблонов Django. Тем не менее, мы рассмотрим основы и отметим моменты, которые следует учесть для Wagtail.

Сначала добавьте новый файл Python в папку templatetags вашего приложения — например, myproject/demo/templatetags/demo_tags.py. Нам нужно будет загрузить некоторые модули Django и модели вашего приложения, а также подготовить декоратор register:

from django import template
from demo.models import Advert

register = template.Library()

...

# Advert snippets
@register.inclusion_tag('demo/tags/adverts.html', takes_context=True)
def adverts(context):
    return {
        'adverts': Advert.objects.all(),
        'request': context['request'],
    }

@register.inclusion_tag() принимает два параметра: шаблон и булево значение, определяющее, должен ли этот шаблон получать контекст запроса. Включать контекст запроса в свои пользовательские теги шаблонов — хорошая идея, поскольку некоторые теги шаблонов, специфичные для Wagtail, например, pageurl, нуждаются в контексте для корректной работы. Функция тега шаблона может принимать аргументы и фильтровать объявления, чтобы вернуть конкретный экземпляр модели, но для краткости мы будем использовать Advert.objects.all().

Вот содержимое шаблона, используемого этим тегом шаблона:

{% for advert in adverts %}
    <p>
        <a href="{{ advert.url }}">
            {{ advert.text }}
        </a>
    </p>
{% endfor %}

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

{% load wagtailcore_tags demo_tags %}

...

{% block content %}

    ...

    {% adverts %}

{% endblock %}

Связывание страниц со сниппетами

В приведенном выше примере список объявлений — это фиксированный список, который отображается с помощью пользовательского тега шаблона независимо от другого контента на странице. Возможно, это то, что вам нужно для общей панели на боковой панели, но в другом случае вы можете захотеть отобразить только один конкретный экземпляр сниппета на определенной странице. Это можно сделать, определив внешний ключ к модели сниппета в модели вашей страницы и добавив SnippetChooserPanel в список content_panels страницы. Например, если вы хотите отобразить конкретное объявление на экземпляре BookPage:

from wagtail.snippets.edit_handlers import SnippetChooserPanel
# ...
class BookPage(Page):
    advert = models.ForeignKey(
        'demo.Advert',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    content_panels = Page.content_panels + [
        SnippetChooserPanel('advert'),
        # ...
    ]

Затем к сниппету можно обратиться в шаблоне как к page.advert.

Чтобы прикрепить несколько объявлений к странице, SnippetChooserPanel можно поместить на встроенный дочерний объект BookPage, а не на BookPage само по себе. Здесь эта дочерняя модель называется BookPageAdvertPlacement (так названа потому, что существует один такой объект для каждого случая размещения объявления на BookPage):

from django.db import models

from wagtail.core.models import Page, Orderable
from wagtail.snippets.edit_handlers import SnippetChooserPanel

from modelcluster.fields import ParentalKey

...

class BookPageAdvertPlacement(Orderable, models.Model):
    page = ParentalKey('demo.BookPage', on_delete=models.CASCADE, related_name='advert_placements')
    advert = models.ForeignKey('demo.Advert', on_delete=models.CASCADE, related_name='+')

    class Meta(Orderable.Meta):
        verbose_name = "advert placement"
        verbose_name_plural = "advert placements"

    panels = [
        SnippetChooserPanel('advert'),
    ]

    def __str__(self):
        return self.page.title + " -> " + self.advert.text


class BookPage(Page):
    ...

    content_panels = Page.content_panels + [
        InlinePanel('advert_placements', label="Adverts"),
        # ...
    ]

Теперь к этим дочерним объектам можно получить доступ через свойство страницы advert_placements, а оттуда мы можем получить доступ к связанному сниппету объявления как к advert. В шаблоне для BookPage мы могли бы включить следующее:

{% for advert_placement in page.advert_placements.all %}
    <p>
        <a href="{{ advert_placement.advert.url }}">
            {{ advert_placement.advert.text }}
        </a>
    </p>
{% endfor %}

Делаем сниппеты подлежащими поиску

Если модель сниппета наследует от wagtail.search.index.Indexed, как описано в индексировании пользовательских моделей, Wagtail автоматически добавит поле поиска в интерфейс выбора для этого типа сниппета. Например, сниппет Advert можно сделать подлежащим поиску следующим образом:

...

from wagtail.search import index

...

@register_snippet
class Advert(index.Indexed, models.Model):
    url = models.URLField(null=True, blank=True)
    text = models.CharField(max_length=255)

    panels = [
        FieldPanel('url'),
        FieldPanel('text'),
    ]

    search_fields = [
        index.SearchField('text', partial_match=True),
    ]

Тегирование сниппетов

Добавление тегов к сниппетам очень похоже на добавление тегов к страницам. Единственное различие в том, что taggit.manager.TaggableManager следует использовать вместо ClusterTaggableManager.

from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from taggit.models import TaggedItemBase
from taggit.managers import TaggableManager

class AdvertTag(TaggedItemBase):
    content_object = ParentalKey('demo.Advert', on_delete=models.CASCADE, related_name='tagged_items')

@register_snippet
class Advert(ClusterableModel):
    ...
    tags = TaggableManager(through=AdvertTag, blank=True)

    panels = [
        ...
        FieldPanel('tags'),
    ]

В документации по тегированию страниц есть больше информации о том, как использовать теги в представлениях.

  • Предыдущая Бэкэнды
  • Следующая Как использовать StreamField для смешанного контента

Содержание страницы

  • Сниппеты
    • Модели сниппетов
    • Включение сниппетов в теги шаблонов
    • Связывание страниц со сниппетами
    • Делаем сниппеты подлежащими поиску
    • Тегирование сниппетов

© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/v2.16.3/topics/snippets.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API