Understanding Django include()

I am having trouble understanding the include() function.

I am having trouble understanding the documentation for include(). I am currently working on the tutorial. Does include basically link the individual apps urls.py to the main urls.py of the project? Is that what it does? What does the documentation mean when it says includes chops off parts of the url and uses what is remaining and sends what remains to ??? where is it sending it to? Can I have an example?

What steps have I taken to solve the problem?
I have tried asking Chat GPT.
I have tried looking on Codecademy.
I have tried looking at YouTube videos.
I have tried asking the Django community on discord.

Quoting directly from the docs:

At any point, your urlpatterns can “include” other URLconf modules.

So yes, it can include an individual app’s urls.py file into your url structure, but it’s not required that those included urls be from different apps. You could, if you so desired, create multiple URL conf modules in a single app.

Again quoting directly from the docs:

it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

The rest of the docs in that section are your example.

If you’re still wrestling with what the example is showing, please identify which part where you would like further clarification.

1 Like

per the include() example

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("polls/", include("polls.urls")),
    path("admin/", admin.site.urls),
]

under the path using the include statement it shows polls.urls.

according to the tutorial:
The idea behind include() is to make it easy to plug-and-play URLs. Since polls are in their own URLconf (polls/urls.py), they can be placed under “/polls/”, or under “/fun_polls/”, or under “/content/polls/”, or any other path root, and the app will still work.

is that because the include function works similar to the name function and as long as polls.urls is somehow in their it will work? or does it work by seeing polls and ignores the urls.py portion? How does it know what to filter?

I was certain that was the name= feature.

I’m sorry, I’m not following you at all here.

What “name” function are you talking about?
If you’re talking about the name parameter to the url function, there’s no relationship between the two. They perform two completely separate and unrelated functions.

Can you elaborate on what you mean and are referring to by your other questions?

Also, have you read the linked docs to the include function?

I was talking about the name parameter to the url function. Thank you for helping me undrstand that there is not a relation to the two. The name function I was taught is a reference point that django uses to identify which url path to use.

The instructions in the django tutorial mention that with include() I can name my url path whatever I want. “they can be placed under /polls/ fun_polls etc…”

I am wondering why I can name my url pathway whatever I want using include.

Also there are linked docs to the include function? I do not see them in your response…

wait a minute I see a hyper link for include() in my response to you. ah… that is what you mean by the link. Yes I read it but I do not understand. Is this supposed to be a link between url config paths for a project?

Can someone explain the include function capabilites in simple terms?

That’s not an accurate statement.

The name parameter (it’s not a function) is a name for a url, that’s all.

That’s not what those docs are saying.

In the tutorial, you’re creating urls for the polls app. These urls are defined in step 3, in the section:

from django.urls import path
from . import views

urlpatterns = [
    # ex: /polls/
    path("", views.index, name="index"),
    # ex: /polls/5/
    path("<int:question_id>/", views.detail, name="detail"),
    # ex: /polls/5/results/
    path("<int:question_id>/results/", views.results, name="results"),
    # ex: /polls/5/vote/
    path("<int:question_id>/vote/", views.vote, name="vote"),
]

Notice that you’re only specifying the part of the url after polls - because the name polls is defined in your root urls.py file like this:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("polls/", include("polls.urls")),
          ^^^^^
    path("admin/", admin.site.urls),
]

What the docs are saying is that the polls above doesn’t need to be polls. You can change that name to anything you want it to be (as long as it’s a valid url), and your application would still work.

In fact, you could have:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("polls/", include("polls.urls")),
    path("my-polls/", include("polls.urls")),
    path("admin/", admin.site.urls),
]

and you can then access views.detail for question_id 1 as either /polls/1/ or /my-polls/1/.

so in these lines of code we are defining the url after the polls/ pathway.

from django.urls import path
from . import views

urlpatterns = [
    # ex: /polls/
    path("", views.index, name="index"),
    # ex: /polls/5/
    path("<int:question_id>/", views.detail, name="detail"),
    # ex: /polls/5/results/
    path("<int:question_id>/results/", views.results, name="results"),
    # ex: /polls/5/vote/
    path("<int:question_id>/vote/", views.vote, name="vote"),
]

