MerixGames

16 czerwca 2016

/ code & tools

Wagtail - system open source do zarządzania treścią (cz. 1)

Filip Stawicki

Wagtail to system open source do zarządzania treścią (CMS) napisany w Pythonie przy użyciu frameworka Django. Pozwala on na szybkie konfigurowanie i uruchomienie w pełni funkcjonalnego środowiska dla edytorów, programistom zaś pomaga w łatwym rozbudowaniu funkcjonalności i dostosowaniu aplikacji do konkretnych potrzeb wykorzystując przy tym mechanizmy znane z Django.

Podstawowe funkcje

  • przyjazny interfejs panelu administracyjnego- pozwala w łatwy sposób zarządzać strukturą strony i edytować poszczególne widoki;
  • wbudowany edytor WYSIWYG -  dzięki niemu można formatować tekst bez znajomości HTML;
  • zarządzanie zdjęciami - domyślny interfejs pozwala na wielokrotne użycie wgranego obrazu, dzięki czemu oszczędzamy czas oraz miejsce na dysku. Zdjęcia można tagować i wyszukiwać po nazwie (lub tagach), dzięki czemu bez problemu można z łatwością pracować nawet z ogromnym zbiorem wgranych zdjęć;
  • dynamiczne widoki - cała funkcjonalność może zawierać się w modelu i szablonie.

Instalacja Wagtail

Najnowsza stabilna wersja systemu dostępna jest na PyPI. Aby zainstalować Wagtail oraz wszystkie pozostałe zależności, takie jak najnowsza wersja Django (na ten moment jest to 1.9.6),  wystarczy wykonać polecenie:

    $ pip install wagtail

Nowy projekt używający Wagtail tworzy się za pomocą polecenia

    $ wagtail start <nazwa_projektu>

Działa ono podobnie do django-admin startproject <nazwa_projektu>, jednak wybrany przeze mnie sposób ma kilka dodatkowych plusów:

  • tworzy plik konfiguracyjny pozwalający używać Wagtail od razu  w projekcie;
  • tworzy prostą aplikację ‘home’, pozwalającą dodawać strony oparte na edytorze WYSIWYG;
  • dodaje szablony do wyświetlania błędów (404, 500) oraz folder z plikami statycznymi (js, css). Zamiast pojedynczego pliku otrzymujemy  moduł z ustawieniami.

Na potrzeby tego artykułu korzystać będziemy z domyślnej bazy danych SQLite3, która nie wymaga konfiguracji i pozwala na natychmiastowe rozpoczęcie pisania kodu. Jeżeli jednak zależy ci na maksymalnej wydajności, polecam korzystać z jej zamiennika, PostgreSQL. Wymaga on wprawdzie konfiguracji, lecz dużo lepiej radzi sobie z większą ilością danych.

Aby utworzyć schemat bazy danych używamy polecenia:

    $ python manage.py migrate

W tym momencie możemy stworzyć konto administratora, który będzie miał dostęp do panelu edytora

    $ python manage.py createsuperuser

oraz uruchamiamy serwer deweloperski, który dostępny będzie pod adresem http://127.0.0.1:8000.

    $ python manage.py runserver

Aby dostać się do panelu administratora musimy przejśc  pod adres http://127.0.0.1:8000/admin. Na ten moment pozwala on jedynie na tworzenie prostych stron składających się z jednego pola WYSIWYG.

Przykład zastosowania

Stworzymy prostą aplikację pozwalającą na dodawanie oraz listowanie zdjęć z opisem i datą wykonania. W dalszych etapach naszej pracy dodamy do niej możliwość zarządzania stronami w różnych wersjach językowych.

Wszystkie polecenia opisane poniżej wywoływane są z poziomu głównego folderu projektu.

Stwórzmy zatem aplikację o nazwie “gallery”:

    $ python manage.py startapp gallery

w pliku konfiguracyjnym (<nazwa_projektu>/settings/base.py) dodajmy ją do listy zainstalowanych aplikacji

INSTALLED_APPS = [
    ...

    'gallery',
]

Dodajmy do niej model PhotoPage, który będzie odpowiedzialny na przechowywanie informacji wymienionych we wstępie tego paragrafu - data, nagłówek, opis (i jego skrót) oraz samo zdjęcie.

from django.db import models

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel

class PhotoPage(Page):
    image = models.ForeignKey(
        'wagtailimages.Image', related_name='+', on_delete=models.CASCADE)
    date = models.DateField("Photo date")
    header = models.CharField("Header", max_length=200)
    abstract = models.TextField("Abstract")
    description = RichTextField("Description")

    content_panels = Page.content_panels + [
        FieldPanel('header'),
        FieldPanel('date'),
        ImageChooserPanel('image'),
        FieldPanel('abstract'),
        FieldPanel('description'),
    ]
  • ‘image’ definiujemy jako ForeignKey, co parę kroków dalej pozwoli nam korzystać ze specjalnego, oferowanego przez Wagtail widgeta służącego do wyboru zdjęcia;
  • pola ‘date’, ‘header’ i ‘abstract’ to pola znane z Django;
  • pole ‘description’ używa typu RichTextField - jest to zwykły TextField z ciekawym widgetem WYSIWYG w panelu administratora.

