Skip to main content

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.

PyPI Build Status Software license

Compatibility

  • python >= 3.8
  • django >= 3.1
  • paper-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

  1. 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)
    
  2. 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
    
  3. 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>
    
  4. 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:

  5. 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

If you need to use custom template name or template engine, you can specify

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:

<!-- blocks/templates/blocks/textblock.html -->
<div class="{{ classes }}">{{ block.text|linebreaks }}</div>
<!-- app/templates/index.html -->
{% load streamfield %}

{% render_stream page.stream classes="text text--small" %}

Access parent context from within a block

In some cases you need to access the parent context from the block template.

You can access the parent context from the block template by using parent_context variable:

<!-- blocks/templates/blocks/textblock.html -->
<div class="{{ parent_context.classes }}">{{ block.text|linebreaks }}</div>
<!-- app/templates/index.html -->
{% load streamfield %}

<!-- Add classes to the page context -->
{% with classes="text text--small" %}
  {% render_stream page.stream %}
{% endwith %}

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

paper-streamfield-0.5.0.tar.gz (25.3 kB view hashes)

Uploaded Source

Built Distribution

paper_streamfield-0.5.0-py2.py3-none-any.whl (30.7 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page