OpenSlides/openslides/utils/views.py

91 lines
2.9 KiB
Python
Raw Normal View History

import base64
2018-08-22 22:00:08 +02:00
from typing import Any, Dict, List, Optional
2017-08-23 20:51:06 +02:00
2017-09-26 14:19:48 +02:00
from django.contrib.staticfiles import finders
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponse
from django.views.decorators.csrf import ensure_csrf_cookie
2017-08-24 12:26:55 +02:00
from django.views.generic.base import View
from rest_framework.response import Response
from rest_framework.views import APIView as _APIView
2012-02-20 17:46:45 +01:00
2018-02-06 08:04:31 +01:00
from .arguments import arguments
2012-04-13 11:35:53 +02:00
class CSRFMixin:
"""
Adds the csrf cookie to the response.
"""
@classmethod
2017-08-24 12:26:55 +02:00
def as_view(cls, *args: Any, **kwargs: Any) -> View:
view = super().as_view(*args, **kwargs) # type: ignore
return ensure_csrf_cookie(view)
class APIView(_APIView):
"""
The Django Rest framework APIView with improvements for OpenSlides.
"""
2018-08-22 22:00:08 +02:00
http_method_names: List[str] = []
"""
The allowed actions have to be explicitly defined.
Django allowes the following:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
"""
2017-08-24 12:26:55 +02:00
def get_context_data(self, **context: Any) -> Dict[str, Any]:
"""
Returns the context for the response.
"""
return context
2017-08-24 12:26:55 +02:00
def method_call(self, request: Any, *args: Any, **kwargs: Any) -> Any:
"""
Http method that returns the response object with the context data.
"""
return Response(self.get_context_data())
# Add the http-methods and delete the method "method_call"
get = post = put = patch = delete = head = options = trace = method_call
del method_call
2017-09-26 14:19:48 +02:00
class TemplateView(View):
2017-09-26 14:19:48 +02:00
"""
A view to serve a single cached template file. Subclasses have to provide 'template_name'.
The state dict is used to cache the template. The state variable is static, but the object ID
is not allowed to change. So the State has to be saved in this dict. Search for 'Borg design
pattern' for more information.
2017-09-26 14:19:48 +02:00
"""
2018-08-22 22:00:08 +02:00
template_name: Optional[str] = None
state: Dict[str, str] = {}
2017-09-26 14:19:48 +02:00
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
if self.template_name is None:
2018-01-23 08:49:13 +01:00
raise ImproperlyConfigured("'template_name' is not provided.")
2017-09-26 14:19:48 +02:00
2018-02-06 08:04:31 +01:00
no_caching = arguments.get('no_template_caching', False)
if self.template_name not in self.state or no_caching:
self.state[self.template_name] = self.load_template()
def load_template(self) -> str:
with open(finders.find(self.template_name)) as template:
return template.read()
2017-09-26 14:19:48 +02:00
def get(self, *args: Any, **kwargs: Any) -> HttpResponse:
2018-08-22 22:00:08 +02:00
return HttpResponse(self.state[self.template_name]) # type: ignore
class BinaryTemplateView(TemplateView):
"""
Loads the specified binary template and encode it with base64.
"""
2018-02-24 16:38:17 +01:00
def load_template(self) -> str:
with open(finders.find(self.template_name), 'rb') as template:
2018-02-24 16:38:17 +01:00
return base64.b64encode(template.read()).decode()