Skip to content

Commit

Permalink
Merge pull request django-cms#4132 from stefanfoulis/feature/tutorial…
Browse files Browse the repository at this point in the history
…-django-1.7-compat

update tutorial for Django 1.7 (and django CMS 3.1)
  • Loading branch information
yakky committed May 31, 2015
2 parents 5af5648 + 3c7c44f commit a0816fc
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 78 deletions.
6 changes: 4 additions & 2 deletions docs/introduction/apphooks.rst
Expand Up @@ -3,7 +3,7 @@ Apphooks
#########

Right now, our django Polls app is statically hooked into the project's
``urls.py``. This is allright, but we can do more, by attaching applications to
``urls.py``. This is all right, but we can do more, by attaching applications to
django CMS pages.

We do this with an **Apphook**, created using a :class:`CMSApp
Expand All @@ -12,7 +12,9 @@ We do this with an **Apphook**, created using a :class:`CMSApp
Apphooks live in a file called ``cms_app.py``, so create one in your Poll
application.

This is the most basic example for a django CMS app::
This is the most basic example for a django CMS app:

.. code-block:: python
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
Expand Down
29 changes: 15 additions & 14 deletions docs/introduction/menu.rst
Expand Up @@ -9,16 +9,20 @@ is still only determined by django CMS Pages.
We can hook into the django CMS menu system to add our own nodes to that
navigation menu.

For this we need a file called ``menu.py`` in the Polls application::
For this we need a file called ``menu.py`` in our application. Add
``polls_plugin/menu.py``:

