Add support for relative imports in django.conf.urls.include()?

189 views
Skip to first unread message

Tim Graham

unread,
Feb 29, 2016, 8:17:39 AM2/29/16
to Django developers (Contributions to Django itself)

For example, within myproject.urls:


urlpatterns = ( url(r'', include('.myapp.urls')), )


.. becomes equivalent to::

    urlpatterns = (
        url(r'', include('myproject.myapp.urls')),
    )
 
Whilst a contrived example, this can make heavy-nested apps look far, far cleaner. For example, within myproject.foo.foo_bar.foo_bar_baz.urls, one only needs to include .foo_bar_baz_qux.urls to get to the "next" level, rather than the significantly more unwieldy myproject.foo.foo_bar.foo_bar_baz.foo.bar_baz_qux.urls.

----

What do you think of this proposal from https://code.djangoproject.com/ticket/26288? I don't know if "nested apps" are very common and/or something that should be promoted with a change like this.

Aymeric Augustin

unread,
Feb 29, 2016, 8:20:23 AM2/29/16
to django-d...@googlegroups.com
I’m +0 on this change, for consistency with Python’s import statement.

-- 
Aymeric.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/5a92150c-4969-4432-b47b-0a02ce889312%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Marten Kenbeek

unread,
Feb 29, 2016, 8:52:55 AM2/29/16
to Django developers (Contributions to Django itself)
The current approach can lead to surprising errors if include() is called by a helper function, rather than directly called in your urlconf. The relative import would be resolved in relation to the module where the helper function is defined. I'm not sure how much of an actual problem that is in practice, but it's something to keep in mind. 

Josh Smeaton

unread,
Feb 29, 2016, 5:34:18 PM2/29/16
to Django developers (Contributions to Django itself)
Going off topic a little bit but.. have we considered deprecating string based includes in favour of actually importing the urls module?

from . import myapp
urlpatterns
= (
 url
(r'^myapp/', include(myapp.urls.urlpatterns)),
)

Then users can relatively import their nested app patterns as they will.

Even if we didn't deprecate string based imports I'm wary of increasing their utility.

Marten Kenbeek

unread,
Feb 29, 2016, 6:10:42 PM2/29/16
to Django developers (Contributions to Django itself)
Hi Josh,


On Monday, February 29, 2016 at 11:34:18 PM UTC+1, Josh Smeaton wrote:
Going off topic a little bit but.. have we considered deprecating string based includes in favour of actually importing the urls module?

I've tried to remove them as a proof of concept, but that's not possible without some small regressions and test failures. Currently, urlpatterns are loaded lazily, and when they're loaded, the complete content of the namespace is loaded. This allows you to recursively include the same URLconf, but only when you include the URLconf using a namespace (otherwise the code attempts to load every level, and you'll run into a maximum recursion depth error). This is done in the test suite as well[1], hence the test failures.

I haven't been able to think of any practical use-cases, but you never know what's out there. The best I can come up with is to include an arbitrary number of positional arguments, but I think that's better handled by capturing them as one argument and splitting in the view, or even better, by using GET parameters.

I don't think string based imports are much of a problem in the case of include. The import is done immediately, and the errors are clear. Deprecating does have the benefit of increased consistency and less magic, but otherwise I don't see any practical benefits.

Then users can relatively import their nested app patterns as they will.
 
Even if we didn't deprecate string based imports I'm wary of increasing their utility.

This just made me realize that the whole problem can already be fixed from the user's perspective by importing the module instead of using string based imports. That is possible and has been possible for a long time. In that light, I don't see the benefit of supporting relative string based imports with some confusing edge-cases. 

lamby

unread,
Mar 3, 2016, 3:40:14 AM3/3/16
to Django developers (Contributions to Django itself)
This just made me realize that the whole problem can already be fixed from the user's perspective by importing the module instead of using string based imports


Not entirely convinced. Firstly it's extra stuff you have to explicitly import which seems a style regression from the "oh just use these included urls" that you get with the string-based import.

Secondly, whilst it might look fine when you are doing it once, for example:

from django.conf.urls import url, include

from . import views
from .foo import urls

urlpatterns = (
    url(r'', include(urls, namespace='foo')),

    url(r'^$', views.landing, name='landing'),
)

.. but the import dance get a bit nasty when you have multiple ones - you have to alias each import:

from django.conf.urls import url, include

from . import views
from .foo_app import urls as foo_urls
from .bar_app import urls as bar_urls
# etc.

urlpatterns = (
    url(r'', include(foo_urls, namespace='foo')),
    url(r'', include(bar_urls, namespace='bar')),

    url(r'^$', views.landing, name='landing'),
)

This isn't an readabiliy improvement over using the string urls IMHO.

Now, if only we could do the following:

from . import views, foo_app, bar_app

urlpatterns = (
    url(r'', include(foo_app.urls), namespace='foo')),
    url(r'', include(bar_app.urls), namespace='bar')),

    url(r'^$', views.landing, name='landing'),
)


/lamby

Tim Graham

unread,
Mar 7, 2016, 10:11:52 AM3/7/16
to Django developers (Contributions to Django itself)
How common are "heavily nested apps"? Is there anyone else reading this who would find this useful?
Reply all
Reply to author
Forward
0 new messages