forked from orbit-oss/flask
Added class based views
This commit is contained in:
parent
1c8097b35a
commit
dcf21989dc
3 changed files with 147 additions and 3 deletions
102
flask/views.py
Normal file
102
flask/views.py
Normal file
|
|
@ -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…
Add table
Add a link
Reference in a new issue