.. code-block:: python
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from cms.menu_bases import CMSAttachMenu
from menus.base import Menu, NavigationNode
from menus.base import NavigationNode
from menus.menu_pool import menu_pool
from .models import Poll
from polls.models import Poll
class PollsMenu(CMSAttachMenu):
name = _("Polls Menu") # give the menu a name this is required.
Expand All @@ -29,24 +33,21 @@ For this we need a file called ``menu.py`` in the Polls application::
"""
nodes = []
for poll in Poll.objects.all():
# the menu tree consists of NavigationNode instances
# Each NavigationNode takes a label as its first argument, a URL as
# its second argument and a (for this tree) unique id as its third
# argument.
node = NavigationNode(
poll.question,
reverse('polls:detail', args=(poll.pk,)),
poll.pk
title=poll.question,
url=reverse('polls:detail', args=(poll.pk,)),
id=poll.pk, # unique id for this node within the menu
)
nodes.append(node)
return nodes
menu_pool.register_menu(PollsMenu) # register the menu.
menu_pool.register_menu(PollsMenu)
What's happening here:

* we define a ``PollsMenu`` class, and register it
* we give the class a ``name`` attribute
* we give the class a ``name`` attribute (will be displayed in admin)
* in its ``get_nodes()`` method, we build and return a list of nodes, where:
* first we get all the ``Poll`` objects
* ... and then create a ``NavigationNode`` object from each one
Expand All @@ -59,5 +60,5 @@ So open your ``cms_app.py`` and add::

to the ``PollsApp`` class.

Now, any page that is attached to the ``Polls`` application have, below its
own node in the navigation menu, a node for each of the Polls in the database.
Any page that is attached to the ``Polls`` application will now have submenu
items for each of the Polls in the database.
44 changes: 31 additions & 13 deletions docs/introduction/plugins.rst
Expand Up @@ -29,18 +29,22 @@ You should end up with a folder structure similar to this::
Let's add it this application to our project. Add ``'polls'`` to the end of ``INSTALLED_APPS`` in
your project's `settings.py` (see the note on :ref:`installed_apps` about ordering ).

Add the following line to ``urlpatterns`` in the project's ``urls.py``::
Add the following line to ``urlpatterns`` in the project's ``urls.py``:

.. code-block:: python
url(r'^polls/', include('polls.urls', namespace='polls')),
Make sure this line is included **before** the line for the django-cms urls::
Make sure this line is included **before** the line for the django-cms urls:

.. code-block:: python
url(r'^', include('cms.urls')),
django CMS's URL pattern needs to be last, because it "swallows up" anything
that hasn't already been matched by a previous pattern.

Now run the application's migrations using ``south``::
Now run the application's migrations::

python manage.py migrate polls

Expand All @@ -51,8 +55,9 @@ However, in pages of the polls application we only have minimal templates, and
no navigation or styling. Let's improve this by overriding the polls
application's base template.

add ``my_site/templates/polls/base.html``::
add ``my_site/templates/polls/base.html``:

.. code-block:: html+django

{% extends 'base.html' %}

Expand Down Expand Up @@ -104,7 +109,9 @@ So our workspace looks like this::
The Plugin Model
================

In your poll application’s ``models.py`` add the following::
In your poll application’s ``models.py`` add the following:

.. code-block:: python
from django.db import models
from cms.models import CMSPlugin
Expand All @@ -129,7 +136,9 @@ Now create a file ``cms_plugins.py`` in the same folder your models.py is in.
The plugin class is responsible for providing django CMS with the necessary
information to render your plugin.

For our poll plugin, we're going to write the following plugin class::
For our poll plugin, we're going to write the following plugin class:

.. code-block:: python
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
Expand Down Expand Up @@ -170,23 +179,32 @@ the plugin which :attr:`render_template

In this case the template needs to be at
``polls_plugin/templates/djangocms_polls/poll_plugin.html`` and should look
something like this::
something like this:

.. code-block:: html+django

<h1>{{ instance.poll.question }}</h1>

<form action="{% url 'polls:vote' instance.poll.id %}" method="post">
{% csrf_token %}
{% for choice in instance.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 %}
<div class="form-group">
{% for choice in instance.poll.choice_set.all %}
<div class="radio">
<label>
<input type="radio" name="choice" value="{{ choice.id }}">
{{ choice.choice_text }}
</label>
</div>
{% endfor %}
</div>
<input type="submit" value="Vote" />
</form>


Now add ``polls_plugin`` to ``INSTALLED_APPS`` and create a database migration
to add the plugin table (using South)::
to add the plugin table::

python manage.py schemamigration polls_plugin --init
python manage.py makemigrations polls
python manage.py migrate polls_plugin

Finally, start the runserver and visit http://localhost:8000/.
Expand Down
12 changes: 9 additions & 3 deletions docs/introduction/templates_placeholders.rst
Expand Up @@ -58,7 +58,9 @@ static placeholders from a template, you can reuse them later.

So let's add a footer to all our pages. Since we want our footer on every
single page, we should add it to our base template
(``mysite/templates/base.html``). Place it at the bottom of the HTML body::
(``mysite/templates/base.html``). Place it at the bottom of the HTML body:

.. code-block:: html+django

<footer>
{% static_placeholder 'footer' %}
Expand All @@ -75,14 +77,18 @@ Rendering Menus

In order to render the CMS's menu in your template you can use the :doc:`show_menu </reference/navigation>` tag.

The example we use in ``mysite/templates/base.html`` is::
The example we use in ``mysite/templates/base.html`` is:

.. code-block:: html+django

<ul class="nav navbar-nav">
{% show_menu 0 1 100 100 "menu.html" %}
</ul>

Any template that uses ``show_menu`` must load the CMS's ``menu_tags`` library
first::
first:

.. code-block:: html+django

{% load menu_tags %}

Expand Down
93 changes: 60 additions & 33 deletions docs/introduction/third_party.rst
Expand Up @@ -4,36 +4,38 @@ Integrating a third-party application

We've already written our own django CMS plugins and apps, but now we want to
extend our CMS with a third party app,
`Aldryn blog <https://github.com/aldryn/aldryn-blog>`_.
`Aldryn News & Blog <https://github.com/aldryn/aldryn-newsblog>`_.

First, we need to install the app into our virtual environment from
`PyPI <http://pypi.python.org>`_::

pip install aldryn-blog
pip install aldryn-newsblog

Add the app and any of its requirements that are not there already to
``INSTALLED_APPS`` in ``settings.py``. Some *will* be already present; it's up
to you to check them::
to you to check them:

'aldryn_blog',
'aldryn_common',
.. code-block:: python
'aldryn_apphooks_config',
'aldryn_boilerplates',
'django_select2',
'aldryn_categories',
'aldryn_newsblog',
'aldryn_people',
'aldryn_reversion',
'djangocms_text_ckeditor',
'easy_thumbnails',
'filer',
'parler',
'reversion',
'sortedm2m',
'taggit',
'hvad',

One of the dependencies is ``easy_thumbnails``. It has already switched to
Django-1.7-style migrations and needs some extra configuration to work with
South. In ``settings.py``::
SOUTH_MIGRATION_MODULES = {
'easy_thumbnails': 'easy_thumbnails.south_migrations',
}
One of the dependencies is django-filer. It provides a special feature that
allows nicer image cropping. For this to work it needs it's own
thumbnail processor (easy-thumbnails) to be inserted in ``settings.py``:

Configure the image thumbnail processors in ``settings.py``::
.. code-block:: python
THUMBNAIL_PROCESSORS = (
'easy_thumbnails.processors.colorspace',
Expand All @@ -43,12 +45,17 @@ Configure the image thumbnail processors in ``settings.py``::
'easy_thumbnails.processors.filters',
)
Configure the templates that will be used by Aldryn Blog (if you configured
django CMS to use Bootstrap templates, choose `bootstrap3` instead)::
aldryn-newsblog uses aldryn-boilerplates_ to provide multiple sets of templates
and staticfiles for different css frameworks. We're using
bootstrap3 in this tutorial, so lets choose `bootstrap3`.:

.. code-block:: python
ALDRYN_BOILERPLATE_NAME='bootstrap3'
ALDRYN_BOILERPLATE_NAME='legacy'
Add boilerplates finder to ``STATICFILES_FINDERS``:

Add boilerplates finder to ``STATICFILES_FINDERS``::
.. code-block:: python
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
Expand All @@ -57,14 +64,20 @@ Add boilerplates finder to ``STATICFILES_FINDERS``::
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]
Add the boilerplates loader to ``TEMPLATE_CONTEXT_PROCESSORS``::
Add the boilerplate template loader to ``TEMPLATE_LOADERS``:

TEMPLATE_CONTEXT_PROCESSORS = [
# ...
'aldryn_boilerplates.context_processors.boilerplate',
]
.. code-block:: python
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'aldryn_boilerplates.template_loaders.AppDirectoriesLoader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader'
)
Add the boilerplates context processor to ``TEMPLATE_CONTEXT_PROCESSORS``:

Add the boilerplates context processor to ``TEMPLATE_CONTEXT_PROCESSORS``::
.. code-block:: python
TEMPLATE_CONTEXT_PROCESSORS = [
# ...
Expand All @@ -78,18 +91,32 @@ Since we added a new app, we need to update our database::

Start the server again.

The blog application comes with a django CMS apphook, so add a new django CMS
page, and add the blog application to it as you did for Polls in the previous
tutorial. *You may need to restart your server at this point.*
The newsblog application comes with a django CMS apphook, so add a new django
CMS page (let's call it 'Blog'), and add the blog application to it as you did
for Polls in the previous tutorial step.
In this case we also have to add an "Application configuration" (see the
field right under the apphook field). You can configure some settings here,
like the url format. It's also possible to add multiple instances of the
application, if you like.
The *Instance namespace* should be ``blog`` (this is used for reversing urls).
Choose ``Blog`` as the *Application title* and choose whatever *Permalink type*
you prefer.

Publish the new page, and you should find the blog application at work there.

You can add new blog posts using the admin, but also have a look at the toolbar.
You can now select "Blog" > "Add Blog Post..." from it and add a new blog post
directly from there.
*You may need to restart your server at this point.*

Try also inserting a "Latest blog entries" plugin into another page - as a good
django CMS application, Aldryn Blog comes with plugins.

You can add new blog posts using the admin, but also have a look at the
toolbar. When you're within the urls of the blog, you should see an extra menu
item called "Blog".
You can now select "Blog" > "Add new article..." from it and add a new blog
post directly from there.

Try also inserting a "Latest articles" plugin into another page - as a good
django CMS application, *Aldryn News & Blog* comes with plugins.

In the next tutorial, we're going to integrate our Polls app into the toolbar
in, just like the blog application has been.

.. _aldryn-boilerplates: https://github.com/aldryn/aldryn-boilerplates

0 comments on commit a0816fc

Please sign in to comment.