Każda strona (model dziedziczący po Page) ma domyślnie 3 zakładki:

  • content_panels - tutaj powinny trafić wszystkie pola, które będą wyświetlane użytkownikowi końcowemu;
  • promote_panels - tu znajdują się takie elementy jak między innymi slug strony czy SEO;
  • settings_panels - domyślnie możemy tu ustawić datę pojawienia się strony oraz datę jej wygaśnięcia. Tutaj mogą też znaleźć się szczegółowe ustawienia, np. używany szablon (Wagtail pozwala dynamicznie dobierać szablon do obiektu).

Zakładki można edytować, co szerzej opisane jest w oficjalnej dokumentacji Wagtail.

Na tym etapie naszej pracy do modelu musimy dodać szablon. Ścieżkę do niego możemy zdefiniować w klasie. Nie jest to konieczne jeśli będziemy używać nazewnictwa zgodnego z konwecją Wagtala, tj. nazwa szablonu jest nazwą klasy zapisaną snake casem. Dla klasy PhotoPage oznacza to, że szablon powinien nazywać się photo_page.html. Umieścmy go w folderze gallery/templates/gallery:

{% extends "base.html" %}

{% load wagtailcore_tags %}
{% load wagtailimages_tags %}

{% block content %}
    <h2>{{ page.header }}</h2>
    <h4>(date: {{ page.date }})</h4>
    {% image page.image width-400 %}
    {{ page.description|richtext }}
{% endblock content %}

By zaktualizować bazę danych zaktualizujmy bazę danych:

    $ python manage.py makemigrations
    $ python manage.py migrate

W tym momencie możemy dodać nowy typ podstrony w panelu administratora.

Panel administratora Wagtail: wybór typu strony

Po wybraniu ‘Photo Page’ pojawi się przyjazny panel utworzony za pomocą definicji content_panels. Zawiera się w nim między innymi Image Chooser, który pozwala wgrywać i przeglądać zdjęcia - właśnie z tego powodu używamy ForeignKey do wagtailimages.Image zamiast zwykłego ImageField.
Panel administratora Wagtail: dodawanie stronyPanel administratora Wagtail: Image Chooser widgetStwórzmy teraz prostą stronę, która pozwoli nam dodać opis naszego zbioru oraz wylistować tytuły zdjęć razem z linkami:

class GalleryPage(Page):
    description = RichTextField("Description")

    content_panels = Page.content_panels + [
        FieldPanel('description')
    ]

    def get_context(self, *args, **kwargs):
        context = super().get_context(*args, **kwargs)
        context['photos'] = PhotoPage.objects.order_by('first_published_at')
        return context

Poza funkcją get_context nie znajdziecie  w tym kodzie niczego nowego. Jak wcześniej pisałem, przy korzystaniu z Wagtail nie ma potrzeby pisania widoków do każdego modelu strony, nawet gdy chcemy przesłać dodatkowe informacje do szablonu. Metoda ta jest odpowiednikiem get_context_data z generycznych widoków klasowych znanych z Django. W naszym wypadku pobieramy context, dodajemy do niego wszystkie zdjęcia posortowane po dacie publikacji (od najnowszego) i przesyłamy kontekst do  szablonu.

Szablon o nazwie gallery_page.html powinien znaleźc się w folderze gallery/templates/gallery i może wyglądać w następujący sposób:

{% extends "base.html" %}

{% load wagtailcore_tags %}

{% block content %}
    <h2>My gallery</h2>
    {{ page.description|richtext }}
    <ul>
        {% for photo in photos %}
            <li>
                <a href="{{ photo.url }}">{{ photo.title }}</a>
            </li>
        {% endfor %}
    </ul>
{% endblock content %}

Pozostało jedynie zaktualizować bazę danych, uruchomić serwer i możemy zobaczyć nasze zmiany na żywo:

    $ python manage.py makemigrations
    $ python manage.py migrate
    $ python manage.py runserver

Co jeszcze powinniśmy wiedzieć na temat Wagtail?

W tej części artykułu dowiedzieliśmy się jak skonfigurować środowisko do pracy z systemem Wagtail oraz poznaliśmy część jego możliwości. Jak widać, nawet początkujący programista Django może z łatwością dostosować CMS do konkretnych potrzeb. Bardziej zaawansowanym użytkownikom Wagtail pozostawia on dużo swobody na rozszerzanie funkcjonalności, np. dostosowanie panelu edytora do zarządzania wieloma wersjami językowymi, co opiszę w następnej części mojego artykułu, którą już niedługo przeczytać będziecie mogli na naszym blogu.

Strona używa plików cookies. Wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.