Locked learning resources

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

Unlock This Lesson

Locked learning resources

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

Unlock This Lesson

Display a Single Project: Recap

Congratulations on making it nearly to the end of this section! Here’s what you did:

  • Used the Django ORM in the shell and in views.py
  • Learned about primary keys (pk)
  • Used angle brackets in your urls.py path objects in order to be able to capture specific parts of a URL and pass them forward as arguments
  • Used an int: path converter to verify the URL path’s datatype
  • Defined proper namespaces for linking and reverse URL matching
  • Passed objects inside URL template tags
  • Debugged the NoReverseMatch error
  • Learned about template inheritance
  • Styled with Bootstrap
  • Made the site mobile responsive
  • Used the Django admin interface

On top of all that, you also have a functioning portfolio site that you can show to potential employers!

00:00 Hey, and welcome to this nearly final section of the course where, in old tradition, we’re going to recap what we did in this section. We started off using the Django ORM—first in a shell and then, later on, we also built it in the views.py. We used it, in this case, to access one specific item from our database, and we did that using primary keys.

00:23 We learned about this pk variable that you might see around in different Django projects and how it relates to the id column that gets automatically generated.

00:32 The next thing we did is we used angled brackets inside of our urls.py path() objects

00:39 in order to be able to capture specific parts of a URL. Then, we were able to pass those forward as arguments, eventually. What we did before actually passing it on is we used the path converter—in our case, an integer path converter—to make sure that what the user enters in the URL is actually going to be useful for what we’re passing forward to the view. In our case, we wanted to make sure that this is an integer and not some kind of string.

01:09 Then, we dove a bit into how does this linking between different templates work. So, we made sure that we know how to define proper namespaces. That helps us both in linking templates together, as well as reverse URL matching.

01:23 And what’s necessary for that is to define the right things in urls.py. We need to define the app_name variable, and we need to define the name keyword for each of our path() objects.

01:36 Another thing we took a look at is how do we deal with this if our path() requires arguments. So, when we’re using these angled brackets and then we want to link forward, we also need to pass that argument so that we can actually find the correct URL.

01:51 Yeah, we talked about how to do that correctly.

01:55 We also took it as a chance to debug the NoReverseMatch error, an error that you might see very often. We narrowed it down to looking at two files, specifically: urls.py and whichever template you’re using .html. Make sure that two important things are squared out.

02:13 So, we want to make sure that Django can identify the right view. We need the namespace for this, so, app_name and the name of the path(), as well as that in case we’re passing arguments, that this is done correctly.

02:26 So, check out this debugging video again, for the process of where to look and how to make sure that—most likely—you’re going to resolve your NoReverseMatch error if you follow these steps.

02:37 Then, we went forward to take a look at template inheritance. We did this following the DRY principle, which means don’t repeat yourself. So, we tried to get rid of a lot of repetitive HTML code that we had in our project by just creating one parent template that the other templates are inheriting from. The two important parts for this is we need to create this {% block content %} with {% endblock %} that opens the space where the child templates can put in the HTML.

03:05 We also need to extend the name of whatever is our parent template. Two simple steps allows us to get rid of quite a lot of repetitive code.

03:16 After creating this base template, we also took a stab at making our style a bit better. We created a Bootstrap header inside of base.html that would appear on all of the pages that we create.

03:29 We also took a very simple step to make our site mobile-responsive by just adding this line of code inside of our base.html. And just to give you a heads up, this doesn’t necessarily always work for each page.

03:43 This just works because we’re using Bootstrap, and Bootstrap is designed for being mobile-responsive. That’s why adding this line of code actually helps us to make it look so good also on a smaller device. Finally, we took a look at the Django admin interface.

04:00 We had to first create a superuser to be able to access it. Then, we needed to register our models, the Project model, in our Django admin.

04:10 We did that in admin.py in our project. After we had done all this, it allowed us to very easily add, edit, or delete database entries in a very convenient way. You can see here, the mobile-responsive admin interface and how I can simply add things here, or edit it, and keep your database up-to-date, essentially, which is crucial if you want to have a good portfolio that you can also show to people. And that’s it! Congratulations!

04:40 You did a good job. If you went through this whole tutorial, you now have a functioning portfolio site that actually looks pretty good, that allows you to keep it up-to-date pretty easily, and I hope you go ahead and add all the cool projects that you’ve built already. Put in a screenshot, put some description, and if you show this project to some potential employers, I’m sure that they’re going to be impressed.

05:04 So, let’s take a quick look at what we built.

05:09 What you should have so far if you followed everything is a project that looks like this. We have a navigation bar up top. Currently, this just takes us to our project index page where we have all of the projects. They’re listed up like this.

05:24 We can click on those to get to a details view of each entry in our database and click up here to get back again. Click here, it takes us to a different one. Everything looks pretty nice already.

05:37 We have some description about the project, technologies that it was built with, and an image.

05:44 We also have the admin interface that Django comes built-in with,

