Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
186eb21d
Kaydet (Commit)
186eb21d
authored
Agu 11, 2015
tarafından
fabrizio ettore messina
Kaydeden (comit)
Tim Graham
Eyl 18, 2015
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #25269 -- Allowed method_decorator() to accept a list/tuple of decorators.
üst
d8d85337
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
126 additions
and
18 deletions
+126
-18
decorators.py
django/utils/decorators.py
+18
-4
utils.txt
docs/ref/utils.txt
+11
-3
1.9.txt
docs/releases/1.9.txt
+3
-2
intro.txt
docs/topics/class-based-views/intro.txt
+21
-1
tests.py
tests/decorators/tests.py
+73
-8
No files found.
django/utils/decorators.py
Dosyayı görüntüle @
186eb21d
...
...
@@ -45,8 +45,20 @@ def method_decorator(decorator, name=''):
else
:
func
=
obj
def
decorate
(
function
):
"""
Apply a list/tuple of decorators if decorator is one. Decorator
functions are applied so that the call order is the same as the
order in which they appear in the iterable.
"""
if
hasattr
(
decorator
,
'__iter__'
):
for
dec
in
decorator
[::
-
1
]:
function
=
dec
(
function
)
return
function
return
decorator
(
function
)
def
_wrapper
(
self
,
*
args
,
**
kwargs
):
@decorat
or
@decorat
e
def
bound_func
(
*
args2
,
**
kwargs2
):
return
func
.
__get__
(
self
,
type
(
self
))(
*
args2
,
**
kwargs2
)
# bound_func has the signature that 'decorator' expects i.e. no
...
...
@@ -57,7 +69,7 @@ def method_decorator(decorator, name=''):
# want to copy those. We don't have access to bound_func in this scope,
# but we can cheat by using it on a dummy function.
@decorat
or
@decorat
e
def
dummy
(
*
args
,
**
kwargs
):
pass
update_wrapper
(
_wrapper
,
dummy
)
...
...
@@ -69,8 +81,10 @@ def method_decorator(decorator, name=''):
return
obj
return
_wrapper
update_wrapper
(
_dec
,
decorator
,
assigned
=
available_attrs
(
decorator
))
# Don't worry about making _dec look similar to a list/tuple as it's rather
# meaningless.
if
not
hasattr
(
decorator
,
'__iter__'
):
update_wrapper
(
_dec
,
decorator
,
assigned
=
available_attrs
(
decorator
))
# Change the name to aid debugging.
if
hasattr
(
decorator
,
'__name__'
):
_dec
.
__name__
=
'method_decorator(
%
s)'
%
decorator
.
__name__
...
...
docs/ref/utils.txt
Dosyayı görüntüle @
186eb21d
...
...
@@ -155,12 +155,20 @@ The functions defined in this module share the following properties:
Converts a function decorator into a method decorator. It can be used to
decorate methods or classes; in the latter case, ``name`` is the name
of the method to be decorated and is required. See :ref:`decorating
class-based views<decorating-class-based-views>` for example usage.
of the method to be decorated and is required.
``decorator`` may also be a a list or tuple of functions. They are wrapped
in reverse order so that the call order is the order in which the functions
appear in the list/tuple.
See :ref:`decorating class based views <decorating-class-based-views>` for
example usage.
.. versionchanged:: 1.9
The ability to decorate classes and the ``name`` parameter were added.
The ability to decorate classes, the ``name`` parameter, and the ability
for ``decorator`` to accept a list/tuple of decorator functions were
added.
.. function:: decorator_from_middleware(middleware_class)
...
...
docs/releases/1.9.txt
Dosyayı görüntüle @
186eb21d
...
...
@@ -378,8 +378,9 @@ Generic Views
* Class-based views generated using ``as_view()`` now have ``view_class``
and ``view_initkwargs`` attributes.
* :func:`~django.utils.decorators.method_decorator` can now be used to
:ref:`decorate classes instead of methods <decorating-class-based-views>`.
* :func:`~django.utils.decorators.method_decorator` can now be used with a list
or tuple of decorators. It can also be used to :ref:`decorate classes instead
of methods <decorating-class-based-views>`.
Internationalization
^^^^^^^^^^^^^^^^^^^^
...
...
docs/topics/class-based-views/intro.txt
Dosyayı görüntüle @
186eb21d
...
...
@@ -286,9 +286,29 @@ of the method to be decorated as the keyword argument ``name``::
class ProtectedView(TemplateView):
template_name = 'secret.html'
If you have a set of common decorators used in several places, you can define
a list or tuple of decorators and use this instead of invoking
``method_decorator()`` multiple times. These two classes are equivalent::
decorators = [never_cache, login_required]
@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
The decorators will process a request in the order they are passed to the
decorator. In the example, ``never_cache()`` will process the request before
``login_required()``.
.. versionchanged:: 1.9
The ability to use ``method_decorator()`` on a class was added.
The ability to use ``method_decorator()`` on a class and the ability for
it to accept a list or tuple of decorators were added.
In this example, every instance of ``ProtectedView`` will have login protection.
...
...
tests/decorators/tests.py
Dosyayı görüntüle @
186eb21d
...
...
@@ -212,22 +212,52 @@ class MethodDecoratorTests(SimpleTestCase):
self
.
assertEqual
(
getattr
(
func
,
'myattr'
,
False
),
True
)
self
.
assertEqual
(
getattr
(
func
,
'myattr2'
,
False
),
True
)
#
Now check method_decorator
class
Test
(
object
):
#
Decorate using method_decorator() on the method.
class
Test
Plain
(
object
):
@myattr_dec_m
@myattr2_dec_m
def
method
(
self
):
"A method"
pass
self
.
assertEqual
(
getattr
(
Test
()
.
method
,
'myattr'
,
False
),
True
)
self
.
assertEqual
(
getattr
(
Test
()
.
method
,
'myattr2'
,
False
),
True
)
# Decorate using method_decorator() on both the class and the method.
# The decorators applied to the methods are applied before the ones
# applied to the class.
@method_decorator
(
myattr_dec_m
,
"method"
)
class
TestMethodAndClass
(
object
):
@method_decorator
(
myattr2_dec_m
)
def
method
(
self
):
"A method"
pass
self
.
assertEqual
(
getattr
(
Test
.
method
,
'myattr'
,
False
),
True
)
self
.
assertEqual
(
getattr
(
Test
.
method
,
'myattr2'
,
False
),
True
)
# Decorate using an iterable of decorators.
decorators
=
(
myattr_dec_m
,
myattr2_dec_m
)
self
.
assertEqual
(
Test
.
method
.
__doc__
,
'A method'
)
self
.
assertEqual
(
Test
.
method
.
__name__
,
'method'
)
@method_decorator
(
decorators
,
"method"
)
class
TestIterable
(
object
):
def
method
(
self
):
"A method"
pass
for
Test
in
(
TestPlain
,
TestMethodAndClass
,
TestIterable
):
self
.
assertEqual
(
getattr
(
Test
()
.
method
,
'myattr'
,
False
),
True
)
self
.
assertEqual
(
getattr
(
Test
()
.
method
,
'myattr2'
,
False
),
True
)
self
.
assertEqual
(
getattr
(
Test
.
method
,
'myattr'
,
False
),
True
)
self
.
assertEqual
(
getattr
(
Test
.
method
,
'myattr2'
,
False
),
True
)
self
.
assertEqual
(
Test
.
method
.
__doc__
,
'A method'
)
self
.
assertEqual
(
Test
.
method
.
__name__
,
'method'
)
def
test_bad_iterable
(
self
):
decorators
=
{
myattr_dec_m
,
myattr2_dec_m
}
# The rest of the exception message differs between Python 2 and 3.
with
self
.
assertRaisesMessage
(
TypeError
,
"'set' object"
):
@method_decorator
(
decorators
,
"method"
)
class
TestIterable
(
object
):
def
method
(
self
):
"A method"
pass
# Test for argumented decorator
def
test_argumented
(
self
):
...
...
@@ -291,6 +321,41 @@ class MethodDecoratorTests(SimpleTestCase):
self
.
assertTrue
(
Test
()
.
method
())
def
test_tuple_of_decorators
(
self
):
"""
@method_decorator can accept a tuple of decorators.
"""
def
add_question_mark
(
func
):
def
_wrapper
(
*
args
,
**
kwargs
):
return
func
(
*
args
,
**
kwargs
)
+
"?"
return
_wrapper
def
add_exclamation_mark
(
func
):
def
_wrapper
(
*
args
,
**
kwargs
):
return
func
(
*
args
,
**
kwargs
)
+
"!"
return
_wrapper
# The order should be consistent with the usual order in which
# decorators are applied, e.g.
# @add_exclamation_mark
# @add_question_mark
# def func():
# ...
decorators
=
(
add_exclamation_mark
,
add_question_mark
)
@method_decorator
(
decorators
,
name
=
"method"
)
class
TestFirst
(
object
):
def
method
(
self
):
return
"hello world"
class
TestSecond
(
object
):
@method_decorator
(
decorators
)
def
method
(
self
):
return
"hello world"
self
.
assertEqual
(
TestFirst
()
.
method
(),
"hello world?!"
)
self
.
assertEqual
(
TestSecond
()
.
method
(),
"hello world?!"
)
def
test_invalid_non_callable_attribute_decoration
(
self
):
"""
@method_decorator on a non-callable attribute raises an error.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment