December 16, 2015

Mezzanine for the Uninitiated: Mezzanine-Specific Components

Last time we talked about how to implement Mezzanine using our corporate site update as an example. As Mezzanine is a collection of Django apps containing models, views, and admin fields, splicing it into a pre-existing project requires some additional components. Here well discuss page_processors.py, themes, and template directory structures.

Page Processors

Many developers utilize Django views to perform functions on model field values and derive additional variables before injecting them into custom templates. We can inherit from Mezzanines Page model (among others) if wed like our pages to have extra fields or functions:

from mezzanine.pages.models import Page
from mezzanine.core.fields import FileField, RichTextField

# A field which lets us use TinyMCE editor, the wysywig editor that comes with Mezzanine
class RichTextMixin(RichText):
edit_as_html = models.BooleanField(default=False)

class Meta:
abstract = True

class WebPage(Page, RichTextMixin):
top_navbar_title = models.CharField(max_length=200, blank=True, null=True)
...

A new script (page_processors.py) within our existing Django app allows us to perform a similar function to views.py. We import our Page-derived models and relevant modules, designate a processor for those models, and use it to send processed variables on to our templates:

from .models import WebPage

@processor_for(WebPage)
def webpage_preprocessor(request, page):
# Access the Pages fields using page.fieldname
if page.slug == industries:
# Access other imported models (including ones that inherit from Page) using ModelName.objects.filter() or .all()
industries = Industries.objects.all()

# The request parameter is populated with context variables and sent to the relevant template
return_value = dict()
return_value[industries] = industries

return return_value

Our sites Django app doesnt have its own views.py (that function is fulfilled by page_processors.py) and only requires a root-level urls.py to redirect old URLs to their new counterparts, load Mezzanines URLs, and point the root URL to our index.html.

Themes

Go here for a more generic tutorial of how to create a new Mezzanine project or theme. We decided to separate our templates and static files from our sites existing core app in order to make future restyling easier. One directory (our core Django app) contains models, admin fields, forms, and page processors, while another (our theme) contains static files and templates. We can easily switch out one theme directory for another while still using our core app. To create a theme:

python manage.py startapp name_of_theme_dir

Then, in settings.py at the top of INSTALLED_APPS, add name_of_theme_dir to indicate youd like to use that theme.

Template Directories

Themes contain a directory, called "templates", which follows a specific structure:

templates/

  • admin/ - any admin templates (like change_form.html) adding to or overriding Mezzanines
  • blog/ - based on Mezzanines blog app; blog_post_detail.html controls styling of individual blog posts; can also contain an includes/ directory
  • errors/ - custom error pages
  • includes/ - snippets of HTML that are injected into other templates
  • menus/ - if set up properly in settings.py, Mezzanine provides functionality in admin to tell pages which menu (navbar, footer, sidebar, etc) theyll appear on; the menus HTML exists here
  • other/ - code that doesnt fit in the other categories
  • pages/ - based on Mezzanines pages app; page.html (which extends base.html) is the base, and all other custom templates go here
  • base.html - the base HTML/CSS/JS code shared by every page
  • index.html - your home page template

Naming conventions are important here as Mezzanine uses model names and page slug fields to determine which template to populate. Remember how you had to write a page processor instead of a view? How do you tell Django what template to render? You dont. Mezzanine figures it out based on the names you select for your models or the slug you choose for individual pages.

Template lookup by model name:

If you create a JobPage model - our next post will cover customization of Mezzanines Page model - to populate individual job listings, it has a URL slug like job-listing/associate-editor/, and no template exists at theme_dir/templates/pages/job-listing/associate-editor.html, then Mezzanine looks for theme_dir/templates/pages/jobpage.html. In other words, Mezzanine looks for templates based on URL slug first and page model name second.

Template lookup by page slug field:

If you wanted basic Contact, About, and Privacy Policy pages, you could create a WebPage model, add three new WebPages to the database in admin (or in the Python shell), and name their URL slugs contact, about, and privacy-policy, which will tell Mezzanine to look for their corresponding templates at theme_dir/templates/pages/[contact,about,privacy-policy].html. Under the WebPage page processor, you can conditionally check for the WebPages slug name (using page.slug) to handle functionality for different templates.

Topic
###