use mro to collect methods
ignore methods attr unless explicitly set add changelog
This commit is contained in:
parent
0d9d3d8f92
commit
648344d4e8
2 changed files with 24 additions and 22 deletions
2
CHANGES
2
CHANGES
|
|
@ -24,8 +24,10 @@ Major release, unreleased
|
||||||
- Add support for ``provide_automatic_options`` in ``add_url_rule`` to disable
|
- Add support for ``provide_automatic_options`` in ``add_url_rule`` to disable
|
||||||
adding OPTIONS method when the ``view_func`` argument is not a class.
|
adding OPTIONS method when the ``view_func`` argument is not a class.
|
||||||
(`#1489`_).
|
(`#1489`_).
|
||||||
|
- ``MethodView`` can inherit method handlers from base classes. (`#1936`_)
|
||||||
|
|
||||||
.. _#1489: https://github.com/pallets/flask/pull/1489
|
.. _#1489: https://github.com/pallets/flask/pull/1489
|
||||||
|
.. _#1936: https://github.com/pallets/flask/pull/1936
|
||||||
.. _#2017: https://github.com/pallets/flask/pull/2017
|
.. _#2017: https://github.com/pallets/flask/pull/2017
|
||||||
.. _#2223: https://github.com/pallets/flask/pull/2223
|
.. _#2223: https://github.com/pallets/flask/pull/2223
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue