Skip to content

Instantly share code, notes, and snippets.

@edelvalle
Last active October 10, 2015 14:45
Show Gist options
  • Save edelvalle/67796c23782ae19f61ee to your computer and use it in GitHub Desktop.
Save edelvalle/67796c23782ae19f61ee to your computer and use it in GitHub Desktop.
context views....
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