Skip to content

Commit

Permalink
Merge pull request #6 from thisissoon/feature/include-endpoint
Browse files Browse the repository at this point in the history
Feature/include endpoint
  • Loading branch information
krak3n committed May 19, 2014
2 parents c90b535 + f5f61ce commit 03afffe
Show file tree
Hide file tree
Showing 28 changed files with 464 additions and 133 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ Change Log

Next Release
------------
* Feature: ``Include`` now supports ``endpoint`` prefixing
* Feature: Blueprint router can now take a blueprint instance
* Imroved: Test Suite now uses PyTest
* Feature: Added support for ``VIA_ROUTES_NAME`` to set a common routes name
* Improved: Test Suite now uses PyTest
* Improved: ``ImproperlyConfigured`` now raised if routes module is not defined
in either ``init_app`` or in application configuration via
``VIA_ROUTES_MODULE``
* Feature: Added support for ``VIA_ROUTES_NAME`` to set a common routes name

2014.05.08
----------
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions REQS_TEST.txt → REQS.TESTING.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
pytest==2.5.2
pytest-cov==1.6
pytest_spec==0.2.17

Flask-Testing
1 change: 1 addition & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ on GitHub.
* `Basic Restful Example <https://github.com/thisissoon/Flask-Via/blob/master/flask_via/examples/restful.py>`_
* `Basic Admin Example <https://github.com/thisissoon/Flask-Via/blob/master/flask_via/examples/admin.py>`_
* `Small Application Example <https://github.com/thisissoon/Flask-Via/tree/master/flask_via/examples/small>`_
* `Include Application Example <https://github.com/thisissoon/Flask-Via/tree/master/flask_via/examples/include>`_
* `Blueprint Application Example <https://github.com/thisissoon/Flask-Via/tree/master/flask_via/examples/blueprints>`_
39 changes: 38 additions & 1 deletion docs/include.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ somewhere else in your application.
* ``routes_name``: (Optional) If you have not called the list of routes in
the moduke ``routes`` you can set that here, for example ``urls``.
* ``url_prefix``: (optional) Add a url prefix to all routes included
* ``endpoint``: (optional) Add a endpoint prefix to all routes included

Example
~~~~~~~
Expand Down Expand Up @@ -81,6 +82,31 @@ top level ``routes.py`` now looks like this::
This will result in the url to the view becoming ``/foo/bar`` instead of
``/bar``.

Endpoints
~~~~~~~~~

The :py:class:`flask_via.routers.Include` router also allows you to add
endpoint prefixes to your included routes, much like blueprints. This is
supported by:

* :py:class:`flask_via.routers.default.Basic`
* :py:class:`flask_via.routers.default.Pluggable`
* :py:class:`flask_via.routers.default.Blueprint`

Example
^^^^^^^

We will assume the same application structure as we have in the previous
example applications. The top level ``routes.py`` can be altered as followes::

from flask.ext.via.routers import Include

routes = [
Include('foo.bar.routes', url_prefix='/foo', endpoint='foo')
]

We can now call ``url_for`` with ``foo.bar`` which would generate ``/foo/bar``.

Blueprint Router
----------------

Expand Down Expand Up @@ -203,7 +229,11 @@ blueprint examples, except our top level ``routes.py`` now looks like this::
from flask.ext.via.routers import default, Include

routes = [
Include('foo.routes', routes_name='api', url_prefix='/api/v1')
Include(
'foo.routes',
routes_name='api',
url_prefix='/api/v1',
endpoint='api.v1')
]