05:50 and it allows us to add a project or delete a project very easily…

06:22 which then also gets reflected right away on our project page.

06:30 So, that’s it for today. I’m Martin and I hope you enjoyed this mini-course on getting started with Django, building your portfolio app. I want to thank you for going all the way through the course, and I want to make sure that you also head over to the final video where I’m going to talk a little bit about next steps on what you can do to make your portfolio look even more awesome than it already does. All right, see you in the final video.

Avatar image for Paul

Paul on Nov. 1, 2019

Thanks for the awesome course martin!

Avatar image for Martin Breuss

Martin Breuss RP Team on Nov. 2, 2019

Thanks for the kind words and also for your contribution in the comments @Paul! :)

Avatar image for reblark

reblark on Nov. 14, 2019

“Mini course?” Damn. Took me forever thanks to my total inadequacy in typing code. But, it was great and I learned a lot from making all the mistakes. They forced me to read more and to understand what I was reading. I can honestly say that I don’t fully understand everything so I will repeat the course again and again. Thank you, Martin.

Avatar image for kal

kal on Nov. 28, 2019

Excellent intro to Django!

Avatar image for Leonard Coman

Leonard Coman on Nov. 29, 2019

Martin, awesome intro to Django! Thanks

Avatar image for Martin Breuss

Martin Breuss RP Team on Dec. 2, 2019

Glad it was useful for you @kal, @Leonard Coman and @reblark. : )

Avatar image for marcinmukosiej

marcinmukosiej on Dec. 16, 2019

Really good basics! Please make advanced level of this ‘Portfolio website with Django’ as it made me to buy the subscription :)

I do expect more from ‘your future employers will be impressed’, please.

That was fun!

Avatar image for aradim

aradim on Dec. 25, 2019

Thanks, fantastic course ! i have learned a lot. More advanced in the future please.

Avatar image for emalfiza

emalfiza on March 22, 2020

Congrats to you the master @Martin! such an amazing and clear step to step project. Upcoming week I have to build a Django Milestone project from my Fullstack Web Development diploma and I really needed a such a teacher to take my hand and explain every bits and bytes…a round of applause to you.

Thank you indeed

Avatar image for Dave Wilson

Dave Wilson on April 1, 2020

I’m so grateful for this! What a great course, thank you so much Martin!

Avatar image for Andrew E

Andrew E on April 7, 2020

Brilliant, thanks for a great course Martin, I really enjoyed it. I had previously seen Django built websites, and tried to reverse engineer my understanding of them, which was completely fruitless. This was a much more efficient way to learn it, and gave me a much deeper understanding. Thanks again for a super course, you’re a great teacher.

Avatar image for Martin Breuss

Martin Breuss RP Team on April 7, 2020

Hi all! Thanks for your positive words, glad you’ve found value in the course :) Noted regarding the more advanced Django topics!

Avatar image for JellyNeck

JellyNeck on April 12, 2020

Thanks Martin! I really enjoyed the class!

Avatar image for hrmessi709

hrmessi709 on April 20, 2020

very lucid and a structured course. way to go martin.

Avatar image for MrUzo

MrUzo on April 24, 2020

Good job Martin!! I’m not actually new to Django, but i learned some easier ways to do some tasks. Thanks for making this so clear to follow.

I need some help with making AJAX calls in Django? Can you point me in the right direction?

Avatar image for Abhishek

Abhishek on May 9, 2020

Good job Martin, you really made it fun with all those brilliantly placed emojis! :) Keep it up

Avatar image for Konstantin Schukin

Konstantin Schukin on June 15, 2020

Thanks for wonderful Django course Martin! Your course helped me understand how it works.

Avatar image for Scretch

Scretch on June 16, 2020

Ditto my fellow devs. Thank you Martin! this was a great course. I will certainly be on the lookout for more content from you.

Avatar image for Rachel Hill

Rachel Hill on Aug. 17, 2020

Thank you! I’m a database developer and the front-end has always been a mystery to me. After completing this course, I’m so pleased to have a new tool added to my my toolbelt. The debugging was especially useful.

Avatar image for gourav9042

gourav9042 on Nov. 14, 2020

Hi Martin, thank you so this course. I have question, I am planning to create a portfolio with more details, like (projects, blog, Dashboards, video’s explanation of live machine learning models and EDA), should I create all in one app or should I do individual app for all as all have databases. Can you please also guide regarding this deployment. thanks.

Avatar image for Martin Breuss

Martin Breuss RP Team on Nov. 15, 2020

Hi everyone! Thanks for the nice words and glad that the content has been helpful :)

@MrUzo: Seems I missed your question here, but for everyone interested in implementing AJAX calls in Django, check out Vitor Freitas tutorial on How To Work With AJAX Requests With Django.

@gourav9042: I suggest that you create separate apps for each of these within one Django project, just as this tutorial suggests to split up the portfolio and blog functionality into two separate apps. This helps you keep your content better structured and easier to handle, update, and debug.

Hope this helps and keep learning! :)

