Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 103 lines (78 sloc) 3.449 kb
dcf2198 @mitsuhiko Added class based views
authored
1 # -*- coding: utf-8 -*-
2 """
3 flask.views
4 ~~~~~~~~~~~
5
6 This module provides class based views inspired by the ones in Django.
7
8 :copyright: (c) 2011 by Armin Ronacher.
9 :license: BSD, see LICENSE for more details.
10 """
11 from .globals import request
12
13
14 http_method_funcs = frozenset(['get', 'post', 'head', 'options',
15 'delete', 'put', 'trace'])
16
17
18
19 class View(object):
20 """Alternative way to use view functions. A subclass has to implement
21 :meth:`dispatch_request` which is called with the view arguments from
22 the URL routing system. If :attr:`methods` is provided the methods
23 do not have to be passed to the :meth:`~flask.Flask.add_url_rule`
24 method explicitly::
25
26 class MyView(View):
27 methods = ['GET']
28
29 def dispatch_request(self, name):
30 return 'Hello %s!' % name
31
32 app.add_url_rule('/hello/<name>', view_func=MyView.as_view('myview'))
33 """
34
35 methods = None
36
37 def dispatch_request(self):
38 raise NotImplementedError()
39
40 @classmethod
41 def as_view(cls, name, *class_args, **class_kwargs):
42 """Converts the class into an actual view function that can be
43 used with the routing system. What it does internally is generating
44 a function on the fly that will instanciate the :class:`View`
45 on each request and call the :meth:`dispatch_request` method on it.
46
47 The arguments passed to :meth:`as_view` are forwarded to the
48 constructor of the class.
49 """
50 def view(*args, **kwargs):
51 self = cls(*class_args, **class_kwargs)
52 return self.dispatch_request(*args, **kwargs)
53 view.__name__ = name
54 view.__doc__ = cls.__doc__
55 view.__module__ = cls.__module__
56 view.methods = cls.methods
57 return view
58
59
60 class MethodViewType(type):
61
62 def __new__(cls, name, bases, d):
63 rv = type.__new__(cls, name, bases, d)
64 if rv.methods is None:
65 methods = []
66 for key, value in d.iteritems():
67 if key in http_method_funcs:
68 methods.append(key.upper())
69 # if we have no method at all in there we don't want to
70 # add a method list. (This is for instance the case for
71 # the baseclass or another subclass of a base method view
72 # that does not introduce new methods).
73 if methods:
74 rv.methods = methods
75 return rv
76
77
78 class MethodView(View):
79 """Like a regular class based view but that dispatches requests to
80 particular methods. For instance if you implement a method called
81 :meth:`get` it means you will response to ``'GET'`` requests and
82 the :meth:`dispatch_request` implementation will automatically
83 forward your request to that. Also :attr:`options` is set for you
84 automatically::
85
86 class CounterAPI(MethodView):
87
88 def get(self):
89 return session.get('counter', 0)
90
91 def post(self):
92 session['counter'] = session.get('counter', 0) + 1
93 return 'OK'
94
95 app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter'))
96 """
97 __metaclass__ = MethodViewType
98
99 def dispatch_request(self, *args, **kwargs):
100 meth = getattr(self, request.method.lower(), None)
101 assert meth is not None, 'Not implemented method'
102 return meth(*args, **kwargs)
Something went wrong with that request. Please try again.