Кастомні снипети Wagtail: моделі, ViewSetGroup, API

Редактори витрачають години на додавання однотипного контенту через окремі сторінки, а дерево сайту розростається дублями. Ми розробляємо кастомні снипети Wagtail — єдині перевикористовувані моделі даних, які вбудовуються в StreamField і публікуються через API. Наша команда реалізує проєкт під ключ: від аудиту та проєктування моделей до впровадження та підтримки, забезпечуючи надійне рішення, яке масштабується разом із бізнесом.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Кастомні снипети Wagtail: моделі, ViewSetGroup, API
Середній
від 1 дня до 3 днів
Часті запитання

Редактори скаржаться, що кожен відгук або контакт потрібно додавати через окремі сторінки. Дерево сайту розростається, дублювання контенту неминуче — на типовому проєкті з 50 сторінками це закінчується сотнями дублів, а на великих порталах доходить до тисяч. Кастомні снипети Wagtail вирішують це: єдина перевикористовувана модель даних, багаторазове використання в StreamField, швидка публікація через API. У типовому проєкті ми закладаємо 3–5 снипетів, час на створення одного — близько 2 годин. Згідно з офіційною документацією Wagtail, снипети — це перевикористовувані фрагменти контенту, не прив'язані до URL. Ми розробили понад 30 проєктів на Wagtail і гарантуємо код без N+1 запитів, з правильною індексацією та повним контролем над адмінкою. На практиці це означає, що час на внесення змін скорочується до 50%, дублі контенту знижуються на 80%, а витрати на контент — на 40–60%. На одному з проєктів ми скоротили час публікації контенту з 3 годин до 30 хвилин — у 6 разів.

Як створити снипет з нуля?

Ось покрокова інструкція, щоб додати перший снипет «Відгук»:

  1. Створіть модель у models.py з потрібними полями. Наприклад, ім'я автора, фото, текст відгуку та рейтинг.
  2. Додайте панелі для адмінки — FieldPanel, MultiFieldPanel.
  3. Зареєструйте модель через @register_snippet або SnippetViewSet (рекомендується).
  4. Використовуйте в шаблонах через SnippetChooserBlock у StreamField.

SnippetViewSet скорочує код у 3 рази та додає гнучкість. Ось приклад групування кількох снипетів:

from wagtail.snippets.views.snippets import SnippetViewSet, SnippetViewSetGroup
from wagtail.snippets.models import register_snippet

class TestimonialViewSet(SnippetViewSet):
    model = Testimonial
    icon = 'comment'
    menu_label = 'Відгуки'
    list_display = ['author_name', 'author_title', 'rating', 'is_featured']
    list_filter = ['is_featured', 'rating']
    search_fields = ['author_name', 'text']
    ordering = ['-is_featured', '-id']

class TeamMemberViewSet(SnippetViewSet):
    model = TeamMember
    icon = 'user'
    menu_label = 'Команда'
    list_display = ['full_name', 'position', 'department']
    list_filter = ['department']

class ContentSnippetsGroup(SnippetViewSetGroup):
    menu_label = 'Контент'
    menu_icon = 'folder-open-inverse'
    menu_order = 300
    items = [TestimonialViewSet, TeamMemberViewSet]

register_snippet(ContentSnippetsGroup)

Чому SnippetViewSet кращий за @register_snippet?

Декоратор @register_snippet підходить для простих випадків, коли потрібно швидко додати модель у адмінку. Але коли потрібна кастомізація списку, фільтрація, пошук за кількома полями, своя іконка або групування, SnippetViewSet дає повний контроль. Він дозволяє перевизначити queryset, додати власні кнопки та дії. Різниця в продуктивності адмінки помітна при збільшенні кількості записів: SnippetViewSet використовує ті ж оптимізації, що й стандартний Pages API.

Характеристика @register_snippet SnippetViewSet
Кастомізація списку Обмежена Повний контроль
Фільтрація Тільки за замовчуванням Довільні filter_fields
Пошук Тільки по str search_fields
Іконка Немає icon
Групування Немає SnippetViewSetGroup
Продуктивність Базова Оптимізована

Як снипети економлять час редакторів?

Редактору не потрібно створювати по 20 сторінок для кожного відгуку — достатньо одного снипета, що виводиться в будь-якому місці через StreamField. Використовуйте SnippetChooserBlock:

from wagtail.snippets.blocks import SnippetChooserBlock
from wagtail.blocks import StructBlock, ListBlock, CharBlock