api = [
Expand Down Expand Up @@ -232,3 +262,10 @@ would be accessed on the following urls:
Hopefully you can see from this that :py:class:`flask_via.routers.Include`
coupled with :py:class:`flask_via.routers.default.Blueprint` can offer some
potentially powerful routing options for your application.

You will also notice we used the ``endpoint`` keyword agument in the Include.
This means our urls can also be reversed using ``url_for``, for example::

* ``url_for('api.v1.bar.bar')`` would return: ``/api/v1/bar/bar``
* ``url_for('api.v1.baz.bar')`` would return: ``/api/v1/baz/bar``
* ``url_for('api.v1.fap.bar')`` would return: ``/api/v1/fap/bar``
8 changes: 5 additions & 3 deletions docs/routers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ using Flasks pluggable views.

**Arguments**:
* ``url``: The url for this route, e.g: ``/foo``
* ``class``: The Flask Pluggable View Class
* ``name``: The name of the view, aka: endpoint

**Keyword Arguments**:
* ``view_func``: View function
* ``**kwargs``: Arbitrary keyword arguments, for example ``methods``

Example
^^^^^^^
Expand All @@ -65,8 +67,8 @@ Example
return 'foo'

routes = [
Plugganle('/', view_func=FooView.as_view('foo')),
Plugganle('/<bar>', view_func=FooView.as_view('foobar')),
Plugganle('/', FooView, 'foo'),
Plugganle('/<bar>', FooView, 'foobar'),
]

``Flask-Restful`` Routers
Expand Down
2 changes: 1 addition & 1 deletion flask_via/examples/blueprints/foo/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
from flask.ext.via.routers import default

routes = [
default.Basic('/', views.foo),
default.Basic('/baz', views.baz),
]
1 change: 1 addition & 0 deletions flask_via/examples/blueprints/foo/templates/baz.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Baz View in Blueprint
1 change: 0 additions & 1 deletion flask_via/examples/blueprints/foo/templates/foo.html

This file was deleted.

4 changes: 2 additions & 2 deletions flask_via/examples/blueprints/foo/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
from flask import render_template


def foo():
return render_template('foo.html')
def baz():
return render_template('baz.html')
5 changes: 3 additions & 2 deletions flask_via/examples/blueprints/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
Include(
'flask_via.examples.blueprints.routes',
routes_name='urls',
url_prefix='/bar'
url_prefix='/bar',
endpoint='bar'
)
]

