|
|
@ -102,38 +102,35 @@ class View(object): |
|
|
|
return view |
|
|
|
return view |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_methods(cls): |
|
|
|
|
|
|
|
return getattr(cls, 'methods', []) or [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MethodViewType(type): |
|
|
|
class MethodViewType(type): |
|
|
|
|
|
|
|
"""Metaclass for :class:`MethodView` that determines what methods the view |
|
|
|
|
|
|
|
defines. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(cls, name, bases, d): |
|
|
|
|
|
|
|
super(MethodViewType, cls).__init__(name, bases, d) |
|
|
|
|
|
|
|
|
|
|
|
def __new__(cls, name, bases, d): |
|
|
|
|
|
|
|
rv = type.__new__(cls, name, bases, d) |
|
|
|
|
|
|
|
if 'methods' not in d: |
|
|
|
if 'methods' not in d: |
|
|
|
methods = set(m for b in bases for m in get_methods(b)) |
|
|
|
methods = set() |
|
|
|
for key in d: |
|
|
|
|
|
|
|
if key in http_method_funcs: |
|
|
|
for key in http_method_funcs: |
|
|
|
|
|
|
|
if hasattr(cls, key): |
|
|
|
methods.add(key.upper()) |
|
|
|
methods.add(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 |
|
|
|
# If we have no method at all in there we don't want to add a |
|
|
|
# the base class or another subclass of a base method view |
|
|
|
# method list. This is for instance the case for the base class |
|
|
|
# that does not introduce new methods). |
|
|
|
# or another subclass of a base method view that does not introduce |
|
|
|
|
|
|
|
# new methods. |
|
|
|
if methods: |
|
|
|
if methods: |
|
|
|
rv.methods = sorted(methods) |
|
|
|
cls.methods = methods |
|
|
|
return rv |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MethodView(with_metaclass(MethodViewType, View)): |
|
|
|
class MethodView(with_metaclass(MethodViewType, View)): |
|
|
|
"""Like a regular class-based view but that dispatches requests to |
|
|
|
"""A class-based view that dispatches request methods to the corresponding |
|
|
|
particular methods. For instance if you implement a method called |
|
|
|
class methods. For example, if you implement a ``get`` method, it will be |
|
|
|
:meth:`get` it means it will respond to ``'GET'`` requests and |
|
|
|
used to handle ``GET`` requests. :: |
|
|
|
the :meth:`dispatch_request` implementation will automatically |
|
|
|
|
|
|
|
forward your request to that. Also :attr:`options` is set for you |
|
|
|
|
|
|
|
automatically:: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CounterAPI(MethodView): |
|
|
|
class CounterAPI(MethodView): |
|
|
|
|
|
|
|
|
|
|
|
def get(self): |
|
|
|
def get(self): |
|
|
|
return session.get('counter', 0) |
|
|
|
return session.get('counter', 0) |
|
|
|
|
|
|
|
|
|
|
@ -143,11 +140,14 @@ class MethodView(with_metaclass(MethodViewType, View)): |
|
|
|
|
|
|
|
|
|
|
|
app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter')) |
|
|
|
app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter')) |
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
def dispatch_request(self, *args, **kwargs): |
|
|
|
def dispatch_request(self, *args, **kwargs): |
|
|
|
meth = getattr(self, request.method.lower(), None) |
|
|
|
meth = getattr(self, request.method.lower(), None) |
|
|
|
|
|
|
|
|
|
|
|
# If the request method is HEAD and we don't have a handler for it |
|
|
|
# If the request method is HEAD and we don't have a handler for it |
|
|
|
# retry with GET. |
|
|
|
# retry with GET. |
|
|
|
if meth is None and request.method == 'HEAD': |
|
|
|
if meth is None and request.method == 'HEAD': |
|
|
|
meth = getattr(self, 'get', None) |
|
|
|
meth = getattr(self, 'get', None) |
|
|
|
|
|
|
|
|
|
|
|
assert meth is not None, 'Unimplemented method %r' % request.method |
|
|
|
assert meth is not None, 'Unimplemented method %r' % request.method |
|
|
|
return meth(*args, **kwargs) |
|
|
|
return meth(*args, **kwargs) |
|
|
|