mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-28 12:30:00 +00:00
bbf6d9b026
Bugfix for feeds - removed categories related and up - load new books now working - category random now working login page is free of non accessible elements boolean custom column is vivible in UI books with only with certain languages can be shown book shelfs can be deleted from UI Anonymous user view is more resticted Added browse of series in sidebar Dependencys in vendor folder are updated to newer versions (licencs files are now present) Bugfix editing Authors names Made upload on windows working
150 lines
5.5 KiB
Python
150 lines
5.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
flask.views
|
|
~~~~~~~~~~~
|
|
|
|
This module provides class-based views inspired by the ones in Django.
|
|
|
|
:copyright: (c) 2015 by Armin Ronacher.
|
|
:license: BSD, see LICENSE for more details.
|
|
"""
|
|
from .globals import request
|
|
from ._compat import with_metaclass
|
|
|
|
|
|
http_method_funcs = frozenset(['get', 'post', 'head', 'options',
|
|
'delete', 'put', 'trace', 'patch'])
|
|
|
|
|
|
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'))
|
|
|
|
When you want to decorate a pluggable view you will have to either do that
|
|
when the view function is created (by wrapping the return value of
|
|
:meth:`as_view`) or you can use the :attr:`decorators` attribute::
|
|
|
|
class SecretView(View):
|
|
methods = ['GET']
|
|
decorators = [superuser_required]
|
|
|
|
def dispatch_request(self):
|
|
...
|
|
|
|
The decorators stored in the decorators list are applied one after another
|
|
when the view function is created. Note that you can *not* use the class
|
|
based decorators since those would decorate the view class and not the
|
|
generated view function!
|
|
"""
|
|
|
|
#: A list of methods this view can handle.
|
|
methods = None
|
|
|
|
#: The canonical way to decorate class-based views is to decorate the
|
|
#: return value of as_view(). However since this moves parts of the
|
|
#: logic from the class declaration to the place where it's hooked
|
|
#: into the routing system.
|
|
#:
|
|
#: You can place one or more decorators in this list and whenever the
|
|
#: view function is created the result is automatically decorated.
|
|
#:
|
|
#: .. versionadded:: 0.8
|
|
decorators = ()
|
|
|
|
def dispatch_request(self):
|
|
"""Subclasses have to override this method to implement the
|
|
actual view function code. This method is called with all
|
|
the arguments from the URL rule.
|
|
"""
|
|
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. Internally this generates a function on the
|
|
fly which will instantiate 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 = view.view_class(*class_args, **class_kwargs)
|
|
return self.dispatch_request(*args, **kwargs)
|
|
|
|
if cls.decorators:
|
|
view.__name__ = name
|
|
view.__module__ = cls.__module__
|
|
for decorator in cls.decorators:
|
|
view = decorator(view)
|
|
|
|
# We attach the view class to the view function for two reasons:
|
|
# first of all it allows us to easily figure out what class-based
|
|
# view this thing came from, secondly it's also used for instantiating
|
|
# the view class so you can actually replace it with something else
|
|
# for testing purposes and debugging.
|
|
view.view_class = cls
|
|
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 'methods' not in d:
|
|
methods = set(rv.methods or [])
|
|
for key in d:
|
|
if key in http_method_funcs:
|
|
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
|
|
# the base class or another subclass of a base method view
|
|
# that does not introduce new methods).
|
|
if methods:
|
|
rv.methods = sorted(methods)
|
|
return rv
|
|
|
|
|
|
class MethodView(with_metaclass(MethodViewType, 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'))
|
|
"""
|
|
def dispatch_request(self, *args, **kwargs):
|
|
meth = getattr(self, request.method.lower(), None)
|
|
# If the request method is HEAD and we don't have a handler for it
|
|
# retry with GET.
|
|
if meth is None and request.method == 'HEAD':
|
|
meth = getattr(self, 'get', None)
|
|
assert meth is not None, 'Unimplemented method %r' % request.method
|
|
return meth(*args, **kwargs)
|