mirror of https://github.com/mitsuhiko/flask.git
Armin Ronacher
14 years ago
3 changed files with 147 additions and 3 deletions
@ -0,0 +1,102 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
""" |
||||||
|
flask.views |
||||||
|
~~~~~~~~~~~ |
||||||
|
|
||||||
|
This module provides class based views inspired by the ones in Django. |
||||||
|
|
||||||
|
:copyright: (c) 2011 by Armin Ronacher. |
||||||
|
:license: BSD, see LICENSE for more details. |
||||||
|
""" |
||||||
|
from .globals import request |
||||||
|
|
||||||
|
|
||||||
|
http_method_funcs = frozenset(['get', 'post', 'head', 'options', |
||||||
|
'delete', 'put', 'trace']) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class View(object): |
||||||
|
"""Alternative way to use view functions. A subclass has to implement |
||||||
|
:meth:`dispatch_request` which is called with the view arguments from |
||||||
|
the URL routing system. If :attr:`methods` is provided the methods |
||||||
|
do not have to be passed to the :meth:`~flask.Flask.add_url_rule` |
||||||
|
method explicitly:: |
||||||
|
|
||||||
|
class MyView(View): |
||||||
|
methods = ['GET'] |
||||||
|
|
||||||
|
def dispatch_request(self, name): |
||||||
|
return 'Hello %s!' % name |
||||||
|
|
||||||
|
app.add_url_rule('/hello/<name>', view_func=MyView.as_view('myview')) |
||||||
|
""" |
||||||
|
|
||||||
|
methods = None |
||||||
|
|
||||||
|
def dispatch_request(self): |
||||||
|
raise NotImplementedError() |
||||||
|
|
||||||
|
@classmethod |
||||||
|
def as_view(cls, name, *class_args, **class_kwargs): |
||||||
|
"""Converts the class into an actual view function that can be |
||||||
|
used with the routing system. What it does internally is generating |
||||||
|
a function on the fly that will instanciate the :class:`View` |
||||||
|
on each request and call the :meth:`dispatch_request` method on it. |
||||||
|
|
||||||
|
The arguments passed to :meth:`as_view` are forwarded to the |
||||||
|
constructor of the class. |
||||||
|
""" |
||||||
|
def view(*args, **kwargs): |
||||||
|
self = cls(*class_args, **class_kwargs) |
||||||
|
return self.dispatch_request(*args, **kwargs) |
||||||
|
view.__name__ = name |
||||||
|
view.__doc__ = cls.__doc__ |
||||||
|
view.__module__ = cls.__module__ |
||||||
|
view.methods = cls.methods |
||||||
|
return view |
||||||
|
|
||||||
|
|
||||||
|
class MethodViewType(type): |
||||||
|
|
||||||
|
def __new__(cls, name, bases, d): |
||||||
|
rv = type.__new__(cls, name, bases, d) |
||||||
|
if rv.methods is None: |
||||||
|
methods = [] |
||||||
|
for key, value in d.iteritems(): |
||||||
|
if key in http_method_funcs: |
||||||
|
methods.append(key.upper()) |
||||||
|
# if we have no method at all in there we don't want to |
||||||
|
# add a method list. (This is for instance the case for |
||||||
|
# the baseclass or another subclass of a base method view |
||||||
|
# that does not introduce new methods). |
||||||
|
if methods: |
||||||
|
rv.methods = methods |
||||||
|
return rv |
||||||
|
|
||||||
|
|
||||||
|
class MethodView(View): |
||||||
|
"""Like a regular class based view but that dispatches requests to |
||||||
|
particular methods. For instance if you implement a method called |
||||||
|
:meth:`get` it means you will response to ``'GET'`` requests and |
||||||
|
the :meth:`dispatch_request` implementation will automatically |
||||||
|
forward your request to that. Also :attr:`options` is set for you |
||||||
|
automatically:: |
||||||
|
|
||||||
|
class CounterAPI(MethodView): |
||||||
|
|
||||||
|
def get(self): |
||||||
|
return session.get('counter', 0) |
||||||
|
|
||||||
|
def post(self): |
||||||
|
session['counter'] = session.get('counter', 0) + 1 |
||||||
|
return 'OK' |
||||||
|
|
||||||
|
app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter')) |
||||||
|
""" |
||||||
|
__metaclass__ = MethodViewType |
||||||
|
|
||||||
|
def dispatch_request(self, *args, **kwargs): |
||||||
|
meth = getattr(self, request.method.lower(), None) |
||||||
|
assert meth is not None, 'Not implemented method' |
||||||
|
return meth(*args, **kwargs) |
Loading…
Reference in new issue