Finish flatpagesplugin; add plugin docs

This commit is contained in:
Will Kahn-Greene 2012-06-10 14:51:13 -04:00
parent 8545dd50f0
commit 4bd65f69c7
11 changed files with 244 additions and 65 deletions

View File

@ -47,7 +47,17 @@ MediaGoblin website. It is written for site administrators.
siteadmin/codebase
Part 2: Plugin Writer's Guide
Part 2: Core plugin documentation
=================================
.. toctree::
:maxdepth: 1
plugindocs/flatpagesfile
plugindocs/sampleplugin
Part 3: Plugin Writer's Guide
=============================
This guide covers writing new GNU MediaGoblin plugins.

View File

@ -0,0 +1 @@
.. include:: ../../../mediagoblin/plugins/flatpagesfile/README.rst

View File

@ -0,0 +1 @@
.. include:: ../../../mediagoblin/plugins/sampleplugin/README.rst

View File

@ -89,7 +89,7 @@ class MediaGoblinApp(object):
self.public_store, self.queue_store = setup_storage()
# set up routing
self.routing = routing.get_mapper()
self.routing = routing.get_mapper(PluginCache().get_routes())
# set up staticdirector tool
self.staticdirector = get_staticdirector(app_config)

View File

@ -1,50 +0,0 @@
========
README
========
This is the flatpages file plugin. It allows you to add pages to your
MediaGoblin instance which are not generated from user content. For
example, this is useful for these pages:
* About this site
* Terms of service
* Privacy policy
* How to get an account here
* ...
How to add pages
================
To add pages, you must edit template files on the file system in your
`local_templates` directory.
The directory structure looks kind of like this::
local_templates
|- flatpagesfile
|- flatpage1.html
|- flatpage2.html
|- ...
The ``.html`` file contains the content of your page. It's just a
template like all the other templates you have.
Here's an example::
{% extends "flatpagesfile/base.html" %}
{% block mediagoblin_content %}
<h1>About this site</h1>
<p>
This site is a MediaGoblin instance set up to host media for
me, my family and my friends.
</p>
{% endblock %}
.. Note::
If you have a bunch of flatpages that kind of look like one
another, take advantage of Jinja2 template extending and create a
base template that the others extend.

View File

@ -0,0 +1,132 @@
======================
flatpagesfile plugin
======================
This is the flatpages file plugin. It allows you to add pages to your
MediaGoblin instance which are not generated from user content. For
example, this is useful for these pages:
* About this site
* Terms of service
* Privacy policy
* How to get an account here
* ...
How to configure
================
Add the following to your MediaGoblin .ini file in the ``[plugins]``
section::
[[mediagoblin.plugins.flatpagesfile]]
This tells MediaGoblin to load the flatpagesfile plugin. This is the
subsection that you'll do all flatpagesfile plugin configuration in.
How to add pages
================
To add a new page to your site, you need to do two things:
1. add a route to the MediaGoblin .ini file in the flatpagesfile
subsection
2. write a template that will get served when that route is requested
Routes
------
First, let's talk about the route.
A route is a key/value in your configuration file.
The key starts with ``path`` and then has a number after that. For
example: ``path1``, ``path2``, ... ``path15``, ...
The value has three parts separated by commas:
1. **route name**: You can use this with `url()` in templates to have
MediaGoblin automatically build the urls for you. It's very handy.
It should be "unique" and it should be alphanumeric characters and
hyphens. I wouldn't put spaces in there.
Examples: ``flatpages-about``, ``about-view``, ``contact-view``, ...
2. **route path**: This is the url that this route matches.
Examples: ``/about``, ``/contact``, ``/pages/about``, ...
Technically, this is a regular expression and you can do anything
with this that you can do with the routepath parameter of
`routes.Route`. For more details, see `the routes documentation
<http://routes.readthedocs.org/en/latest/>`_.
Example: ``/siteadmin/{adminname:\w+}``
.. Note::
If you're doing something fancy, enclose the route in single
quotes.
For example: ``'/siteadmin/{adminname:\w+}'``
3. **template**: The template to use for this url. The template is in
the flatpagesfile template directory, so you just need to specify
the file name.
Like with other templates, if it's an HTML file, it's good to use
the ``.html`` extensions.
Examples: ``index.html``, ``about.html``, ``contact.html``, ...
Here's an example configuration that adds two flat pages: one for an
"About this site" page and one for a "Terms of service" page::
[[mediagoblin.plugins.flatpagesfile]]
page1 = about-view, '/about', about.html
page2 = terms-view, '/terms', terms.html
Templates
---------
To add pages, you must edit template files on the file system in your
`local_templates` directory.
The directory structure looks kind of like this::
local_templates
|- flatpagesfile
|- flatpage1.html
|- flatpage2.html
|- ...
The ``.html`` file contains the content of your page. It's just a
template like all the other templates you have.
Here's an example that extends the `flatpagesfile/base.html`
template::
{% extends "flatpagesfile/base.html" %}
{% block mediagoblin_content %}
<h1>About this site</h1>
<p>
This site is a MediaGoblin instance set up to host media for
me, my family and my friends.
</p>
{% endblock %}
.. Note::
If you have a bunch of flatpages that kind of look like one
another, take advantage of Jinja2 template extending and create a
base template that the others extend.