in these lines of code in my root urls.py file which I am led to believe is the projects urls.py file…
you are saying I do not have to have it say polls/ it can be my-polls/ or andrew-polls/ or whatever so long as its a valid url. by that you must mean whatever comes after polls/ my-polls/ or andrew-polls/ whatever comes after that slash needs to also be the correct url.

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("polls/", include("polls.urls")),
          ^^^^^
    path("admin/", admin.site.urls),
]```

I have two questions, 
I want to know is what is the function of include(), why do I need include(polls.urls) is that telling django to go to the polls.urls file and grab all of the pathways? I think that is what you are saying. 

Question two you mentioned that the url patterns that are NOT in the root directory but in the polls app urls... the ones listed below this line

from django.urls import path
from . import views

urlpatterns = [
# ex: /polls/
path(“”, views.index, name=“index”),
# ex: /polls/5/
path(“int:question_id/”, views.detail, name=“detail”),
# ex: /polls/5/results/
path(“int:question_id/results/”, views.results, name=“results”),
# ex: /polls/5/vote/
path(“int:question_id/vote/”, views.vote, name=“vote”),
]

(continued) you said we were specifying what comes after the polls/. or my-polls/ or andrew-polls/

how exactly are we specifying what comes after polls/?

What I mean is that the characters being used in the url must be valid characters to be used in a url. (Must not be a space or any of a number of punctuation or special characters such as the question mark.)

Also to clarify, your “root urls” is the urls.py file defined in your settings.py file, regardless of the directory in which it resides. It identifies the first urls.py file to be processed by Django when it’s setting up the url structure.

reading the documentation links again…

In Django, include() is a function that allows you to insert the URLconf of another application into the current URLconf. This makes it easy to plug-and-play different Django applications. Suppose you have an application called polls with its own URL configurations. Rather than defining all the URL patterns in your main project’s urls.py , you can include the URLs from the polls app. Here’s how to do it:

from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    ...
]

In this example, any URLs starting with polls/ will be forwarded to the polls application.

So basically include works like an import statement in python. It allows me to include all of the url paths of a urls.py file in another urls.py file in one line of code instead of importing everything. Is that correct?

Essentially correct, however it is not limited to including a file by the name of urls.py.

Specifically, from the docs at URL dispatcher | Django documentation | Django

At any point, your urlpatterns can “include” other URLconf modules.

and

Another possibility is to include additional URL patterns by using a list of path() instances.

See both examples in that section of the docs.

So while you might think of it as being similar to the import statement, the analogy only goes so far and you shouldn’t let your thinking be limited by it in that direction.

Finally:

I would not describe this as being fully correct.

The URLs starting with polls/ will be matched to the urlpatterns as defined in the polls.urls module. Whether or not the requests are actually handled by the polls app is an entirely different question and depends solely upon the contents of those urlpatterns.

1 Like

I have also observed that when I am seeing a grayed out import statement in my import statement lines that one way to possibly fix it is to use the include() statement in my project urls.py.

path(‘url_path_name/’, include(‘appname.urls’)),

Per HydroMike in addition to linking url patterns we can also include files. Files can have an entire app in them with their own urls.py. Instead of typing out all of the url patterns in that respective file given to us include() will search that file for the urls.py and than “include” them into the search list for the projects urls.py file.

I don’t know who “HydroMike” is or what you’re referencing, but:

It’s not clear what you’re trying to describe here or how this is different from the normal include statement.

I am trying to understand the include() app. I am leaving notes so that next time I have this issue I can follow my bookmarked questions and look them up.

Thank you for all of your help answering my questions so far Ken.

It is worth noting that in the path() method that when used with include will prepend the path name to the all the included urls.

like running a for each loop on each of the directorys that are passed in.

example: path(‘andrew/’, include(‘polls.urls’)

every path in polls.urls will be prepended with /andrew path.

You’re looking at this from the wrong direction. There’s no “prepending” being performed here.

Quoting directly from the docs at URL dispatcher | Django documentation | Django

Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

A request comes in from the browser. The browser may be submitting a request for a url like /a/b/c/.

If your path statement is path('a/', include(b_app.urls)), then Django is going to match the submitted /a/b/c/ to this path. It’s then going to drop the a/ from the request path and continue processing by searching the urlpatterns in b_app.urls with b/c/.

okay so its coming in from the users http request into django and is getting filtered as it goes deeper into the website losing parts of the url when its already taken that pathway as it goes…

Note to self include does NOT link urls together.

when the request comes in from the browser it chops off the matching part and then tells django to look in the thing it redirects to.

would it be fair to say that include acts like a routing switch that chops off the parts of the path as it uses it?

1 Like

Yea, I’d say that just about covers it.