Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

URL Linking: app_name, Path Names, and Arguments

In this lesson, you’ll learn about linking templates together, namespaces in Django, path names, and passing arguments in URLs. You’ll also make friends with a new error: NoReverseMatch!

Comments & Discussion

reblark on Nov. 13, 2019

At 1:05, your html code for all_projects.html is missing: <div class=”row”> and of course, the closing tag for div

reblark on Nov. 13, 2019

Now, I see it. but it doesn’t look right… BTW, “single” is pronounced “sing ul”

reblark on Nov. 13, 2019

Sorry to bother, but I just cannot make this work and have examined the code to near death: ‘Page not found (404) Request Method: GET Request URL: localhost:8000/projects/4%7D Using the URLconf defined in CA.urls, Django tried these URL patterns, in this order: admin/ projects/ [name=’all_projects’] projects/ <int:pk> [name=’project_detail’] The current path, projects/4}, didn’t match any of these.

This is the error message, not the “NoReverseMatch” message…4 is the id number for the first database entry. If I simply put “4” as the argument, I get the page and then when I click on the button, I get this error message.

reblark on Nov. 13, 2019

Wow. Persistence, persistence, persistence and then try again. Your selling the “error messages are your friends” pitch is terrific. I looked at the error messages many, many times. But, finally I saw something that was giant, “that’s not right.” and, it wasn’t, now my code works. I really appreciate your constant “harping” on this message and I like the images because they make the “harping” palatable. I am very grateful.

Lokman on Jan. 8, 2020

Hi @Martin, for code here:

<a href={% url 'projects:project_details' project.pk %}

Why can’t we just replace app_name since we already defined the variable in ./projects/urls.py

Lokman on Jan. 8, 2020

Hi @Martin, for code here:

<a href={% url 'projects:project_details' project.pk %}

Why can’t we just replace app_name at ‘projects’ since we already defined the variable in ./projects/urls.py

>>> from django.urls import include, path
>>> from projects import views

>>> app_name = 'projects'
>>> urlpatterns = [
        path('', views.all_projects, name='all_projects'),
        path('<int:pk>', views.projects_detail, name='projects_detail'),
    ]

Thanks

rolandgarceau on Jan. 16, 2020

The beginning is very confusing to know exactly what linking two templates actually is. Just starting to describe existing functionality dooes not clarify this. If it is the # in the href that signifies template linking, then explain that. If it is the process in which one has to implement a work flow to get to the linking, then explain the process and the steps before just diving into how to change a file. This makes it very difficult to follow, especially for those never exposed to template linking as it is being described with django and for nested project structures.

Martin Breuss RP Team on Jan. 17, 2020

Ah, I just see that that’s a confusion I introduced with calling it “Template linking” in the video.

A better way to name that into slide might be:

Creating URLs in Django Templates

I’m attempting to explain what Django does behind the scene and where it gets the information from that it needs to construct a valid URL that can point users from one page (built by a template) to another page (built by a different template).

Linking With URLs

Instead, I am accessing the resources that are exposed at different URLs, specifically:

  • http://localhost:8000/projects and
  • http://localhost:8000/projects/1.

In Django, and many other web frameworks, the layout of the data that is available at a certain URL is defined inside of a template. Templates are the blueprints for the HTML page that ultimately gets displayed by your browser when you access a certain URL.

Just like any webpage, they can contain links to other resources (=other URLs), and in Django in order to display a link on your final HTML page, you can edit the template that is what Django creates the HTML page from.

