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:
When working with block templates, it's important to note that you have access to all variables from the parent context.
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:
template_engine = "jinja2"
template_name = "blocks/heading.html"
Caching the rendered HTML of a block
You can enable caching for specific blocks to optimize rendering.
class HeadingBlock(models.Model):
# ...
class StreamBlockMeta:
cache = True
cache_ttl = 3600
Once caching is enabled for the block, the rendered HTML will be stored in cache, and subsequent requests will retrieve the cached content, reducing the need for re-rendering.
Note that the specified block will not be invalidated when something changes in it.
Adding context variables to all blocks
You can add context variables to all blocks in your StreamField by providing them
through the render_stream
template tag. This allows you to pass common context data
to customize the rendering of all content blocks consistently:
<!-- 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>
Adding context variables to a specific block
To add context variables to a specific content block, you must create a custom processor. A processor provides a mechanism for customizing the context data and the rendering process of an individual block.
- Create a custom processor class that inherits from
streamfield.processors.DefaultProcessor
.from streamfield.processors import DefaultProcessor from reviews.models import Review class ReviewsBlockProcessor(DefaultProcessor): def get_context(self, block): context = super().get_context(block) context["reviews"] = Review.objects.all()[:5] return context
- In your block's model, specify the processor to use:
class ReviewsBlock(models.Model): # ... class StreamBlockMeta: processor = "your_app.processors.ReviewsBlockProcessor"
Using render_block
template tag
In some cases, you may have a page that references a specific block through
a ForeignKey
relationship, and you want to render that referenced block on the page.
You can achieve this using the render_block template tag. Here's an example:
# page/models.py
from django.db import models
from blocks.models import TextBlock
class Page(models.Model):
text_block = models.ForeignKey(TextBlock, on_delete=models.SET_NULL, blank=True, null=True)
class Meta:
verbose_name = "Page"
<!-- app/templates/page.html -->
{% load streamfield %}
<div>
<h1>Page Title</h1>
<div>
<h2>Text Block:</h2>
{% render_block page.text_block %}
</div>
</div>
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 %}
Settings
PAPER_STREAMFIELD_DEFAULT_PROCESSOR
Default processor for content blocks.
Default: "streamfield.processors.DefaultProcessor"
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.7.2-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 934fbca6d4ffa84f5babe530c967c151d595c80c48d72c25a3cdfa6b9e250ec0 |
|
MD5 | 53de0c798fc4ecf5ae78d1b0f7a499a6 |
|
BLAKE2b-256 | 73aa4cbeb004aa92843650c67c5e13a97fa6a99d962de7fddba8df60890b79d3 |