block

Note

Some of this documentation is awaiting review. It has been moved from the old cms app.

https://gitlab.com/kb/block

Project

requirements/base.txt:

django-taggit==

Tip

See Requirements for the current version.

settings/base.py:

TEMPLATES = [
    {
        'OPTIONS': {
            'context_processors': [
                # ...
                'django.template.context_processors.request',

THIRD_PARTY_APPS = (
    'taggit',

CMS

To use the block system as a CMS:

url(regex=r'^block/',
    view=include('block.urls.block')
    ),
url(regex=r'^compose/',
    view=include('compose.urls.compose')
    ),
url(regex=r'^wizard/',
    view=include('block.urls.wizard')
    ),
# this url include should come last
url(regex=r'^',
    view=include('block.urls.cms')
    ),

Note

The block.urls.cms URLs add a header and footer to the page. The block.urls.wizard URLs add the image and link wizard.

Custom Pages

If you want to add a form or extra context to a page, then use a CUSTOM page. Our standard is to use Page.CUSTOM for the page parameter.

The URL of a custom page must be different to the standard URL for the page.

Here is an example management command to create a custom page:

# -*- encoding: utf-8 -*-
from django.core.management.base import BaseCommand

from block.models import Page, Section, Template, TemplateSection
from web.service import SECTION_MAIN

class Command(BaseCommand):

    def init_page(self, page_name, slug_menu, template):
        self.stdout.write("      - {}".format(page_name))
        page = Page.objects.init_page(
            Page.CUSTOM,
            slug_menu,
            page_name,
            0,
            template,
            is_custom=True,
        )
        # update page sections
        page.refresh_sections_from_template()

    def init_template(self, page_name, template_name):
        # page section
        section = Section.objects.get(slug=SECTION_MAIN)
        # template
        template = Template.objects.init_template(page_name, template_name)
        TemplateSection.objects.init_template_section(template, section)
        return template

    def handle(self, *args, **options):
        self.stdout.write('Pages')
        data = [
            ('Question', 'question', 'web/question.html'),
            ('Student', 'student', 'web/student.html'),
        ]
        for page_name, slug_menu, template_name in data:
            template = self.init_template(page_name, template_name)
            self.init_page(page_name, slug_menu, template)
        self.stdout.write('Complete')

See enquiry for an older example…

Template

To use the simple CMS menu and styling in your project we can use block/base.html in place of base/base.html:

<!-- project/templates/project/base.html -->
{% extends 'block/base.html' %}

<!-- web/templates/web/page.html -->
{% extends 'project/base.html' %}

To extend the block menu in your project:

<!-- this block will appear below the dashboard and above the pages -->
{% block menu_dash %}

<!-- this block will below the pages and above logout-->
{% block menu_extra %}

To use a different styling create a Navigation Menu and include the following in your base template:

<ul class="pure-menu-list">
{% for menu_item in main_menu_item_list %}
  <li class="pure-menu-item">
    <a href="{{ menu_item.get_link }}" class="pure-menu-link">
      {{ menu_item.title }}
    </a>
  </li>
{% endfor %}
N.B: (you probably want to include dashboard, design mode and logout
    items if user is authenticated)
</ul>

Testing

To test a view with a custom page with this URL:

url(regex=r'^contact/$',
    view=EnquiryCreateView.as_view(),
    kwargs=dict(page=Page.CUSTOM, menu='contact'),
    name='web.contact'
    ),

You need to create the Page with a factory e.g:

from block.models import Page
from block.tests.factories import (
    PageFactory,
    TemplateFactory,
)

@pytest.mark.django_db
def test_contact(client):
    PageFactory(
        is_custom=True,
        slug=Page.CUSTOM,
        slug_menu='contact',
        template=TemplateFactory(template_name='web/page_panelled.html'),
    )
    url = reverse('web.contact')
    r = client.get(url)
    assert 200 == r.status_code

URL

To use the Django url tag to link to a page:

<a href="{% url 'project.page' 'custom' 'contact' %}">
  You can find our contact details by clicking here...
</a>

And to reverse:

url = reverse('project.page', kwargs=dict(page='thank-you'))

Tip

The URL name (project.page) is in the block.urls.cms module.

Wizard

We have a link and an image wizard. The following field types are available for use in a ContentModel:

link = models.ForeignKey(
    Link,
    related_name='article_link',
    blank=True, null=True
)
references = models.ManyToManyField(Link)
picture = models.ForeignKey(
    Image,
    related_name='article_picture',
    blank=True, null=True
)
carousel = models.ManyToManyField(Image)

The field names are returned as a list to the block app in a wizard_fields method e.g:

@property
def wizard_fields(self):
    return [
        Wizard('picture', Wizard.IMAGE, Wizard.SINGLE),
        Wizard('link', Wizard.LINK, Wizard.SINGLE),
        Wizard('carousel', Wizard.IMAGE, Wizard.MULTI),
        Wizard('references', Wizard.LINK, Wizard.MULTI),
    ]

If you want the user to be able to link a single image (or link), then specify Wizard.SINGLE. For multi-links or images, use Wizard.MULTI.

The urls for these fields are rendered in the block/block/templates/block/_moderate.html template.

To create the Urls for all non custom pages use the following code:

from block.models import Url
Url.objects.init_pages()