Namespacing and using name=

So I’ve namespaces my templates in ISO22301/templates/ISO22301 and using the urls in views and templates works fine. However, if I try to use the name, I get Template Does Not exist errors.

Fore example, with the layout.html template:

urls.py

app_name="ISO22301"
urlpatterns = [
    #path("landing/", views.landing, name="landing"),
    path("layout/", views.layout, name="layout"),
    path("leadership/", views.leadership, name="leadership"),

views.py

def layout(request):

    return render(request, "layout",) # TemplateDoesNotExist - I expected this to work but my namespace may be the issue

    return render(request, "ISO22301/layout.html",) # works

In addition, if I try to use the name in {% extends %} it doesn’t work either

{% extends  "ISO22301/layout.html" %} # works

{% extends  "layout" %} # TemplateDoesNotExist
{% extends  url "layout" %} # Error is 'extends' takes one argument
{% extends  url "ISO:22301:layout" %} # Error is 'extends' takes one argument

Is there a way to use namespaced name= values in extends? and render()?

The name spaces in URLs apply to names of URLs. This has nothing to do with file and directory names for templates, at all. There is no relationship between the two.

Template file organization and the “namespacing” that is used for them is covered in the Django tutorial, part 3. (There’s a note box for that specific topic on that page, about half-way down.)

The extends tag extends template files, it does not extend urls.

Templates, template files, and rendering doesn’t have anything to do with URLs.

The purpose of a named URL is to give you the ability “internally” - within your code - to reference a URL without “knowing” what that URL is going to be. It only applies to URLs, nothing else.

I tried to follow the tutorial page 3 when setting up my app, using app name/template/app name as the directory structure and placed my templates there, per the tutorial, i.e.

ISO22301/templates/ISO22301

Then add app_name= to the urls.py file in the app like it says in the section Namespacing URL names: app_name=“ISO22301”.

I thought that would allow me to use the path name= instead of hardcoding the URL in the return render () in my views.py functions. Clearly I am missing something.

I’ll just hardcode paths in ‘extends’

The extends tag is extending a file, not a url.

The app and path name attributes are referencing urls, not files. They’re two different things.

Files are not urls. Urls are not files.

1 Like

AH, I see what you mean. Extend tells where to find the file to use the block in; correct? However, in the rest of the HTML,

{% url 'polls:vote' question.id %}

says to return question.id to the function vote in views.py; and '‘url’ tells it where in urls.py to find the return path and associated view

However, in render() it is a also url, correct?

As I understand it, in urls.py

app_name="ISO22301"
urlpatterns = [
    path("layout/", views.layout, name="layout"),

means, when the url ISO22301/layout is entered in the browser; go to the function layout in views.py; do whatever that code does, and the return the template specified in render() with whatever context is provided. As I understand it, the name I defined in path, layout, would return ISO22301/layout so I would not have to hardcode that.

So I’m not sure why the using “layout” in render(request,“layout”) yields TemplateDoesNotExist

Are you referring to the {% url ... %} tag? If so, yes. The url tag references url names, not files.

See the docs for render. That second parameter is the template to be rendered. It has nothing to do with a url. And, that error has nothing to do with any contents of the template - it can’t find a file named “layout” to even try rendering it.

Thanks.

WRT render, I was referring to the url in the browser that says go to this page.

I was under the impression using the value in path( name=“”) provides the same path to the file as hardcoding the file location, and adding app_name=“ISO22301” prefix the paths with ISO22301/
so using “layout” in render for the template_name is the same as using “ISO22301/layout”; which is not the case based on the error.

The two are not related. At all.

To “Think Django”, do not think of a url in the browser as “going to a page.” That’s far too limiting a perspective.

A url in the browser says “call the view referenced by this url”. In the common case, that view is going to return a page. However, it could also return a file, or anything else within the context of an HttpResponse.

In that common case where a page is returned, how that page is generated is entirely and solely dependent upon that view. It’s got nothing (directly) to do with the url that caused that view to be executed. Any templates that may be rendered are not associated with the url.

You want to separate whatever “mental connection” you have between the two. (URLs and files)

1 Like

Yea, getting used to thinking Django is part of the challenge; especially as my thought patterns re process oriented so I try to reason out a flow for what is happening. I appreciate your help.

So I guess the value in name= doesn’t work in render() for the template_name?

That is correct. They are two separate and unrelated attributes.

Ok. So is name just used in HTML to avoid hardcoding in the full path?

Not “just”. It provides independance of the url from the reference to the url.

In other words, if you have an app that needs to refer to other urls in that app (or in other apps), it doesn’t matter where that app’s urls end up in the url path tree.

Consider the case of the Django admin as an example. (I’m using this as an example for discussion purposes. This example holds true regardless of the app being discussed.)

The configuration shown in the tutorial is:

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

This means that all admin urls are going to exist under the top-level directory as /admin/.

Now, this means that for me to edit the User object with pk = 1, I would issue a request for /admin/auth/user/1/change/. And, other pages with the admin - and in other apps, can link to that url.

However, what happens if I want to change my urls to this?

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

Anything coded to refer to /admin/auth/user/1/change/ is not going to work. The url for editing the User with pk = 1 would now be /a/auth/user/1/change/.

However, by using the name reference in things like the {% url ... %} tag - it doesn’t matter. The name doesn’t change. Django calculates what the url is going to be from the name definition and it’s location within the URLconf. You have configured the url structure as you see fit, and the references to that url by name “just works”.

And that is the real power and significance of the name attribute in a url definition.

Thanks for the explanation. I meant just in the sense it only works in tags in HTML code from what I can gather; since when I tried to use names in views.py it didn’t work.

Is there a way to do the same in python code; or than a find a replace in views after updating urls.py?

It works, when you’re using it to resolve URLs. (e.g., the reverse function.)

If you’ve got an example where you’re trying to use a name with a url and it’s not working, we can help you there.

1 Like

I think reverse() was what I was looking for as I wanted the same capability to not have to hardcode values into template_name that the HTML code has with tags by using the name assigned to it in urls.py.

If I understand correctly, for

urlpatterns = [
    path("leadership/", views.leadership, name="leadership"),
]

these two are equivalent in terms of what to render:

return render(request, "leadership.html", context)

return render(reverse("leadership"), context)

and by using reverse() changes to urls.py will be anywhere the name is used.

As I understand the documentation, reverse(views.leadership) would work but since I namespaced my templates it would not work.

Thanks again.

No.

You are still confusing a reference to a file with a url.

The render function, renders a template, which is a file in the file system. It is not a URL, it is not related to any URLs, and any similarity between the name of a template file and a URL is purely coincidental.

Files and URLs are two different, and totally separate, concepts.

You could change the name of that file (leadership.html) to abc.def, and it would still work exactly the same in your render function call within your view.