Implementation of the Wagtail's StreamField block picker for paper-admin.
Project description
paper-streamfield
Implementation of the Wagtail's StreamField block picker for paper-admin.
Compatibility
python
>= 3.8django
>= 3.1paper-admin
>= 6.0
Installation
Install the latest release with pip:
pip install paper-streamfield
Add streamfield
to your INSTALLED_APPS in django's settings.py
:
INSTALLED_APPS = (
# other apps
"streamfield",
)
Add streamfield.urls
to your URLconf:
urlpatterns = patterns('',
...
path("streamfields/", include("streamfield.urls")),
)
How to use
-
Create some models that you want to use as blocks:
# blocks/models.py from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.utils.text import Truncator class HeadingBlock(models.Model): text = models.TextField() rank = models.PositiveSmallIntegerField( default=1, validators=[ MinValueValidator(1), MaxValueValidator(6) ] ) class Meta: verbose_name = "Heading" def __str__(self): return Truncator(self.text).chars(128) class TextBlock(models.Model): text = models.TextField() class Meta: verbose_name = "Text" def __str__(self): return Truncator(self.text).chars(128)
-
Register your models using
StreamBlockModelAdmin
class.# blocks/admin.py from django.contrib import admin from streamfield.admin import StreamBlockModelAdmin from .models import HeadingBlock, TextBlock @admin.register(HeadingBlock) class HeadingBlockAdmin(StreamBlockModelAdmin): list_display = ["__str__", "rank"] @admin.register(TextBlock) class TextBlockAdmin(StreamBlockModelAdmin): pass
-
Create templates for each block model, named as lowercase model name or snake_cased model name.
<!-- blocks/templates/blocks/headingblock.html --> <!-- or --> <!-- blocks/templates/blocks/heading_block.html --> <h{{ block.rank }}>{{ block.text }}</h{{ block.rank }}>
<!-- blocks/templates/blocks/textblock.html --> <!-- or --> <!-- blocks/templates/blocks/text_block.html --> <div>{{ block.text|linebreaks }}</div>
-
Add a
StreamField
to your model:# app/models.py from django.db import models from django.utils.translation import gettext_lazy as _ from streamfield.field.models import StreamField class Page(models.Model): stream = StreamField( _("stream"), models=[ "blocks.HeaderBlock", "blocks.TextBlock", ] ) class Meta: verbose_name = "Page"
Result:
Now you can create some blocks:
-
Use
render_stream
template tag to render the stream field.<!-- app/templates/index.html --> {% load streamfield %} {% render_stream page.stream %}
Result:
Special cases
Use custom template name or template engine
You can specify a template name or engine to render a specific block
with StreamBlockMeta
class in your block model:
class HeadingBlock(models.Model):
# ...
class StreamBlockMeta:
engine = "jinja2"
template = "blocks/heading.html"
Add extra context
You can add extra context to the template by passing
additional keyword arguments to render_stream
template tag:
<!-- app/templates/index.html -->
{% load streamfield %}
{% render_stream page.stream classes="text text--small" %}
<!-- blocks/templates/blocks/textblock.html -->
<div class="{{ classes }}">{{ block.text|linebreaks }}</div>
Access parent context from within a block
In paper-streamfield
you can use variables from the parent context within block
templates (similar to how it's done with the {% include %}
tag in Django templates).
-
Pass Variables in Parent Template: In your parent template, define variables you want to use in block templates. For example:
<!-- app/templates/index.html --> {% load streamfield %} <!-- Add classes to the page context --> {% with theme="dark" %} {% render_stream page.stream %} {% endwith %}
-
Access Variables in Block Templates: In your block templates, you can access variables from the parent context just like regular Django templates:
<!-- blocks/templates/blocks/textblock.html --> <div class="block{% if theme %} block--{{ theme }}{% endif %}">{{ block.text|linebreaks }}</div>
With this approach, you can utilize variables from the parent context within block templates, making it easy to customize block rendering in your Django project.
Customize block in admin interface
You can customize how a block is rendered in the admin interface
by specifying stream_block_template
field in the StreamBlockModelAdmin
class:
from django.contrib import admin
from streamfield.admin import StreamBlockModelAdmin
from .models import ImageBlock
@admin.register(ImageBlock)
class ImageBlockAdmin(StreamBlockModelAdmin):
stream_block_template = "blocks/admin/image.html"
list_display = ["__str__", "title", "alt"]
<!-- blocks/admin/image.html -->
{% extends "streamfield/admin/block.html" %}
{% block content %}
<div class="d-flex">
<div class="flex-grow-0 mr-2">
<img class="preview"
src="{{ instance.image }}"
width="48"
height="36"
title="{{ instance.title }}"
alt="{{ instance.alt }}"
style="object-fit: cover">
</div>
{{ block.super }}
</div>
{% endblock content %}
Caching the rendered HTML of a block
You can cache the rendered HTML of a block by using CacheRenderer
class:
class HeadingBlock(models.Model):
# ...
class StreamBlockMeta:
renderer = "streamfield.renderers.CacheRenderer"
cache_ttl = 3600
Note that the specified block will not be invalidated when something changes in it.
Settings
PAPER_STREAMFIELD_DEFAULT_RENDERER
Default renderer for render_stream
template tag.
Default: "streamfield.renderers.DefaultRenderer"
PAPER_STREAMFIELD_DEFAULT_TEMPLATE_ENGINE
Default template engine for render_stream
template tag.
Default: None
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for paper_streamfield-0.6.1-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0f0696b40c59326e1ca184147bebf00d1adbf01a43ee4884a27b95bcba2e10e3 |
|
MD5 | 6722d61de69117e98bb93c5a83a43f75 |
|
BLAKE2b-256 | 30630b09ba5eb7b2aad51eab610dd45235b9cf1754edf9a500409fb03e0e460b |