Sage Abdullah
JSONField
JSONField
The last comment block of each slide will be treated as slide notes. It will be visible and editable in Presenter Mode along with the slide. Read more in the docs
Sage Abdullah
JSONField
An open source content management system (CMS) built on Django.
The Page
model acts as both "model" and "view". The tree structure of the model is reflected in your website’s URL structure.
Wagtail gives you the power to:
python -m pip install wagtail
python -m pip install wagtail
INSTALLED_APPS
MIDDLEWARES
urls.py
Wagtail primarily works with its Page
model. For other models, you can register them as "snippets".
Add a @register_snippet
decorator to your model and specify the editable fields using panels
.
from wagtail.admin.panels import FieldPanel from wagtail.snippets.models import register_snippet @register_snippet class Person(models.Model): name = models.CharField(max_length=255) description = models.TextField() ... # Optional, but allows you to fine-tune the editable fields and their order panels = [ FieldPanel("name"), FieldPanel("description"), ... ]
from wagtail.admin.panels import FieldPanel from wagtail.snippets.models import register_snippet @register_snippet class Person(models.Model): name = models.CharField(max_length=255) description = models.TextField() ... # Optional, but allows you to fine-tune the editable fields and their order panels = [ FieldPanel("name"), FieldPanel("description"), ... ]
The preview feature comes from the PreviewableMixin
class.
To use it, add it as a superclass to your model. Then, override the get_preview_template
and get_preview_context
methods.
from wagtail.models import PreviewableMixin @register_snippet class Product(PreviewableMixin, models.Model): ... def get_preview_template(self, request, preview_mode): return f"products/detail.html" def get_preview_context(self, request, preview_mode): return {"product": self}
from wagtail.models import PreviewableMixin @register_snippet class Product(PreviewableMixin, models.Model): ... def get_preview_template(self, request, preview_mode): return f"products/detail.html" def get_preview_context(self, request, preview_mode): return {"product": self}
You can define different preview modes using the preview_modes
attribute.
... class Product(PreviewableMixin, models.Model): ... preview_modes = [ ("index", "Index"), ("detail", "Detail"), ] def get_preview_template(self, request, preview_mode): return f"products/{preview_mode}.html" def get_preview_context(self, request, preview_mode): if preview_mode == "index": return {"products": [self]*20} return {"product": self}
... class Product(PreviewableMixin, models.Model): ... preview_modes = [ ("index", "Index"), ("detail", "Detail"), ] def get_preview_template(self, request, preview_mode): return f"products/{preview_mode}.html" def get_preview_context(self, request, preview_mode): if preview_mode == "index": return {"products": [self]*20} return {"product": self}
You can have revisions for your model by extending the RevisionMixin
class.
from wagtail.models import RevisionMixin ... class Product(RevisionMixin, PreviewableMixin, models.Model): ...
from wagtail.models import RevisionMixin ... class Product(RevisionMixin, PreviewableMixin, models.Model): ...
Then, create and and run the migrations.
python manage.py makemigrations python manage.py migrate
python manage.py makemigrations python manage.py migrate
This allows you to compare the changes between revisions and revert to a previous revision.
Wagtail allows you to save unpublished changes ("drafts") of your models. This functionality is provided by the DraftStateMixin
.
from wagtail.models import DraftStateMixin ... class Product(DraftStateMixin, RevisionMixin, PreviewableMixin, models.Model): ...
from wagtail.models import DraftStateMixin ... class Product(DraftStateMixin, RevisionMixin, PreviewableMixin, models.Model): ...
After creating and running the migrations, you can make use of the live
field of the model.
Product.objects.filter(live=True)
Product.objects.filter(live=True)
Unpublished changes are saved as Revision
s and will not be reflected to your model’s instance until you publish them.
To enable the scheduled publishing feature, add the PublishingPanel
to your model’s panels
.
from wagtail.admin.panels import PublishingPanel ... class Product(DraftStateMixin, RevisionMixin, PreviewableMixin, models.Model): ... panels = [ ... PublishingPanel(), ]
from wagtail.admin.panels import PublishingPanel ... class Product(DraftStateMixin, RevisionMixin, PreviewableMixin, models.Model): ... panels = [ ... PublishingPanel(), ]
You can prevent multiple users from editing the same model instance at the same time by using the LockableMixin
class.
from wagtail.models import LockableMixin ... class Product( DraftStateMixin, LockableMixin, RevisionMixin, PreviewableMixin, models.Model, ): ...
from wagtail.models import LockableMixin ... class Product( DraftStateMixin, LockableMixin, RevisionMixin, PreviewableMixin, models.Model, ): ...
After making and running the migrations, Wagtail will give you the option to lock the model instance.
Wagtail allows you to define workflows for your models, which can be used to moderate content changes before they go live. This functionality is provided by the WorkflowMixin
class.
from wagtail.models import WorkflowMixin ... class Product( WorkflowMixin, DraftStateMixin, LockableMixin, RevisionMixin, PreviewableMixin, models.Model, ): ...
from wagtail.models import WorkflowMixin ... class Product( WorkflowMixin, DraftStateMixin, LockableMixin, RevisionMixin, PreviewableMixin, models.Model, ): ...
By default, Wagtail gives you the "Moderators approval" workflow, which requires a moderator to approve the changes before they go live.
You can create custom workflows with custom tasks to suit your specific needs.
Wagtail allows further customisations to the views for your models by using a custom SnippetViewSet
subclass and registering that instead. It is similar to Django’s ModelAdmin
class.
# wagtail_hooks.py from wagtail.snippets.models import register_snippet from wagtail.snippets.views.snippets import SnippetViewSet from products.models import Product class ProductViewSet(SnippetViewSet): model = Product search_fields = ["name"] list_display = ["name", "final_price", "stock"] list_export = ["name", "price", "discount", "final_price", "stock"] list_filter = {"discount": ["gte"], "stock": ["lte"]} register_snippet(ProductViewSet)
# wagtail_hooks.py from wagtail.snippets.models import register_snippet from wagtail.snippets.views.snippets import SnippetViewSet from products.models import Product class ProductViewSet(SnippetViewSet): model = Product search_fields = ["name"] list_display = ["name", "final_price", "stock"] list_export = ["name", "price", "discount", "final_price", "stock"] list_filter = {"discount": ["gte"], "stock": ["lte"]} register_snippet(ProductViewSet)
Learn more at wagtail.org
Slides available at slides.laymonage.com/modern-wagtail
Code example available at github.com/laymonage/modern-wagtail
Reach out to [email protected]
Thanks to Storm and Thibaud for helping with ideas for this talk!