URL Fragments (#)

What might look a bit confusing is the # that you spotted in the URL after I clicked on the button. The resulting URL looks like so:

http://localhost:8000/projects/#

This URL points to the same resource as /projects without the #. This part of a URL is called a “fragment” or “anchor” and points to a specific section in the same resource.

MDN explains on their page about URLs:

#SomewhereInTheDocument is an anchor to another part of the resource itself. An anchor represents a sort of “bookmark” inside the resource, giving the browser the directions to show the content located at that “bookmarked” spot. On an HTML document, for example, the browser will scroll to the point where the anchor is defined; on a video or audio document, the browser will try to go to the time the anchor represents. It is worth noting that the part after the #, also known as the fragment identifier, is never sent to the server with the request.

The code you’re working with contains a default # in the href attribute of the button link element you’re creating:

<a href="#" class="btn btn-primary">Read more </a>

This just means “stay on the current page when clicked”. If you use the fragment in a link’s href without any further identifier, the # takes you back to the top of the current resource, which can be used for “Scroll to the top” links.

In this case you don’t see a change since you’re already at the top of the page.

Editing The Template

In order to make the link useful, you then edit the href attribute in the template. The edits you make in here ultimately create a URL that gets pointed to when you click the link, and this video explains what happens and how the final URL gets created in Django.

Hope that helps and clarifies the situation.

Martin Breuss RP Team on Jan. 17, 2020

hei @Lokman. If I understand correctly, you’re wondering why you can’t write:

<a href={% url 'app_name:project_details' project.pk %}

in your template instead of the following (which is correct):

<a href={% url 'projects:project_details' project.pk %}

? (Please clarify in case I misunderstood)

The reason that you can use the variable name projects inside of your link is because you defined it in /projects/urls.py. Without setting that app_name variable, you would not be able to use it for linking.

And you want to be able to use the value of the app_name variable in the templates explicitly, since it allows you to link to different apps with separate url configurations.

E.g. if you had another Django app in your project, let’s call it blog, that contains its own file for url configurations /blog/urls.py and you also set the app_name variable in there, then you could theoretically link to a resource even by using the same name, like so:

from django.urls import path
from blog import views

app_name = 'blog'
urlpatterns = [
        path('', views.project_details, name='project_details'),
    ]
<a href={% url 'blog:project_details' %}

DISCLAIMER: This does not make a whole lot of sense :) and it’s always better to give separate, distinctive, and descriptive names to all of your functions.

I’ve used this example only to exemplify that if we’d use app_name instead, then Django wouldn’t know which app it should go to look for a resource in. Hope this helps.

Tl;dr

Setting app_name allows you to use its value to create relative URLs in your templates that know which app of your project to direct to.

vikramjeetsra on March 31, 2020

Hi

I am getting this error NoReverseMatch at /blog/ Reverse for ‘post’ with arguments ‘(‘’,)’ not found. 1 pattern(s) tried: [‘blog/(?P<pk>[0-9]+)$’]

even though i added path (“<int:pk>”, views.post, name=”post”), in url

and <a href=”{% url ‘blog:post’ post.pk %}” class=”btn btn-primary”>Read More</a> in html

def post(request, pk): post = Post.objects.get(pk=pk) return render(request, ‘blog/post.html’, {‘post’: post})

in the view

Martin Breuss RP Team on March 31, 2020

Hei @vikramjeetsra! Looks like a lot of your code set up seems fine to me. When you check your initial error, there’s a hint to what might be going wront:

NoReverseMatch at /blog/ Reverse for post with arguments (‘’,) not found. 1 pattern(s) tried: [blog/(?P<pk>[0-9]+)$’]

Specifically, look at this part: with arguments ‘(‘’,). Seems like there was nothing to find after /blog/ in your URL. Are you sure you entered a number after the slash, like so:

http://localhost:8000/blog/1

okorobright13 on April 15, 2020

hi everyone!!!, please can anyone help me to fix this,i can not see the blue button Read More of this code?.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

</head>

<body>
{% extends "base.html" %}
{% load static %}
{% block page_content %}
<h1>Projects</h1>
<div class="row">
{% for project in projects %}
    <div class="col-md-4">
        <div class="card mb-2">
            <img class="card-img-top" src="{% static project.image %}">
            <div class="card-body">
                <h5 class="card-title">{{ project.title }}</h5>
                <p class="card-text">{{ project.description }}</p>
                <a href="{% url 'projects:project_detail' project.pk %}"
                   class="btn btn-primary">
                    Read More
                </a>
            </div>
        </div>
    </div>
    {% endfor %}
</div>
{% endblock %}


</body>
</html>

Martin Breuss RP Team on April 17, 2020

Hello @okorobright13, the HTML that makes this button is the following Link Element:

<a href="{% url 'projects:project_detail' project.pk %}" class="btn btn-primary">
    Read More
</a>

I am not sure why it would not display for you. Could you share more of your project code, maybe via GitHub? Also check out Bootstrap’s Docs on Buttons, that might help you forward.

Martin Breuss RP Team on April 17, 2020

It is also possible that you are not passing any projects to your template. Double-check your views.py file whether you are fetching the database entries from the database, as well as passing them on to the template correctly.

Another thing to check is whether you have any entries in the database. If there’s nothing in there, then your template won’t have any posts to display.

Joel Witherspoon on May 2, 2020

Thanks for explaining the namespace for views. I was confused as to their purpose when I used another resource to learn Python.

