Why do some includes in Django need strings, and others variable names?
Asked Answered
L

5

10

Referring to the Django Book, chapter 3:

from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'mysite.views.home', name='home'),
    # url(r'^mysite/', include('mysite.foo.urls')),
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    # url(r'^admin/', include(admin.site.urls)),
)

What determines why one thing is included as a string, and another as regular variable? Why admin.site.urls but not 'admin.site.urls'? All other includes are included as strings... I see no logical pattern here.

Lallans answered 19/4, 2015 at 22:19 Comment(0)
D
7

First of all, the first pattern ('mysite.views.home' -> a view function) is deprecated in 1.8: it led to all kinds of trouble.

As for the rest, it generally works both. 'mysite.foo.urls' is resolved to include the patterns in the module mysite.foo.urls, but from mysite.foo import urls as foo_urls; include(foo_urls) works as well. The string-based imports are mostly a historical artifact that hasn't been removed, but it is convenient and doesn't have any real drawbacks as the module is immediately imported (and thus, any ImportError is easily traceable to the url config).

admin.site.urls is different, because admin.site.urls is not a module, but site is an object and urls is an attribute. For that reason, string-based imports of admin.site.urls won't work, and you have to use the second method.

As a last note, the warning at the beginning of the Django Book, stating that it is extremely out of date, is outdated. More up-to-date resources, such as the official documentation (one of the best official documentations I know), would be preferable.

Dilation answered 19/4, 2015 at 22:42 Comment(2)
What would you do to call a view there then past dj 1.8? import the view and call it like url(r'^$', view_but_not_as_string, name='home')?Lallans
Without the include: from mysite.views import home; ...url(r'^$', home, name='home'),.... include() is only to add other patterns nested in the current pattern.Dilation
P
4

If you're passing to include() a list of url() instances, then you don't use a string (see Include() docs and Including other URLconfs docs). In your admin urls example, admin.site.urls refers to a list of url instances. See the get_urls method in the source code (which provides the list of url instances referred to by admin.site.urls).

def get_urls(self):
    ...
    # Admin-site-wide views.
    urlpatterns = [
        url(r'^$', wrap(self.index), name='index'),
        url(r'^login/$', self.login, name='login'),
        url(r'^logout/$', wrap(self.logout), name='logout'),
        url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
        url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
            name='password_change_done'),
        url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
        url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
            name='view_on_site'),
    ]
Penmanship answered 19/4, 2015 at 22:40 Comment(1)
if I could put 2 green arrows, I'd give you oneLallans
F
3

You are right this was a little confusing. They changed this in Django 1.8, so now they only support including normal variables.

Read more about this in Django 1.8 release note.

Flotation answered 19/4, 2015 at 22:40 Comment(1)
The link provided is for referencing views, not URLconfs in generalPlacard
T
3

You must to put a path with a string into the function include(). But admin.site.urls is like a string because at the begining of code, you have a import

Towandatoward answered 19/4, 2015 at 22:46 Comment(0)
P
3

From the Django 1.8 documentation, include() can take as an argument a module OR a module name

https://docs.djangoproject.com/en/1.8/ref/urls/#include

The line

from django.contrib import admin

imports the admin module. Thus, it can be used directly as an argument for include. The other include() methods have string arguments that name other URLconfs.

Placard answered 19/4, 2015 at 22:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.