PyCon 5 - Florence, May 24, 2014
All you need is…
...Mezzanine!
Simone Dalla @simodalla
CI[T]O of Comune di Zola Predosa (Bologna, IT)
Pythonista and Django programmer.
I use Python into my work environment for.....
ALL!
Problem
Respect of Italy’s decree-law:
“Amministrazione Trasparente, Pubblicazioni ai sensi del Decreto Legislativo
14 marzo 2013, n. 33. Riordino della disciplina riguardante gli obblighi di
pubblicità, trasparenza e diffusione di informazioni da parte delle pubbliche
amministrazioni. (GU n.80 del 5-4-2013)”
≃ 250 obligation to publish
into official government web
site
OpenPa by Mezzanine
https://www2.comune.zolapredosa.bo.it
http://mezzanine.jupo.org/
http://mezzanine.jupo.org/
http://mezzanine.jupo.org/
Batteries
Included
http://mezzanine.jupo.org/
Batteries
Included
- Ecommerce: cartridge.jupo.org
- Forum: drum.jupo.org
- Themes: mezzathe.me
~ 70 Packages:
https://www.djangopackages.
com/grids/g/mezzanine/
EXTRABatteries
Included
Bootstrap (into an virtualenv)
# Install from Pypi
(venv)$ pip install mezzanine [south django-debug-toolbar]
# Create a project
(venv)$ mezzanine-project mysite
(venv)$ cd mysite
# Create a database
(venv)$ python manage.py createdb
# Apply default migrations
(venv)$ python manage.py migrate
# Run the webserver
(venv)$ python manage.py runserver
Et voilà...
User
User (backoffice)
User (backoffice)
http://blog.jupo.org/2014/04/19/mezzanine-3.1-for-workgroups/
Growth of Mezzanine has been
consistent
Developer... “and now???”
“Mantra for working with
Mezzanine:
Mezzanine is Just Django”
Ken Bolton, long-time Mezzanine contributor.
Creating Custom Content Types
from django.db import models
from mezzanine.pages.models import Page
# The members of Page will be inherited by the Poll
# model, such as title, slug, etc. For polls we can use
# the title field to store the poll’s question. For our
# model definition, we just add any extra fields that
# aren't part of the Page model, in this case, date of
# publication.
class Poll(Page):
# question = models.CharField(max_length=200)
pub_date = models.DateTimeField("Date published")
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
https://docs.djangoproject.com/en/1.
6/intro/tutorial01/#creating-models
http://mezzanine.jupo.org/docs/content-architecture.
html#creating-custom-content-types
(venv)$ python manage.py startapp polls
polls/models.py
Admin Custom Content Types
from copy import deepcopy
from django.contrib import admin
from mezzanine.core.admin import (
TabularDynamicInlineAdmin)
from mezzanine.pages.admin import PageAdmin
from .models import Poll, Choice
poll_extra_fieldsets = (
(None, {"fields": ("pub_date",)}),)
class ChoiceInline(TabularDynamicInlineAdmin):
model = Choice
class PollAdmin(PageAdmin):
inlines = (ChoiceInline,)
fieldsets = (deepcopy(PageAdmin.fieldsets) +
poll_extra_fieldsets)
admin.site.register(Poll, PollAdmin)
https://docs.djangoproject.com/en/1.
6/intro/tutorial02/#adding-related-objects
http://mezzanine.jupo.org/docs/content-architecture.
html#creating-custom-content-types
polls/admin.py
Displaying Custom Content Types
>>> Poll.objects.create(title="What's your favourite program language?", pub_date=now())
<Poll: What's your favourite program language?>
>>> page = Page.objects.create(title="What's your favourite program language?")
>>> page
<Page: What's your favourite program language?>
>>> page.poll
<Poll: What's your favourite program language?>
>>> page.get_content_model()
<Poll: What’s your favourite program language>
http://mezzanine.jupo.org/docs/content-architecture.html#displaying-custom-content-types
{% extends "pages/page.html" %}
{% load mezzanine_tags %}
{% block title %}
{% editable page.poll.title %}{{ page.poll.title }}{% endeditable %}
{% endblock %}
{% block main %}
{{ block.super }}
<p>Published at {{ page.poll.pub_date }}</p>
<ul>
{% for choice in page.poll.choice_set.all %}
<li>{% editable choice.choice_text %}{{ choice.choice_text }}{% endeditable %} n. votes: {{ choice.votes }}</li>
{% endfor %}
</ul>
{% endblock %}
polls/templates/poll.py
Page Processor
http://mezzanine.jupo.org/docs/content-architecture.html#page-processors
from django.shortcuts import get_object_or_404
from mezzanine.pages.page_processors import processor_for
from .models import Poll, Choice
@processor_for(Poll)
def author_form(request, page):
if request.method == "POST":
p = get_object_or_404(Poll, pk=page.poll.id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return {'error_message': "You didn't select a choice."}
else:
selected_choice.votes += 1
selected_choice.save()
return {'success_message': "Thank you for your vote."}
<h2>Vote!!!</h2>
{% if error_message %}<div class="alert alert-danger">{{ error_message }}</div>{% endif %}
{% if success_message %}<div class="alert alert-success">{{ success_message }}</div>{% endif %}
<form action="." method="post">
{% csrf_token %}
{% for choice in page.poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
polls/page_processors.py
polls/templates/poll.py
Integrating Third-party Apps
http://mezzanine.jupo.org/docs/content-architecture.html#integrating-third-party-apps-with-pages
# MEZZANINE'S URLS
# ----------------
# ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW. ``mezzanine.urls`` INCLUDES
# A *CATCH ALL* PATTERN FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.
urls``
# WILL NEVER BE MATCHED!
url(r'^dj_polls/', include('dj_polls.urls', namespace='polls')),
# If you'd like more granular control over the patterns in ``mezzanine.urls``, go right ahead
# and take the parts you want from it, and use them directly below instead of using
# ``mezzanine.urls``.
("^", include("mezzanine.urls")),
Our “regoular third-party” Django app to integrate. Polls apps of official
Django tutorial named here “dj_polls”.
https://docs.djangoproject.com/en/1.6/intro/tutorial01/
Polls “Mezzanine” app developed earlier for custom types.
Integrating Third-party Apps
http://mezzanine.jupo.org/docs/content-architecture.html#integrating-third-party-apps-with-pages
Other requirement is pages in Mezzanine’s navigation to point to the
urlpatterns for these regular Django apps. Implementing this simply
requires creating a page (RichTextPage, Link..) in the admin, with a
URL matching a pattern used by the application.
More information? Need help?
Documentation
http://mezzanine.jupo.org/
@stephen_mcd PyCon APAC keynote
Source Code
https://github.com/stephenmcd/mezzanine
Mailing list https://groups.google.com/forum/#!
forum/mezzanine-users
Issues tracker
https://github.com/stephenmcd/mezzanine/issues
Thank you! ….questions?
Talk Mezzanine Project code
https://github.com/simodalla/mezzanine_talk_polls

All you need is...Mezzanine!

  • 1.
    PyCon 5 -Florence, May 24, 2014 All you need is… ...Mezzanine!
  • 2.
    Simone Dalla @simodalla CI[T]Oof Comune di Zola Predosa (Bologna, IT) Pythonista and Django programmer. I use Python into my work environment for..... ALL!
  • 3.
    Problem Respect of Italy’sdecree-law: “Amministrazione Trasparente, Pubblicazioni ai sensi del Decreto Legislativo 14 marzo 2013, n. 33. Riordino della disciplina riguardante gli obblighi di pubblicità, trasparenza e diffusione di informazioni da parte delle pubbliche amministrazioni. (GU n.80 del 5-4-2013)” ≃ 250 obligation to publish into official government web site
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
    - Ecommerce: cartridge.jupo.org -Forum: drum.jupo.org - Themes: mezzathe.me ~ 70 Packages: https://www.djangopackages. com/grids/g/mezzanine/ EXTRABatteries Included
  • 10.
    Bootstrap (into anvirtualenv) # Install from Pypi (venv)$ pip install mezzanine [south django-debug-toolbar] # Create a project (venv)$ mezzanine-project mysite (venv)$ cd mysite # Create a database (venv)$ python manage.py createdb # Apply default migrations (venv)$ python manage.py migrate # Run the webserver (venv)$ python manage.py runserver
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
    “Mantra for workingwith Mezzanine: Mezzanine is Just Django” Ken Bolton, long-time Mezzanine contributor.
  • 18.
    Creating Custom ContentTypes from django.db import models from mezzanine.pages.models import Page # The members of Page will be inherited by the Poll # model, such as title, slug, etc. For polls we can use # the title field to store the poll’s question. For our # model definition, we just add any extra fields that # aren't part of the Page model, in this case, date of # publication. class Poll(Page): # question = models.CharField(max_length=200) pub_date = models.DateTimeField("Date published") class Choice(models.Model): poll = models.ForeignKey(Poll) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) https://docs.djangoproject.com/en/1. 6/intro/tutorial01/#creating-models http://mezzanine.jupo.org/docs/content-architecture. html#creating-custom-content-types (venv)$ python manage.py startapp polls polls/models.py
  • 19.
    Admin Custom ContentTypes from copy import deepcopy from django.contrib import admin from mezzanine.core.admin import ( TabularDynamicInlineAdmin) from mezzanine.pages.admin import PageAdmin from .models import Poll, Choice poll_extra_fieldsets = ( (None, {"fields": ("pub_date",)}),) class ChoiceInline(TabularDynamicInlineAdmin): model = Choice class PollAdmin(PageAdmin): inlines = (ChoiceInline,) fieldsets = (deepcopy(PageAdmin.fieldsets) + poll_extra_fieldsets) admin.site.register(Poll, PollAdmin) https://docs.djangoproject.com/en/1. 6/intro/tutorial02/#adding-related-objects http://mezzanine.jupo.org/docs/content-architecture. html#creating-custom-content-types polls/admin.py
  • 20.
    Displaying Custom ContentTypes >>> Poll.objects.create(title="What's your favourite program language?", pub_date=now()) <Poll: What's your favourite program language?> >>> page = Page.objects.create(title="What's your favourite program language?") >>> page <Page: What's your favourite program language?> >>> page.poll <Poll: What's your favourite program language?> >>> page.get_content_model() <Poll: What’s your favourite program language> http://mezzanine.jupo.org/docs/content-architecture.html#displaying-custom-content-types {% extends "pages/page.html" %} {% load mezzanine_tags %} {% block title %} {% editable page.poll.title %}{{ page.poll.title }}{% endeditable %} {% endblock %} {% block main %} {{ block.super }} <p>Published at {{ page.poll.pub_date }}</p> <ul> {% for choice in page.poll.choice_set.all %} <li>{% editable choice.choice_text %}{{ choice.choice_text }}{% endeditable %} n. votes: {{ choice.votes }}</li> {% endfor %} </ul> {% endblock %} polls/templates/poll.py
  • 21.
    Page Processor http://mezzanine.jupo.org/docs/content-architecture.html#page-processors from django.shortcutsimport get_object_or_404 from mezzanine.pages.page_processors import processor_for from .models import Poll, Choice @processor_for(Poll) def author_form(request, page): if request.method == "POST": p = get_object_or_404(Poll, pk=page.poll.id) try: selected_choice = p.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): return {'error_message': "You didn't select a choice."} else: selected_choice.votes += 1 selected_choice.save() return {'success_message': "Thank you for your vote."} <h2>Vote!!!</h2> {% if error_message %}<div class="alert alert-danger">{{ error_message }}</div>{% endif %} {% if success_message %}<div class="alert alert-success">{{ success_message }}</div>{% endif %} <form action="." method="post"> {% csrf_token %} {% for choice in page.poll.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br /> {% endfor %} <input type="submit" value="Vote" /> </form> polls/page_processors.py polls/templates/poll.py
  • 22.
    Integrating Third-party Apps http://mezzanine.jupo.org/docs/content-architecture.html#integrating-third-party-apps-with-pages #MEZZANINE'S URLS # ---------------- # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW. ``mezzanine.urls`` INCLUDES # A *CATCH ALL* PATTERN FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine. urls`` # WILL NEVER BE MATCHED! url(r'^dj_polls/', include('dj_polls.urls', namespace='polls')), # If you'd like more granular control over the patterns in ``mezzanine.urls``, go right ahead # and take the parts you want from it, and use them directly below instead of using # ``mezzanine.urls``. ("^", include("mezzanine.urls")), Our “regoular third-party” Django app to integrate. Polls apps of official Django tutorial named here “dj_polls”. https://docs.djangoproject.com/en/1.6/intro/tutorial01/ Polls “Mezzanine” app developed earlier for custom types.
  • 23.
    Integrating Third-party Apps http://mezzanine.jupo.org/docs/content-architecture.html#integrating-third-party-apps-with-pages Otherrequirement is pages in Mezzanine’s navigation to point to the urlpatterns for these regular Django apps. Implementing this simply requires creating a page (RichTextPage, Link..) in the admin, with a URL matching a pattern used by the application.
  • 25.
    More information? Needhelp? Documentation http://mezzanine.jupo.org/ @stephen_mcd PyCon APAC keynote Source Code https://github.com/stephenmcd/mezzanine Mailing list https://groups.google.com/forum/#! forum/mezzanine-users Issues tracker https://github.com/stephenmcd/mezzanine/issues
  • 26.
    Thank you! ….questions? TalkMezzanine Project code https://github.com/simodalla/mezzanine_talk_polls