Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 113 lines (88 sloc) 4.051 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):
775caf7 @mitsuhiko Improved cbv and added tests
authored
38 """Subclasses have to override this method to implement the
39 actual view functionc ode. This method is called with all
40 the arguments from the URL rule.
41 """
dcf2198 @mitsuhiko Added class based views
authored
42 raise NotImplementedError()
43
44 @classmethod
45 def as_view(cls, name, *class_args, **class_kwargs):
46 """Converts the class into an actual view function that can be
47 used with the routing system. What it does internally is generating
48 a function on the fly that will instanciate the :class:`View`
49 on each request and call the :meth:`dispatch_request` method on it.
50
51 The arguments passed to :meth:`as_view` are forwarded to the
52 constructor of the class.
53 """
54 def view(*args, **kwargs):
775caf7 @mitsuhiko Improved cbv and added tests
authored
55 self = view.view_class(*class_args, **class_kwargs)
dcf2198 @mitsuhiko Added class based views
authored
56 return self.dispatch_request(*args, **kwargs)
775caf7 @mitsuhiko Improved cbv and added tests
authored
57 # we attach the view class to the view function for two reasons:
58 # first of all it allows us to easily figure out what class based
59 # view this thing came from, secondly it's also used for instanciating
60 # the view class so you can actually replace it with something else
61 # for testing purposes and debugging.
62 view.view_class = cls
dcf2198 @mitsuhiko Added class based views
authored
63 view.__name__ = name
64 view.__doc__ = cls.__doc__
65 view.__module__ = cls.__module__
66 view.methods = cls.methods
67 return view
68
69
70 class MethodViewType(type):
71
72 def __new__(cls, name, bases, d):
73 rv = type.__new__(cls, name, bases, d)
775caf7 @mitsuhiko Improved cbv and added tests
authored
74 if 'methods' not in d:
75 methods = set(rv.methods or [])
dcf2198 @mitsuhiko Added class based views
authored
76 for key, value in d.iteritems():
77 if key in http_method_funcs:
775caf7 @mitsuhiko Improved cbv and added tests
authored
78 methods.add(key.upper())
dcf2198 @mitsuhiko Added class based views
authored
79 # if we have no method at all in there we don't want to
80 # add a method list. (This is for instance the case for
81 # the baseclass or another subclass of a base method view
82 # that does not introduce new methods).
83 if methods:
775caf7 @mitsuhiko Improved cbv and added tests
authored
84 rv.methods = sorted(methods)
dcf2198 @mitsuhiko Added class based views
authored
85 return rv
86
87
88 class MethodView(View):
89 """Like a regular class based view but that dispatches requests to
90 particular methods. For instance if you implement a method called
91 :meth:`get` it means you will response to ``'GET'`` requests and
92 the :meth:`dispatch_request` implementation will automatically
93 forward your request to that. Also :attr:`options` is set for you
94 automatically::
95
96 class CounterAPI(MethodView):
97
98 def get(self):
99 return session.get('counter', 0)
100
101 def post(self):
102 session['counter'] = session.get('counter', 0) + 1
103 return 'OK'
104
105 app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter'))
106 """
107 __metaclass__ = MethodViewType
108
109 def dispatch_request(self, *args, **kwargs):
110 meth = getattr(self, request.method.lower(), None)
111 assert meth is not None, 'Not implemented method'
112 return meth(*args, **kwargs)
Something went wrong with that request. Please try again.