Skip to content

Commit 5c9917a

Browse files
committed
Proper fix for django-cms#3393
1 parent 1e6da03 commit 5c9917a

File tree

1 file changed

+47
-38
lines changed

1 file changed

+47
-38
lines changed

menus/utils.py

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import with_statement
3+
from contextlib import contextmanager
34
import inspect
45
import warnings
56
from cms.models.titlemodels import Title
@@ -132,45 +133,12 @@ def __call__(self, lang):
132133
if view.namespace:
133134
"%s:%s" % (view.namespace, view_name)
134135
url = None
135-
# In Django < 1.7 reverse tries to convert
136-
# to string the arguments without checking
137-
# if they are classes or instances.
138-
# Here we monkeypatch the __unicode__ method
139-
# to make it works as static.
140-
# Before leaving we undo the monkeypatching
141-
if DJANGO_1_6:
142-
for idx, arg in enumerate(view.args):
143-
if inspect.isclass(arg):
144-
if hasattr(arg, '__unicode__'):
145-
@staticmethod
146-
def custom_str():
147-
return six.text_type(arg)
148-
arg._original = arg.__unicode__
149-
arg.__unicode__ = custom_str
150-
view.args[idx] = arg
151-
for key, arg in view.kwargs.items():
152-
if inspect.isclass(arg):
153-
if hasattr(arg, '__unicode__'):
154-
@staticmethod
155-
def custom_str():
156-
return six.text_type(arg)
157-
arg._original = arg.__unicode__
158-
arg.__unicode__ = custom_str
159-
view.kwargs[key] = arg
160136
with force_language(lang):
161-
try:
162-
url = reverse(view_name, args=view.args, kwargs=view.kwargs, current_app=view.app_name)
163-
except NoReverseMatch:
164-
pass
165-
if DJANGO_1_6:
166-
for idx, arg in enumerate(view.args):
167-
if inspect.isclass(arg):
168-
if hasattr(arg, '__unicode__'):
169-
arg.__unicode__ = arg._original
170-
for key, arg in view.kwargs.items():
171-
if inspect.isclass(arg):
172-
if hasattr(arg, '__unicode__'):
173-
arg.__unicode__ = arg._original
137+
with static_stringifier(view): # This is a fix for Django < 1.7
138+
try:
139+
url = reverse(view_name, args=view.args, kwargs=view.kwargs, current_app=view.app_name)
140+
except NoReverseMatch:
141+
pass
174142
if url:
175143
return url
176144
return '%s%s' % (self.get_page_path(lang), self.app_path)
@@ -187,3 +155,44 @@ def _wrapped(request, *args, **kwargs):
187155
_wrapped.__name__ = func.__name__
188156
_wrapped.__doc__ = func.__doc__
189157
return _wrapped
158+
159+
160+
@contextmanager
161+
def static_stringifier(view):
162+
"""
163+
In Django < 1.7 reverse tries to convert to string the arguments without
164+
checking whether they are classes or instances.
165+
166+
This context manager monkeypatches the __unicode__ method of each view
167+
argument if it's a class definition to render it a static method.
168+
Before leaving we undo the monkeypatching.
169+
"""
170+
if DJANGO_1_6:
171+
for idx, arg in enumerate(view.args):
172+
if inspect.isclass(arg):
173+
if hasattr(arg, '__unicode__'):
174+
@staticmethod
175+
def custom_str():
176+
return six.text_type(arg)
177+
arg._original = arg.__unicode__
178+
arg.__unicode__ = custom_str
179+
view.args[idx] = arg
180+
for key, arg in view.kwargs.items():
181+
if inspect.isclass(arg):
182+
if hasattr(arg, '__unicode__'):
183+
@staticmethod
184+
def custom_str():
185+
return six.text_type(arg)
186+
arg._original = arg.__unicode__
187+
arg.__unicode__ = custom_str
188+
view.kwargs[key] = arg
189+
yield
190+
if DJANGO_1_6:
191+
for idx, arg in enumerate(view.args):
192+
if inspect.isclass(arg):
193+
if hasattr(arg, '__unicode__'):
194+
arg.__unicode__ = arg._original
195+
for key, arg in view.kwargs.items():
196+
if inspect.isclass(arg):
197+
if hasattr(arg, '__unicode__'):
198+
arg.__unicode__ = arg._original

0 commit comments

Comments
 (0)