denken == gratis?

Einen Blog mit Wagtail erstellen

Wenn man plant, einen Blog zu schreiben, sollte man sich immer überlegen, welche Elemente man nutzen will. Meistens braucht man eine Überschrift, natürlich Text, Teilüberschriften sind auch meist vom Vorteil um den Text zu gliedern. Vielleicht braucht man Bilder, vielleicht Code-Fragmente. Da man mit Wagtail die Elemente beliebig nutzen und anordnen kann, muss man sich also zunächst überlegen welche Möglichkeiten man anderen geben will. Man kann diese natürlich immer erweitern.

 - Dann kann man starten. Zuinächst sollte man sich eine neue App erstellen, dies kann man über manage.py ausführen:

$ python3 manage.py startapp Blog

Diese App muss man zunächst in den settings, welche sich in dem Ordner befinden, welcher wie das Projekt heißt, ich nenne ihn ab sofort einfach sample, also unter sample/sample/[settings]. Je nach dem wie das Projekt erstellt wurde heißt die Datei settings.py oder base.py. Darin gibt es die Liste INSTALLED_APPS, in welcher man die App hinzufügen muss:

INSTALLED_APPS = [
    # apps etc.
    'Blog',
]

Ab nun wird Django die App beachten, somit kann nun die models.py bearbeitet werden, um die Elemente hinzuzufügen.

Ein wichtiges Feld, welches wir benutzen werden, ist das StreamField, denn darin lassen sich die Elemente beliebig anordnen. Darin definieren wir weitere Felder. Wagtail bietet folgende Felder:

  • CharBlock - ein einzeiliger Text
  • TextBlock - ein mehrzeiliger Text
  • EmailBlock - ein Feld für eine E-Mail Adresse mit Validierung
  • IntegerBlock - ein Ganzzahlfeld
  • RichTextBlock - ein Feld für Texte mit Formatierung im WYSIWYG-Editor

und weitere, jedoch will ich hier nicht alle ausführen.

Wollen wir nun einen simplen Block bauen, so nutzen wir CharBlocks für Überschriften und RichtextBlocks für den Text. Ein simpler Entwurf könnte so aussehen:

from django.db import models
from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.wagtailcore import blocks
from wagtail.wagtailcore.fields import StreamField

# Die Seite, in der man die Blogeinträge gesammelt findet
class BlogIndexPage(Page):
    # ein kleiner Einleitungstext
    intro = models.TextField()

    # hinzufügen zum content_panel, um es bearbeiten zu können
    content_panels = Page.content_panels + [
        FieldPanel('intro', classname="full")
    ]
    # Unterseiten dürfen nur Blogeinträge sein
    subpage_types = ['BlogPage']

# Die Blogseite
class BlogPage(Page):
    content = StreamField([
        ('heading', blocks.CharBlock(classname="full title")),
        ('paragraph', blocks.RichTextBlock()),
    ])
    author = models.CharField(max_length=255, blank=True)

    content_panels = Page.content_panels + [
        StreamFieldPanel('content'),
        FieldPanel('author', classname="full"),
    ]
    # Diese Seite darf nur Tochterseite einer Indexseite sein
    parent_page_types = ['BlogIndexPage']
    # Und darf keine Unterseiten haben
    subpage_types = []

Aber ein Model allein reicht nicht aus, man muss es natürlich auch irgendwo ausgeben können. Dazu brauchen wir ein Template, welches zum Beispiel, ein weiteres tolles Feature, aus der Hauptseite seinen Header und Footer sowie weitere Einstellungen übernehmen kann, und dann nur den Inhalt von Wagtail hineinrendert (hierzu fügt man einfach {% extends '[NAME_DES_HAUPTFILE.html]' %}. Ich werde hier keine Kenntnisse von HTML zeigen, aber ich empfehle dafür CodeCademy. Hat man ein template für diese Zwecke, so legt man es in seinem App Ordner unter templates/[APP_NAME]/ und benennt die Dateien wie ihre Klassen in der models.py, jedoch kleingeschrieben und dazwischen immer mit Unterstrich, also in unserem Fall jeweils blog_page.html und blog_index_page.html.

Dann müssen diese nur noch als Templates von Django erkannt werden, indem man in den Settings diese zu DIRS hinzufügt (beachte wie bei dir BASE_DIR als Variable gespeichert wurde, diese sollte irgendwo bereits einmal stehen, zum Beispiel als BASE_DIR oder auch base_dir.BASE_DIR oder auch anders!):

TEMPLATES = [
    {
        # andere Einstellungen
        'DIRS': [
            # andere Ordner
            os.path.join(BASE_DIR, 'blog/templates/blog'),
        ],
}

Wurde es nun hinzugefügt, erkennt Django dein Templates, aber du musst Django noch signalisieren, wo welche Daten erscheinen sollen. Dies kannst du über die TemplateTags lösen, welche es dir ermöglichen in Templates auch Python-Code ausführen zu können. Dazu musst du zum laden der statischen Daten dies oben in deinen HTML-Code schreiben:

{% load wagtailcore_tags %}
{% load static from staticfiles %}

Um jetzt irgendwo deine Daten einzutragen, musst du noch abfragen, welche Daten angekommen sind, und in einer For-Schleife um dies für alle Dateien machen, zum Beispiel um es hier auf unseren heading und paragraph zu beziehen:

{% for block in page.content %}
    {% if block.block_type == "heading" %}
        # zeige es als Heading an
        <h1>{{block.value}}</h1>
    {% else %}
        # oder als normaler (formatierter) Text
        <p>{{block.value}}</p>
    {% endif %}
{% endfor %}

Und um in der blog_index_page.html die vorhandenen Blogeinträge anzeigen zu lassen, müssen einfach nur die Unterseiten angezeigt werden, welche live geschaltet sind, dies geht über:

# wenn es Unterseiten gibt ...
{% if page.get_children.live %}
    {% for entry in page.get_children.live %}
        # ... zeige sie in einer Liste an (mit Verlinkung durch pageurl)
        <li style="list-style-type: none;">
            <a href="{% pageurl entry %}" style="text-decoration: none;">
                <p>{{ entry.title }}</p></a>
        </li>
    {% endfor %}
{% else %}
      # ... ansonsten gib diesen Text wieder
      <p>No Blogs</p>
{% endif %}

Nun nur noch in der Konsole:

$ python3 manage.py migrate

wenn man noch keinen Superuser angelegt hat auch noch:

$ python3 manage.py createsuperuser

und natürlich nur noch den Runserver mit

$ python3 manage.py runserver

starten, und schon kann man sich unter /admin einloggen, und bei Pages auf die "Welcome to your new Wagtail Site" klicken, um da eine neue Tochterseite zu erstellen, welche dann die Blogindexpage ist, und darunter noch einen Blog-Eintrag. Stellt man diese dann auf publish, kann man prüfen ob alles geklappt hat. Wenn nicht, hilft eine Google-Suche. Sollte ich hier etwas falsch oder veraltet dargestellt haben, reicht eine Email mit dem Problem und wenn es möglich ist der Lösung, und ich werde es sofort verbessern.

Bocian67