I'm trying to use django's reverse() function in definition of django form for my custom widget, but am getting an error:
ImproperlyConfigured
The included urlconf urls doesn't have any patterns in it
Here is the code:
class WorkForm(forms.Form):
# ...
category = forms.ChoiceField(
required=True,
label=_('Category'),
help_text=_('Select most appropriate category for your work.')
)
subcategory = forms.ChoiceField(
widget=DependantChoiceWidget(
default_value=_('Select category first'),
data_source_url=reverse('works-json-categories'),
# data_source_url='', -- it works this way
depends_on='category_id'
),
required=True,
label=_('SubCategory'),
help_text=_('Which subcategory suits your work best.')
)
I am pretty sure, that my 'works.urls' is configured properly, since all other pages work as expected.
Is there a reason, why I cannot use reverse()
in form definition? Does it have something to do with when this code runs? Is there a way to fix this, or the only choice here is to hardcode the URL?
Here is full error dump:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/works/add?category=1&subcategory=1
Django Version: 1.4 pre-alpha
Python Version: 2.7.1
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'social_auth',
'sorl.thumbnail',
'helpers',
'users',
'works',
'debug_toolbar']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware')
Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
89. response = middleware_method(request)
File "/usr/local/lib/python2.7/dist-packages/django/middleware/common.py" in process_request
67. if (not _is_valid_path(request.path_info, urlconf) and
File "/usr/local/lib/python2.7/dist-packages/django/middleware/common.py" in _is_valid_path
164. urlresolvers.resolve(path, urlconf)
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in resolve
416. return get_resolver(urlconf).resolve(path)
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in resolve
298. for pattern in self.url_patterns:
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in url_patterns
328. patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in urlconf_module
323. self._urlconf_module = import_module(self.urlconf_name)
File "/usr/local/lib/python2.7/dist-packages/django/utils/importlib.py" in import_module
35. __import__(name)
File "/var/www/megenius/trunk/urls.py" in <module>
27. url(r'^works/', include('works.urls')),
File "/usr/local/lib/python2.7/dist-packages/django/conf/urls/__init__.py" in include
24. urlconf_module = import_module(urlconf_module)
File "/usr/local/lib/python2.7/dist-packages/django/utils/importlib.py" in import_module
35. __import__(name)
File "/var/www/megenius/trunk/works/urls.py" in <module>
2. from works.views import *
File "/var/www/megenius/trunk/works/views.py" in <module>
9. from works.forms import WorkForm
File "/var/www/megenius/trunk/works/forms.py" in <module>
10. class WorkForm(forms.Form):
File "/var/www/megenius/trunk/works/forms.py" in WorkForm
31. data_source_url=reverse('works-json-categories'),
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse
473. (prefix, resolver.reverse(view, *args, **kwargs)))
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse
360. possibilities = self.reverse_dict.getlist(lookup_view)
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse_dict
276. self._populate()
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in _populate
242. for pattern in reversed(self.url_patterns):
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in url_patterns
332. raise ImproperlyConfigured("The included urlconf %s doesn't have any patterns in it" % self.urlconf_name)
Exception Type: ImproperlyConfigured at /works/add
Exception Value: The included urlconf urls doesn't have any patterns in it
the reverse function allows to retrieve url details from url's.py file through the name value provided there. This is the major use of reverse function in Django. The redirect variable is the variable here which will have the reversed value. So the reversed url value will be placed here.
Reverse_lazy is, as the name implies, a lazy implementation of the reverse URL resolver. Unlike the traditional reverse function, reverse_lazy won't execute until the value is needed. It is useful because it prevent Reverse Not Found exceptions when working with URLs that may not be immediately known.
Just in case you do not know why it is called reverse : It takes an input of a url name and gives the actual url, which is reverse to having a url first and then give it a name.
Use handy request. build_absolute_uri() method on request, pass it the relative url and it'll give you full one. By default, the absolute URL for request. get_full_path() is returned, but you can pass it a relative URL as the first argument to convert it to an absolute URL.
The problem might be that the form is defined before the urls have been loaded.
Django 1.4 will have a reverse_lazy
feature that would solve this problem. You could implement it in your project yourself (see changeset 16121).
Alternatively, you could set the widget in your forms __init__
method instead. Then the reverse call happens when the form is created, after the urls have loaded.
class WorkForm(forms.Form):
# ...
subcategory = forms.ChoiceField(
required=True,
label=_('SubCategory'),
help_text=_('Which subcategory suits your work best.')
)
def __init__(self, *args, **kwargs):
super(WorkForm, self).__init__(*args, **kwargs)
self.fields['subcategory'].widget=DependantChoiceWidget(
default_value=_('Select category first'),
data_source_url=reverse('works-json-categories'),
depends_on='category_id'
),
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With