View File

@ -17,7 +17,10 @@
import logging
import os
from routes.route import Route
from mediagoblin.tools import pluginapi
from mediagoblin.tools.response import render_to_response
PLUGIN_DIR = os.path.dirname(__file__)
@ -26,16 +29,45 @@ PLUGIN_DIR = os.path.dirname(__file__)
_log = logging.getLogger(__name__)
class FlatpagesPlugin(pluginapi.Plugin):
def flatpage_handler(template):
"""Flatpage view generator
Given a template, generates the controller function for handling that
route.
"""
def _flatpage_handler(request, *args, **kwargs):
return render_to_response(
request, 'flatpagesfile/%s' % template,
{'args': args, 'kwargs': kwargs})
return _flatpage_handler
class FlatpagesFilePlugin(pluginapi.Plugin):
"""
This is the flatpages plugin class. See the README for how to use
flatpages.
"""
def __init__(self):
self._setup_plugin_called = 0
def setup_plugin(self):
self.config = pluginapi.get_config('mediagoblin.plugins.flatpagesfile')
_log.info('Setting up flatpages....')
_log.info('Setting up flatpagesfile....')
# Register the template path.
pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
# Set up and register routes.
pages = [(int(key.replace('page', '')), val)
for key, val in self.config.items()
if key.startswith('page')]
pages = [mapping for index, mapping in sorted(pages)]
routes = []
for name, url, template in pages:
name = 'flatpagesfile.%s' % name.strip()
controller = flatpage_handler(template)
routes.append(
Route(name, url, controller=controller))
pluginapi.register_routes(routes)
_log.info('Done setting up flatpagesfile!')

View File

@ -1,6 +0,0 @@
========
README
========
This is a sample plugin. It does nothing interesting other than show
one way to structure a MediaGoblin plugin.

View File

@ -0,0 +1,8 @@
==============
sampleplugin
==============
This is a sample plugin. It does nothing interesting other than show
one way to structure a MediaGoblin plugin.
The code for this plugin is in ``mediagoblin/plugins/sampleplugin/``.

View File

@ -26,10 +26,13 @@ from mediagoblin.webfinger.routing import webfinger_well_known_routes, \
from mediagoblin.admin.routing import admin_routes
def get_mapper():
def get_mapper(plugin_routes):
mapping = Mapper()
mapping.minimization = False
# Plugin routes go first so they can override default routes.
mapping.extend(plugin_routes)
mapping.connect(
"index", "/",
controller="mediagoblin.views:root_view")

View File

@ -80,6 +80,9 @@ class PluginCache(object):
# list of registered template paths
"template_paths": set(),
# list of registered routes
"routes": [],
}
def clear(self):
@ -106,6 +109,13 @@ class PluginCache(object):
"""Returns a tuple of registered template paths"""
return tuple(self.template_paths)
def register_route(self, route):
"""Registers a single route"""
self.routes.append(route)
def get_routes(self):
return tuple(self.routes)
class MetaPluginClass(type):
"""Metaclass for PluginBase derivatives"""
@ -119,7 +129,7 @@ class MetaPluginClass(type):
class Plugin(object):
"""Exttend this class for plugins.
"""Extend this class for plugins.
Example::
@ -139,6 +149,44 @@ class Plugin(object):
pass
def register_routes(routes):
"""Registers one or more routes
If your plugin handles requests, then you need to call this with
the routes your plugin handles.
A "route" is a `routes.Route` object. See `the routes.Route
documentation
<http://routes.readthedocs.org/en/latest/modules/route.html>`_ for
more details.
Example passing in a single route:
>>> from routes import Route
>>> register_routes(Route('about-view', '/about',
... controller=about_view_handler))
Example passing in a list of routes:
>>> from routes import Route
>>> register_routes([
... Route('contact-view', '/contact', controller=contact_handler),
... Route('about-view', '/about', controller=about_handler)
... ])
.. Note::
Be careful when designing your route urls. If they clash with
core urls, then it could result in DISASTER!
"""
if isinstance(routes, (tuple, list)):
for route in routes:
PluginCache().register_route(route)
else:
PluginCache().register_route(routes)
def register_template_path(path):
"""Registers a path for template loading