Last active
October 10, 2015 14:45
-
-
Save edelvalle/67796c23782ae19f61ee to your computer and use it in GitHub Desktop.
context views....
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from inspect import signature | |
import xoutil.logger as log | |
from xoutil.functools import lru_cache | |
from xoutil.decorator import memoized_property | |
from xoutil.objects import metaclass | |
from xoutil.iterators import first_non_null as first | |
from django import http | |
from django.core.paginator import Paginator, InvalidPage | |
from django.core.serializers.json import DjangoJSONEncoder | |
from django.template.response import TemplateResponse | |
from django.template.context import RequestContext | |
from django.utils.translation import ugettext_lazy as _ | |
def dispatch(**methods): | |
def view(request, *args, **kwargs): | |
handler = methods.get(request.method.lower()) | |
if handler: | |
handler = handler(request=request, **kwargs) | |
template_name = getattr(handler, 'template_name', None) | |
# check for json support in the view | |
if ((request.META.get('HTTP_ACCEPT') == 'application/json' or | |
not template_name) and | |
hasattr(handler, '__json__')): | |
indent = 0 if request.is_ajax() else 2 | |
return JsonResponse(handler.__json__(), indent=indent) | |
# check for template support in the view | |
if template_name: | |
return TemplateResponse( | |
request, | |
handler.template_name, | |
context=RequestContext(request, handler), | |
) | |
log.warning( | |
'Method Not Allowed (%s): %s', | |
request.method, request.path, | |
extra={ | |
'status_code': 405, | |
'request': request | |
} | |
) | |
return http.HttpResponseNotAllowed(methods.keys()) | |
return view | |
class JsonResponse(http.HttpResponse): | |
def __init__(self, data, encoder=DjangoJSONEncoder, **kwargs): | |
super(JsonResponse, self).__init__( | |
content=encoder(**kwargs).encode(data), | |
content_type='application/json' | |
) | |
class MetaView(type): | |
def __new__(cls, name, bases, attrs): | |
for name, attr in attrs.items(): | |
# translate every callable to cached callable | |
if (not name.startswith('_') and | |
not isinstance(attr, type) and | |
callable(attr)): | |
# if has just one parameter translate it to a memoized_property | |
n_parameters = len(signature(attr).parameters) | |
if n_parameters == 1: | |
attr = memoized_property(attr) | |
# if has more parameters translate it to a lru_cache method | |
elif n_parameters > 1: | |
attr = lru_cache()(attr) | |
attrs[name] = attr | |
new_class = super(MetaView, cls).__new__(cls, name, bases, attrs) | |
return new_class | |
class View(metaclass(MetaView)): | |
def __init__(self, **kwargs): | |
for key, value in kwargs.items(): | |
setattr(self, key, value) | |
def __contains__(self, member): | |
return hasattr(self, member) | |
def __getitem__(self, key): | |
return getattr(self, str(key)) | |
def query(self): | |
if self.request.method.lower() in ('post', 'put', 'delete'): | |
try: | |
json.loads(str(self.request.body)) | |
except ValueError: | |
return self.request.POST | |
if self.request.method.lower() == 'get': | |
json_data = first(self.request.GET.keys()) | |
try: | |
return json.loads(json_data or '{}') | |
except ValueError: | |
return self.request.GET | |
return {} | |
class ListView(View): | |
paginate_by = 25 | |
paginator_class = Paginator | |
page_kwarg = 'page' | |
def q(self): | |
return self.query.get('q', '') | |
def paginator(self): | |
return self.paginator_class( | |
self.queryset, | |
self.paginate_by | |
) | |
def page_number(self): | |
page_number = self.query.get(self.page_kwarg) or 1 | |
try: | |
page_number = int(page_number) | |
except ValueError: | |
if page_number == 'last': | |
page_number = self.paginator.num_pages | |
else: | |
raise http.Http404( | |
_("Page is not 'last', nor can it be converted to an int.") | |
) | |
return page_number | |
def page_obj(self): | |
try: | |
page = self.paginator.page(self.page_number) | |
except InvalidPage as e: | |
raise http.Http404( | |
_('Invalid page (%(page_number)s): %(message)s') % { | |
'page_number': self.page_number, | |
'message': str(e) | |
} | |
) | |
return page | |
def object_list(self): | |
return self.page_obj.object_list |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment