Your finished project still looks a bit better than your current project, so let’s spice it up with a bit of Bootstrap. You’re going to center the contents and add some navigation.
Join us and get access to thousands of tutorials and a community of expert Pythonistas.
This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.
More Styling
00:00 Our finished project still looks a bit better than our current project, so let’s go ahead and spice it up with a bit of Bootstrap.
00:16
I’m going to simply replace what we have in here, for now, with a bunch of Bootstrap code that I copy-pasted. Let’s take a quick look. We’re using a heading for our project.title, and remember, we’re passing this project from our view, from the detail_view().
00:32
Then, I’m just applying some Bootstrap classes. Here’s an image link to "{% static project.image %}", our image URL sitting in here, and as an alternative text, we’re giving a project description.
00:45
Additionally, I’m going to fill 100% of this column part that Bootstrap creates with this setup. And what we have here is another heading, a smaller heading, {{ project.description }}, and what does is it built with—the technology.
01:00 Let’s take a look how this looks. When I reload it, this looks already much better. The one thing that’s still different over here is we have the whole thing centered and up there, we also have some nice navigation.
01:15 I will show you how to implement this by just putting the pieces into the right place. This is going to be another bunch of Bootstrap code. Read up on it in the associated text, or just learn some more about Bootstrap if you’re interested in that. For now, we’re just going to make our app look as good as this one does.
01:35
Notice that the page that I’m editing—the template that I’m editing—is going to be base.html, because I want this header to be appearing on all of the pages that I have inside of my app.
01:47
So, I’m going here above {% block content %} and I’m pasting a navbar that I just took from the Bootstrap website. We’re also opening up this "container" class before our block, which is going to add some Bootstrap styling, and I’m going to have to close it afterwards.
02:09 So, what’s happening here is this part
02:15
creates the Bootstrap header, and then this container around whatever content we’re putting in the templates that we’re extending base.html from, is going to help to apply a certain styling that Bootstrap uses.
02:37
Okay, so look at that! We’re getting a NoReverseMatch. 'projects:projects'.
02:45
And that is simply because I copy-pasted that from the finished project, but we actually built it a little differently. So here, I’m linking to 'projects:projects', but that’s not how we called it, so we got a NoReverseMatch. Remember where we go to check?
03:02
We go to check first in urls, make sure that we have the app_name—correct—and we have the view name—'all_projects', 'project_detail'. That’s our home, so that’s where we want to link to.
03:16
And then next, we check inside of the template—in this case, base.html. We look for the url tags. Here is one and there it is, see? Okay, the app_name is correct, but the path() name is incorrect. So here, we need the proper path() name.
03:34
And we see this happens down here again. So, we’re linking back to the page. And now, we should have dealt with our NoReverseMatch. Let’s check it out.
03:46 I reload this. It’s working and it finally looks great. We have the navbar up top. We have our details page. Let’s check that when we click Home, we come back to the list view. We can click in here, go to my test project, come back Home, check up the next project.
04:04 Everything is looking nice and very similar to our finished page. Awesome! We’re totally getting there. We did some nice styling here. Congrats. Before we stop the styling for this one, here’s one last thing.
04:21 Take a look at how does this page look like if we check it out on the phone. Now we could not really check it out on the phone yet, but what each modern browser offers are developer tools, if you right-click and then say Inspect Element,
04:38 you can choose to display it either as a normal web page, or if you click up here, as a device. So here, for example, on iPhone X, or you can choose a different phone, as well.
04:52 Our page looks pretty crappy on the phone, right? Do you see that? Like, it’s very small. Imagine seeing a page like that on your phone. You would probably not impress anyone with your portfolio if it looks like this.
05:03
So, there’s actually a very simple thing we can do to solve this problem because we’re using Bootstrap, which is designed for being mobile-responsive. The only thing we need to do is add this one line of HTML code into our base.html so that it applies to all of the pages. You can simply Google this one if you don’t know it. It’s the meta "viewport", and then it allows us to make the page mobile-responsive by declaring that the content is going to look for what’s the device screen-width, and then adapt to that one. I’ll put it into the code now, and then we can see how much better our page looks on the phone.
05:51 I put this viewport line in here. If we reload the page now, you can see that this looks much better. Now, the cards adapt to the device width, and we can click here, Read More.
06:05 Also, our single page looks quite decent. So, that’s nice. With this said and done, I think we’re fine with leaving the design as it is right now. You can always dive deeper into this front end development if you want to make it look better, check out Bootstrap, but I think we’ve got a pretty decent page that looks good both on the phone as well as just normally on the browser.
06:31 Okay, great! So, what I want to show you in the next video is moving a bit away from styling, but we want to be able to add more of those projects and we want to make this in an easier way than always having to go into the Django shell.
karakus on June 18, 2020
Thanks for the info Martin - it all helps!
charneuk on Aug. 14, 2020
i’m still getting this error message
NoReverseMatch at /projects/1 ‘projects’ is not a registered namespace
Martin Breuss RP Team on Aug. 15, 2020
Hi @charneuk. For the NoReverseMatch to go away, there are a couple of things you can check, see if you can find the bug by following the suggestions in NoReverseMatch Debugging.
Let me know what you tried and what worked - or if it didn’t work so we can dig deeper.
KatMac on July 23, 2021
HI Martin
I have created a new file called “custom.css” and placed it in the same folder as base.html, all_projects.html etc. and added this code to the base.html head tag…
<link rel="stylesheet" href="http://127.0.0.1:8000/projects/custom.css">
It isn’t finding this file. Is there something I am missing here?
Martin Breuss RP Team on July 26, 2021
Hi @KatMac, if you want to add your own CSS file to customize your app’s look and feel, you’ll have to handle that CSS file as a static file.
In short, just like you want to remove hardcoded URLs from templates, you’ll also want to handle static files without hardcoding your URLs:
# your-template.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'projects/custom.css' %}">
Hope that helps! :)
Eli on Oct. 30, 2021
Hey Martin, first of all thank you for being responsive here to help guide us, and also thanks to the community for helping us to find the same navbar from bootstrap that you are using. Honestly I was unsure which navbar to grab. MY question is about the meta structure. I noticed that I can either add a second meta tag for the device view or i could add it to the existing tag. Is there a best practice or is that personal preference?
Martin Breuss RP Team on Nov. 2, 2021
Hi @Eli, I’d suggest to add a second <meta> tag. This keeps the information logically separate:
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
The first meta tag is about character encoding, the second one about your site’s viewport. At least to me this approach makes it less effort to maintain, because I can find the information I need more quickly.
samjeezy on July 24, 2023
I keep getting this error. Any nudge in the right direction would be appreciated.
Exception Type: NoReverseMatch Exception Value: Reverse for ‘projects’ not found. ‘projects’ is not a valid view function or pattern name.
Martin Breuss RP Team on Aug. 2, 2023
samjeezy did you check out the lesson on debugging this error? It could be a couple of reasons you’re getting the error, that lesson gives you hints and approaches on how to tackle it: realpython.com/lessons/noreversematch-debugging/
Become a Member to join the conversation.
Martin Breuss RP Team on June 18, 2020
Hi @karakus! That’s an interesting question and might come down to personal preference, although let’s see what Django suggests:
While this doesn’t explicitly address your question about multiple apps, I could see it used like that as well. E.g. you’d use a project-wide
base.htmltemplate, and then app-specificbase_APPNAME.htmltemplates etc.Personally, I would make this choice on a per-project basis, since both approaches make sense to me. If it’s a project where the apps are tied together rather firmly and it’s unlikely that I would segment one of them out to use it elsewhere, then I would opt for the general
base.htmltemplate, especially if unified styling and structure is something I’m going for. Otherwise, having everything neatly packaged inside of its app feels the most comfortable to me. :)Tl;dr: I’m not sure there is a definite answer to your question. There are some good practices you can follow, such as the approach of double-inheritance that the Django docs suggest, and it’s a good idea to consider the trade-offs of either approach on a per-project basis.
Other Approaches
There are also ways to make the inheritance conditional that I have never used myself, but you could play around with it. Here are two links on StackOverflow:
I like sticking with the other approach better, though, since it feels to me this could potentially get a little messy ¯\_(ツ)_/¯