PS.: @Scretch if you’re interested in more Django content from me, I built a whole Django Web Development course over at CodingNomads that starts by covering similar topics, but then dives deeper, has practice tasks & projects, and also goes into deploying your apps.

Avatar image for KatMac

KatMac on July 22, 2021

Hi

In my all_projects.html file, I have the following code that works and navigates to the appropriate page:

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

In my base.html file, I have updated the Home link in the navbar as follows. This gives me an NoReverseMatch…

<a class="nav-link" href="{% url 'projects:projects' %}">Home</a>

I checked the required files and can’t seem to find what the issue is.

I ended up putting in this code and it works:

<a class="nav-link" href="http://127.0.0.1:8000/projects/">Home <span class="sr-only">(current)</span></a>
Avatar image for Martin Breuss

Martin Breuss RP Team on July 26, 2021

Hi @KatMac, did you double-check in your urls.py file that the name of your path() is the same as the name you’re using for this link ("projects").

You might have a misspelling somewhere there, e.g. an s too much or too little. Can you confirm that these two match in your app:

# projects/urls.py

# ...
app_name = "projects"

urlpatterns = [
    # ...
    path("/projects", views.projects, name="projects"),
]
<!-- projects/templates/projects/base.html -->

<a class="nav-link" href="{% url 'projects:projects' %}">Home</a>

Note that the name you’re using doesn’t have to be projects, it just needs to match between the two files.

Avatar image for KatMac

KatMac on July 26, 2021

Hi Martin

Thanks for getting back to me… I tried that and I’m getting an error message.

here is my urls.py

app_name = "projects"

urlpatterns = [
    # path("", views.all_projects),
    path("/projects",   views.all_projects, name="projects"),
    path("<int:pk>",  views.project_detail, name="project_detail")
    ]

My url in base.html below.

<a class="nav-link" href="{% url 'projects:projects' %}">Home</a>

Getting error message.

Page not found (404)
Request Method:     GET
Request URL:    http://127.0.0.1:8000/projects/

Using the URLconf defined in portfolio.urls, Django tried these URL patterns, in this order:

    admin/
    projects/ /projects [name='projects']
    projects/ <int:pk> [name='project_detail']

The current path, projects/, didnt match any of these.
Avatar image for Martin Breuss

Martin Breuss RP Team on July 26, 2021

Hm… @KatMac how does your portfolio/urls.py file in your management app look like where you’re routing to projects/urls.py?

When you look at the error message you’re getting, it seems that there’s an additional /projects part snipped off your URL path:

Page not found (404)
Request Method:     GET
Request URL:    http://127.0.0.1:8000/projects/

Using the URLconf defined in portfolio.urls, Django tried these URL patterns, in this order:

    admin/
    projects/ /projects [name='projects']
    projects/ <int:pk> [name='project_detail']

The current path, projects/, didn’t match any of these.

The first part shown is the URL you’re expecting, but there’s another one after it. It looks just like the <int:pk> that Django snips off if there’d be a number instead.

So it seems you’ve defined the routing from portfolio/urls.py to projects/urls.py already with the path "projects/", which is why you’d get a double projects/ URL here, with the second part snipped off.

What happens when you keep an empty path in projects/urls.py:

# projects/urls.py
app_name = "projects"

urlpatterns = [
    path("",   views.all_projects, name="projects"),
    path("<int:pk>",  views.project_detail, name="project_detail")
    ]

Let me know whether that fixes it, and if so, give me your interpretation on why it does. :)

Avatar image for KatMac

KatMac on July 27, 2021

It worked. Thank you. The empty string indicates the root path?

Avatar image for Martin Breuss

Martin Breuss RP Team on July 27, 2021

Great! :)

The empty string indicates that there’s nothing following the initial path that directed people to this endpoint.

So, if you have “projects” already in your other urls.py file, then the empty path here means that there’s nothing more:

http://localhost:8000/projects

If you have another “projects” string in there, as you initially had, then the matching URL would be:

http://localhost:8000/projects/projects

Each string in a path matches a string in the URL, then chops it off (and optionally passes the rest onwards to another URL config, if it’s set up like your portfolio/urls.py file). Does that clear it up? Glad it’s working now : )

Avatar image for KatMac

KatMac on July 28, 2021

Thank you. I learned so much from this video. Please do more, a lot more

Avatar image for Vasanth Baskaran

Vasanth Baskaran on Aug. 23, 2021

Thanks Martin for this course :)

Avatar image for rya1992

rya1992 on Feb. 26, 2022

i am happy because i started learn django with you not from random videos on youtube you make it easy and sequentially i really love django right now i applied everything in this course except bootstrap part sorry i don’t like styling even in my real project :)

Avatar image for Stephen Brodigan

Stephen Brodigan on May 24, 2024

Martin, thank you for this fantastic course, I had resisted working with Django, largely because I would not have a clue where to start, your course broke down all the trepidation and I love Django.

Become a Member to join the conversation.