mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			151 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| """
 | |
|     flask.views
 | |
|     ~~~~~~~~~~~
 | |
| 
 | |
|     This module provides class-based views inspired by the ones in Django.
 | |
| 
 | |
|     :copyright: (c) 2011 by Armin Ronacher.
 | |
|     :license: BSD, see LICENSE for more details.
 | |
| """
 | |
| from .globals import request
 | |
| 
 | |
| 
 | |
| 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 for which methods this pluggable 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 baseclass or another subclass of a base method view
 | |
|             # that does not introduce new methods).
 | |
|             if methods:
 | |
|                 rv.methods = sorted(methods)
 | |
|         return rv
 | |
| 
 | |
| 
 | |
| class MethodView(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'))
 | |
|     """
 | |
|     __metaclass__ = MethodViewType
 | |
| 
 | |
|     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)
 |