PageRenderTime 40ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/view_shortcuts/decorators.py

https://bitbucket.org/neithere/django-view-shortcuts/
Python | 107 lines | 80 code | 12 blank | 15 comment | 6 complexity | 380b779ba9eedcd0041666001a562d98 MD5 | raw file
Possible License(s): LGPL-3.0
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (c) 2008 Alexander Solovyov (parts)
  4. # Copyright (c) 2008--2009 Andy Mikhailenko and contributors
  5. #
  6. # This file is part of Django View Shortcuts.
  7. #
  8. # Django View Shortcuts is free software under terms of the GNU Lesser
  9. # General Public License version 3 (LGPLv3) as published by the Free
  10. # Software Foundation. See the file README for copying conditions.
  11. #
  12. from django.http import HttpRequest
  13. from django.template import RequestContext
  14. from django.shortcuts import render_to_response
  15. def render_to(template=None):
  16. """
  17. Decorator for Django views that sends returned dict to render_to_response
  18. function with given template and RequestContext as context instance.
  19. If view doesn't return dict then decorator simply returns output.
  20. Additionally view can return two-tuple, which must contain dict as first
  21. element and string with template name as second. This string will
  22. override template name, given as parameter
  23. Parameters:
  24. :param template: template name to use
  25. Usage::
  26. >>> @render_to('foo.html')
  27. ... def view_foo(request):
  28. ... return {'foo': 'bar'}
  29. ...
  30. Template name can be omitted. The following code will render the output
  31. to template "foo_detail.html" -- its name is equal to the view function name::
  32. >>> @render_to()
  33. ... def foo_detail(request, pk):
  34. ... obj = Foo.objects.get(pk=pk)
  35. ... return {'object': obj}
  36. Class views are supported too::
  37. >>> @render_to()
  38. ... class ViewFoo(object):
  39. ... def __init__(self, foo):
  40. ... self.foo = foo
  41. ... def __call__(self, request, *args, **kwargs):
  42. ... qs = Foo.objects.filter(foo=self.foo)
  43. ... return {'object_list': qs}
  44. Source: <http://piranha.org.ua/blog/2008/03/22/render-to-improved/>
  45. Improved by Andy Mikhailenko, 2008--2009:
  46. + added support for class views (i.e. with "self" in args);
  47. + template name can be omitted if it's equal to function name + 'html' extension.
  48. """
  49. def renderer(func):
  50. def wrapper(*args, **kw):
  51. # ensure HttpRequest instance is passed properly
  52. request = None
  53. for arg in args:
  54. if isinstance(arg, HttpRequest):
  55. request = arg
  56. break
  57. if not request:
  58. raise ValueError, 'Request not found in arguments'
  59. # call the view function
  60. output = func(*args, **kw)
  61. # process results
  62. if isinstance(output, (list, tuple)):
  63. return render_to_response(output[1], output[0], RequestContext(request))
  64. elif isinstance(output, dict):
  65. # if template not specified, use view function name instead
  66. if template:
  67. tmpl = template
  68. else:
  69. if func.__name__ == '<lambda>':
  70. raise TypeError, 'Decorator render_to cannot be used ' \
  71. 'with anonymous functions if template '\
  72. 'name is not provided.'
  73. tmpl = '%s.html' % func.__name__
  74. return render_to_response(tmpl, output, RequestContext(request))
  75. return output
  76. # preserve custom attributes of the view function
  77. wrapper.__dict__ = dict(func.__dict__)
  78. return wrapper
  79. return renderer
  80. def cached_property(f):
  81. """A property which value is computed only once and then stored with
  82. the instance for quick repeated retrieval.
  83. """
  84. def _closure(self):
  85. cache_key = '_cache__%s' % f.__name__
  86. value = getattr(self, cache_key, None)
  87. if value == None:
  88. value = f(self)
  89. setattr(self, cache_key, value)
  90. return value
  91. return property(_closure)