Фрагменты
Фрагменты — это фрагменты контента, для отображения которых не требуется полная веб-страница. Они могут использоваться для создания вторичного контента, такого как заголовки, подвалы и боковые панели, редактируемые в административной панели Wagtail. Фрагменты представляют собой модели Django, которые не наследуют класс Page и поэтому не организованы в дереве Wagtail. Однако их можно сделать редактируемыми, назначив панели и определив модель как фрагмент с помощью декоратора класса register_snippet.
Фрагменты лишены многих функций страниц, таких как возможность упорядочения в административной панели Wagtail или определения URL-адреса. Внимательно решите, подходит ли тип контента, который вы хотите создать как фрагмент, для страницы.
Модели фрагментов
Вот пример модели фрагмента:
from django.db import models
from wagtail.admin.panels 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.
Связывание страниц с фрагментами
В приведенном выше примере список объявлений — это фиксированный список, отображаемый с помощью настраиваемого тега шаблона независимо от другого контента на странице. Это может быть то, что вам нужно для общей панели на боковой панели, но в другом случае вы можете захотеть отобразить только один конкретный экземпляр фрагмента на определенной странице. Этого можно добиться, определив внешний ключ для модели фрагмента в модели вашей страницы и добавив FieldPanel в список content_panels страницы. Например, если вы хотите отобразить определенное объявление на экземпляре BookPage.
# ...
class BookPage(Page):
advert = models.ForeignKey(
'demo.Advert',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
content_panels = Page.content_panels + [
FieldPanel('advert'),
# ...
]
Затем к фрагменту можно обратиться в шаблоне как к page.advert.
Чтобы прикрепить несколько объявлений к странице, FieldPanel можно поместить на вложенный дочерний объект BookPage вместо BookPage. Здесь эта дочерняя модель называется BookPageAdvertPlacement (так названа потому, что существует такой объект каждый раз, когда объявление размещается на странице BookPage):
from django.db import models
from wagtail.models import Page, Orderable
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 = [
FieldPanel('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'),
]
В документации по разметке страниц содержится дополнительная информация о том, как использовать теги в представлениях.
© 2014-present Torchbox Ltd and individual contributors.
All rights are reserved.
Licensed under the BSD License.
https://docs.wagtail.org/en/v3.0.3/topics/snippets.html