urls = [
default.Blueprint(
'foo.bar',
'foo',
'flask_via.examples.blueprints.foo',
url_prefix='/foo',
template_folder='templates'
Expand Down
Empty file.
20 changes: 20 additions & 0 deletions flask_via/examples/include/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-

"""
flask_via.examples.include.app
==============================
A include ``Flask-Via`` example Flask application.
"""

from flask import Flask
from flask.ext.via import Via

app = Flask(__name__)
app.config['VIA_ROUTES_MODULE'] = 'flask_via.examples.include.routes'

via = Via()
via.init_app(app)

if __name__ == '__main__':
app.run(debug=True)
Empty file.
17 changes: 17 additions & 0 deletions flask_via/examples/include/bar/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-

"""
flask_via.examples.include.foo.routes
=====================================
A include ``Flask-Via`` example Flask application.
"""

from flask_via.examples.include.bar.views import FooView, FazView, flop
from flask.ext.via.routers.default import Basic, Pluggable

routes = [
Pluggable('/foo', FooView, 'foo'),
Pluggable('/faz', FazView, 'faz'),
Basic('/flop', flop),
]
27 changes: 27 additions & 0 deletions flask_via/examples/include/bar/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-

"""
flask_via.examples.include.bar.views
====================================
A include ``Flask-Via`` example Flask application.
"""

from flask import request
from flask.views import MethodView


class FooView(MethodView):

def get(self):
return '{0.path} - {0.endpoint}'.format(request)


class FazView(MethodView):

def get(self):
return '{0.path} - {0.endpoint}'.format(request)


def flop():
return '{0.path} - {0.endpoint}'.format(request)
Empty file.
21 changes: 21 additions & 0 deletions flask_via/examples/include/foo/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-

"""
flask_via.examples.include.foo.routes
=====================================
A include ``Flask-Via`` example Flask application.
"""

from flask_via.examples.include.foo.views import BarView, BazView
from flask.ext.via.routers import Include
from flask.ext.via.routers.default import Pluggable

routes = [
Pluggable('/bar', BarView, 'bar'),
Pluggable('/baz', BazView, 'baz'),
Include(
'flask_via.examples.include.bar.routes',
url_prefix='/bar',
endpoint='bar')
]
23 changes: 23 additions & 0 deletions flask_via/examples/include/foo/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-

"""
flask_via.examples.include.foo.views
====================================
A include ``Flask-Via`` example Flask application.
"""

from flask import request
from flask.views import MethodView


class BarView(MethodView):

def get(self):
return '{0.path} - {0.endpoint}'.format(request)


class BazView(MethodView):

def get(self):
return '{0.path} - {0.endpoint}'.format(request)
17 changes: 17 additions & 0 deletions flask_via/examples/include/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-

"""
flask_via.examples.include.routes
=================================
A include ``Flask-Via`` example Flask application.
"""

from flask.ext.via.routers import Include

routes = [
Include(
'flask_via.examples.include.foo.routes',
url_prefix='/foo',
endpoint='foo')
]
9 changes: 5 additions & 4 deletions flask_via/examples/mixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ def foo(bar=None):
api = restful.Api(app)

routes = [
# Basic Views
Basic('/basic', foo),
Basic('/basic/<bar>', foo, endpoint='foo.basic'),
Pluggable('/pluggable', view_func=FooView.as_view('foo.pluggable')),
Pluggable(
'/pluggable/<bar>',
view_func=FooView.as_view('foobar.pluggable')),
# Pluggable Viewa
Pluggable('/pluggable', FooView, 'foo.pluggable'),
Pluggable('/pluggable/<bar>', FooView, 'foobar.pluggable'),
# Flask Restful Resource Views
Resource('/resource', FooResource, 'foo.resource'),
Resource('/resource/<bar>', FooResource, endpoint='foobar.resource')
]
Expand Down
4 changes: 2 additions & 2 deletions flask_via/examples/pluggable.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def get(self, bar=None):
app = Flask(__name__)

routes = [
Pluggable('/foo', view_func=FooView.as_view('foo')),
Pluggable('/foo/<bar>', view_func=FooView.as_view('foo2')),
Pluggable('/foo', FooView, 'foo'),
Pluggable('/foo/<bar>', FooView, 'foo2'),
]

via = Via()
Expand Down
38 changes: 33 additions & 5 deletions flask_via/routers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ class Include(BaseRouter, RoutesImporter):
This is not a implementation of Flask blueprints
"""

def __init__(self, routes_module, routes_name=None, url_prefix=None):
def __init__(
self,
routes_module,
routes_name=None,
url_prefix=None,
endpoint=None):
""" Constructor for Include router, taking the passed arguments
and storing them on the instance.
Expand All @@ -79,6 +84,7 @@ def __init__(self, routes_module, routes_name=None, url_prefix=None):
.. versionchanged:: #NEXTRELEASE
* ``routes_name`` keyword argument default value set to ``None``
* ``endpoint`` keyword argument added
Arguments
---------
Expand All @@ -87,23 +93,34 @@ def __init__(self, routes_module, routes_name=None, url_prefix=None):
Keyword Arguments
-----------------
routes_name : str (optional)
routes_name : str, optional
Name of the variable holding the routes in the module, defaults to
``routes``
url_prefix : str (optional)
url_prefix : str, optional
Adds a url prefix to all routes included by the router, defaults
to ``None``
endpoint : str, optional
Prefix an endpoint to all routes included, defaults to ``None``
"""

self.routes_module = routes_module
self.routes_name = routes_name
self.url_prefix = url_prefix
self.endpoint = endpoint

def add_to_app(self, app, **kwargs):
""" Instead of adding a route to the flask application this will
include and load routes similar, same as in the
:py:class:`flask_via.Via` class.abs
.. versionchanged:: 2014.05.08
* ``url_prefix`` now injected into kwargs when loading in routes
.. versionchanged:: #NEXTRELEASE
* ``endpoint`` now injects into kwargs when loading in routes
Arguments
---------
app : flask.app.Flask
Expand All @@ -117,14 +134,25 @@ def add_to_app(self, app, **kwargs):
self.routes_name = app.config.get('VIA_ROUTES_NAME', 'routes')

# Inject url_prefix into kwargs
if self.url_prefix is not None:
if self.url_prefix:
# This allows us to chain url prefix's when multiple includes
# are called
try:
url_prefix = kwargs['url_prefix']
except KeyError:
url_prefix = ''
kwargs['url_prefix'] = url_prefix + self.url_prefix
finally:
kwargs['url_prefix'] = url_prefix + self.url_prefix

# Inject endpoint into kwagrs
if self.endpoint is not None:
# This allows us to add a endpoint prefix to routes included
try:
endpoint = kwargs['endpoint']
except KeyError:
endpoint = ''
finally:
kwargs['endpoint'] = endpoint + self.endpoint + '.'

# Get the routes
routes = self.include(self.routes_module, self.routes_name)
Expand Down

0 comments on commit 03afffe

Please sign in to comment.