Muthukumar Kusalavan on May 3, 2020

thanks for your work, Mr.martin. i have one question.

so everytime, i do pk, i need to update like this? even if it is 100?

p2 = Project.objects.get(pk=2) p1 = Project.objects.get(pk=1) ........ pn2 = Project.objects.get(pk=n)

Bill Lafferty on June 11, 2020

Hi all,

I get the NoReverseMatch error on the main project page (named ‘farmapp’ in my case). The individual projects under farmapp do display correctly, though, if I append the url with /1, /2, etc.

Looks like I have the appname and namespace set up correctly. I’m stumped. Any ideas where else I can look?

urls.py

app_name = "farmapp"

urlpatterns = [
   path('', views.all, name='all'),
   path('<int:pk>', views.produce_detail, name='produce_detail'),
]

template –> all.html

 <a href="{% url 'produce_detail' project.pk %}" class="btn btn-primary">

Thanks. Bill

Bill Lafferty on June 11, 2020

Hi again,

Forgot to add the error message I’m getting!

NoReverseMatch at /farmapp/

Reverse for ‘produce_detail’ not found. ‘produce_detail’ is not a valid view function or pattern name.

Request Method: GET

Request URL: localhost:8000/farmapp/

Django Version: 3.0.6

Exception Type: NoReverseMatch

Exception Value:

Reverse for ‘produce_detail’ not found. ‘produce_detail’ is not a valid view function or pattern name.

Exception Location: C:\Python\portfolio.env1\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 677 Python Executable: C:\Python\portfolio.env1\Scripts\python.exe Python Version: 3.8.3 Python Path:

[‘C:\Python\portfolio’, ‘C:\Python\Python38\python38.zip’, ‘C:\Python\Python38\DLLs’, ‘C:\Python\Python38\lib’, ‘C:\Python\Python38’, ‘C:\Python\portfolio\.env1’, ‘C:\Python\portfolio\.env1\lib\site-packages’]

Martin Breuss RP Team on June 11, 2020

Hi @Bill! Since you’re using both the app_name and the name argument in your path(), you also need to refer to both in your {% url %} tag. Currently you are only mentioning the name argument here:

 <a href="{% url 'produce_detail' project.pk %}" class="btn btn-primary">

How would you fix it up and correctly add the app_name also into your link here?

Martin Breuss RP Team on June 11, 2020

Hi @Muthukumar Kusalavan, sorry I missed your question. I am not sure I completely understand, but maybe this helps:

Inside of your view function in views.py, your pk is going to be a variable that changes depending on what URL the user tries to access. So it will automatically change to the number of the project that you are trying to access.

But yes, every time you want to get a specific entry from the database, you need to pass the specific pk of that object (in this case - and usually - an integer) to the database call. Hope that helps!

Bill Lafferty on June 11, 2020

Hi Martin,

Ok, to add the app_name, I think I need to do as follows. Still not working, though. Am I on the right track?

<a href="{% url 'farmapp.views.produce_detail' project.pk %}" class="btn btn-primary">

Martin Breuss RP Team on June 11, 2020

Totally on the right track, only the syntax for this is a little different. Instead of a . to separate app_name and name, you need to use a :. :)

Martin Breuss RP Team on June 11, 2020

That rendered potentially a bit confusing with the colon-dot-smiley, so here’s the correct syntax:

'app_name:name'

Martin Breuss RP Team on June 11, 2020

Also keep in mind that this is not a reference to views.py, as you were trying to establish, it seems.

You are exclusively building these URLs through the information inside of urls.py, which is why all you need to construct the URL properly is the 'app_name:name' - both of which are located in urls.py.

Hope that helps to clarify this!

Bill Lafferty on June 11, 2020

Makes sense, thank you! Noted that it’s not in reference to views.

However, it is still giving me trouble. This gives me the same noreversematch error at /farmapp error.

 <a href="{% url 'farmapp:produce_detail' project.pk %}" class="btn btn-primary">

Martin Breuss RP Team on June 12, 2020

This link should be fine now, you fixed it up correctly. There might be another link in that template that doesn’t have the correct namespace set up? If there is any link on your page that Django can’t resolve, it will give you the NoReverseMatch error.

Another thing I notice: you mention your template sits in template/all.html instead of templates/all.html (not the “s”). Django only automatically discovers folders in apps that are named “templates”. Might be a typo, but thought I’d mention it.

If none of this solves it you can post a link to your GitHub repo and I can take a look.

Become a Member to join the conversation.