diff --git a/docs/patterns/packages.rst b/docs/patterns/packages.rst index 4d54e49c..65678a15 100644 --- a/docs/patterns/packages.rst +++ b/docs/patterns/packages.rst @@ -17,6 +17,9 @@ this:: login.html ... +Simple Packages +--------------- + To convert that into a larger one, just create a new folder `yourapplication` inside the existing one and move everything below it. Then rename `yourapplication.py` to `__init__.py`. (Make sure to delete @@ -71,6 +74,20 @@ And this is what `views.py` would look like:: def index(): return 'Hello World!' +You should then end up with something like that:: + + /yourapplication + /yourapplication + /__init__.py + /views.py + /static + /style.css + /templates + layout.html + index.html + login.html + ... + .. admonition:: Circular Imports Every Python programmer hates them, and yet we just added some: @@ -84,3 +101,99 @@ And this is what `views.py` would look like:: There are still some problems with that approach but if you want to use decorators there is no way around that. Check out the :ref:`becomingbig` section for some inspiration how to deal with that. + + +.. _working-with-modules: + +Working with Modules +-------------------- + +For larger applications with more than a dozen views it makes sense to +split the views into module. First let's look at the typical struture of +such an application:: + + /yourapplication + /yourapplication + /__init__.py + /views + __init__.py + admin.py + frontend.py + /static + /style.css + /templates + layout.html + index.html + login.html + ... + +The views are stored in the `yourapplication.views` package. Just make +sure to place an empty `__init__.py` file in there. Let's start with the +`admin.py` file in the view package. + +First we have to create a :class:`~flask.Module` object with the name of +the package. This works very similar to the :class:`~flask.Flask` object +you have already worked with, it just does not support all of the method, +but most of them are the same. + +Long story short, here a nice and concise example:: + + from flask import Module + + admin = Module(__name__) + + @admin.route('/') + def index(): + pass + + @admin.route('/login') + def login(): + pass + + @admin.route('/logout') + def login(): + pass + +Do the same with the `frontend.py` and then make sure to register the +modules in the application (`__init__.py`) like this:: + + from flask import Flask + from yourapplication.views.admin import admin + from yourapplication.views.frontend import frontend + + app = Flask(__name__) + app.register_module(admin) + app.register_module(frontend) + +So what is different when working with modules? It mainly affects URL +generation. Remember the :func:`~flask.url_for` function? When not +working with modules it accepts the name of the function as first +argument. This first argument is called the "endpoint". When you are +working with modules you can use the name of the function like you did +without, when generating modules from a function or template in the same +module. If you want to generate the URL to another module, prefix it with +the name of the module and a dot. + +Confused? Let's clear that up with some examples. Imagine you have a +method in one module (say `admin`) and you want to redirect to a +different module (say `frontend`). This would look like this:: + + @admin.route('/to_frontend') + def to_frontend(): + return redirect(url_for('frontend.index')) + + @frontend.route('/') + def index(): + return "I'm the frontend index" + +Now let's say we only want to redirect to a different module in the same +module. Then we can either use the full qualified endpoint name like we +did in the example above, or we just use the function name:: + + @frontend.route('/to_index') + def to_index(): + return redirect(url_for('index')) + + @frontend.route('/') + def index(): + return "I'm the index" diff --git a/flask.py b/flask.py index 1442650c..0993e6a0 100644 --- a/flask.py +++ b/flask.py @@ -143,6 +143,19 @@ class _RequestContext(object): def url_for(endpoint, **values): """Generates a URL to the given endpoint with the method provided. + The endpoint is relative to the active module if modules are in use. + + Here some examples: + + ==================== ======================= ============================= + Active Module Target Endpoint Target Function + ==================== ======================= ============================= + `None` ``'index'`` `index` of the application + `None` ``'.index'`` `index` of the application + ``'admin'`` ``'index'`` `index` of the `admin` module + any ``'.index'`` `index` of the application + any ``'admin.index'`` `index` of the `admin` module + ==================== ======================= ============================= :param endpoint: the endpoint of the URL (name of the function) :param values: the variable arguments of the URL rule @@ -382,6 +395,9 @@ class Module(_PackageBoundObject): @admin.route('/login') def login(): pass + + For a gentle introduction into modules, checkout the + :ref:`working-with-modules` section. """ def __init__(self, import_name, name=None, url_prefix=None):