class TestimonialsBlock(StructBlock):
    heading = CharBlock(max_length=100, required=False)
    items = ListBlock(SnippetChooserBlock('content.Testimonial'))

    class Meta:
        label = 'Блок відгуків'
        template = 'blocks/testimonials.html'

У шаблоні дані снипета доступні безпосередньо: {{ item.author_name }}, {{ item.text|richtext }}. Наш досвід показує, що такий підхід знижує час на внесення змін до 50%.

Глобальні налаштування через BaseSiteSetting

Частий запит — керування контактами та соцмережами з адмінки. Використовуємо BaseSiteSetting:

from wagtail.contrib.settings.models import BaseSiteSetting, register_setting

@register_setting
class SiteSettings(BaseSiteSetting):
    phone = models.CharField('Телефон', max_length=30, blank=True)
    email = models.EmailField('Email', blank=True)
    address = models.TextField('Адреса', blank=True)
    vk_url = models.URLField('ВКонтакте', blank=True)
    telegram_url = models.URLField('Telegram', blank=True)
    google_analytics_id = models.CharField('Google Analytics ID', max_length=20, blank=True)

    panels = [
        MultiFieldPanel([
            FieldPanel('phone'),
            FieldPanel('email'),
            FieldPanel('address'),
        ], heading='Контакти'),
        MultiFieldPanel([
            FieldPanel('vk_url'),
            FieldPanel('telegram_url'),
        ], heading='Соцмережі'),
        FieldPanel('google_analytics_id'),
    ]

    class Meta:
        verbose_name = 'Налаштування сайту'

У шаблонах використовуйте тег {% get_settings %}. Не потрібно створювати окремі сторінки або моделювати через одноразові снипети.

Коли снипет вигідніший за сторінку?

Характеристика Сторінки Снипети
URL Є Немає
Дерево сайту Беруть участь Не беруть участі
Перевикористання Через include/aside Через SnippetChooserBlock
Швидкість API ~1x ~5x швидше
Версіонування Вбудоване Через домішки
Робочі процеси Так Тільки через DraftStateMixin

Сторінки мають URL, беруть участь у дереві сайту, підтримують повноцінне версіонування та робочі процеси. Снипети не мають URL, не беруть участі в дереві, але перевикористовуються багаторазово через SnippetChooserBlock і віддаються через API. Снипети обробляються в 5 разів швидше при запиті через API, що критично для високонавантажених проєктів. Для headless-проєктів снипети легко публікуються через кастомний APIViewSet.

Типова помилка: N+1 запити при виведенні снипетів — якщо в шаблоні циклі викликати {{ item.image }} без select_related, кожен снипет зробить окремий SQL-запит. Використовуйте SnippetChooserBlock з попередньою вибіркою споріднених об'єктів через select_related у методі get_queryset ViewSet.

API для headless: швидкий старт

Зареєструйте снипет у Wagtail API:

from wagtail.api.v2.views import BaseAPIViewSet
from .models import Testimonial


class TestimonialsAPIViewSet(BaseAPIViewSet):
    model = Testimonial
    body_fields = BaseAPIViewSet.body_fields + [
        'author_name',
        'author_title',
        'text',
        'rating',
    ]
    listing_default_fields = BaseAPIViewSet.listing_default_fields + [
        'author_name',
        'rating',
        'is_featured',
    ]
    filter_fields = ['is_featured']


api_router.register_endpoint('testimonials', TestimonialsAPIViewSet)

Запит GET /api/v2/testimonials/?is_featured=true&order=-rating поверне JSON з потрібними полями. Ідеально для SPA або мобільного застосунку.

Що входить у роботу?

  • Код снипетів з панелями та валідацією.
  • Налаштування ViewSetGroup та кастомізація адмінки.
  • Документація по API (якщо headless).
  • Навчання редакторів роботі з контентом.
  • Гарантія відсутності N+1 запитів у шаблонах.

Зв'яжіться з нами для розробки кастомних снипетів. Отримайте готовий код снипетів з документацією та навчанням редакторів. Замовте консультацію щодо вашого проєкту — ми допоможемо підібрати оптимальне рішення.

Терміни та вартість

Терміни — від 2–3 годин на один снипет до 2–3 днів на комплект з 5–7 моделей з ViewSetGroup та API. Точну вартість розраховуємо після аналізу вашого проєкту — зв'яжіться з нами для оцінки.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1543
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060