Build Views
In this lesson, you’re going to create your views and have a visit with your good friend, the AttributeError
! According to this error message, the module project.views
has no attribute called all_projects
, so head over to views.py
to create this view:
# Create your views here.
def all_projects(request):
return render(request, 'all_projects.html')
Now, you’re getting a new error message, TemplateDoesNotExist
, because you haven’t yet created this template, so Django doesn’t know what to render.
00:00
Let’s go ahead and create our views. As you already know from the last video, we’re going to start this one off with a good old friend, the AttributeError
.
00:10
'project.views' has no attribute 'all_projects'
. Great! So, let’s head over there
00:16
inside of views.py
and create this view. We’re looking for one called all_projects
, that’s the one we want to create. If I say def all_projects()
, taking the request
, as always, as input, and we want to return render()
.
00:39
We want to return the request
and template_name
, and that’s all we have to worry about for now. So, I’m returning the request
, and as the template_name
, I’m going to put 'all_projects.html'
.
00:55 So, what’s going to happen over here?
00:59 It changed. It seems to be running fine. Let’s head over—
01:06
this slide is already telling us what to expect. If I reload this here, I’m going to get the TemplateDoesNotExist
error. Again, just simply because I have not created this template yet, and that’s why it’s telling me it cannot find this template and doesn’t know what to render. Great!
01:26
So, back to here. We know already how to fix this TemplateDoesNotExist
, right? We’re going to have to go in here, templates/projects/
, and create the template in here with the same name. We’re going to do that in just a moment. For now, let’s focus on the view. In this case, we went to make a query to the database.
01:43
We want to return all the projects, and the views is where the logic of the code happens. So, what we want to do in here is query the database to return all Project
objects that we have in there. So, you might be wondering how to do that, and it’s actually exactly the same code that we used when we were inside of the Django shell.
02:10
So, if you remember what I ran in there to retrieve all the objects from the database, it was something that went like Project.objects.all()
, right? And we want to save this to a variable, so I’m going to say projects =
this.
02:30
Now, this is not working yet. It’s telling me, also—it’s red underlined, and the reason is simply that I didn’t import the Project
model. Go ahead and do that. from
…
02:50
Here it is. So, from our projects
app in the models
file, I’m going to import the Project
class, and now I’m able to call Project.objects.all()
. This is actually working.
03:02
So, usually, the suggestions are very helpful. Sometimes they’re a bit off, so don’t worry about it here. Okay, so I’m returning this projects
.
03:10 What can I do with this? One thing I can do, just for us to take a look, I can print them out. I’ll do that.
03:23
So, one interesting thing for me when I was learning Django is to understand when is this code going to get called? I think that’s very important, and that’s why we’re putting this print()
statement in here. My server is running, you see that? It’s all fine, but nothing is printed.
03:37 And that’s because this function has not run. Now, the question is, when does it run it? The answer to this question is simply when we go to the URL and make a request!
03:48 In this case, our template still does not exist. But I made a request, which, if we go here,
04:00
printed out, before giving us the error—because the template doesn’t exist—but before that, this print()
statement ran, so we get this QuerySet
Project
with one Project
object in there.
04:11
It’s the same thing that we got in the Django shell with the exact same code, right? So, all that’s happening is Django is routing through our setup, it’s routing the request
to this view, and then executes the code—whatever code is sitting in here. In this case, we’re making a call to the database and retrieving all objects, printing out those objects to the console—that’s happening down here—and then we’re trying to render a template that currently doesn’t exist yet.
04:40
Cool! So, what we want to do, additionally to building out this template in the next video, is we want to be able to access these projects, because currently, I’m not passing them forward, right? All I’m passing forward is the request
object and the name of the template.
04:56
How you do that in Django is as a third argument in here, you can simply pass a dictionary. So, I’m going to give this a key called 'projects'
,
05:11
and as a value, I’m going to give what we got returned from our database, so this projects
variable. I’m going to pass it here with the name 'projects'
.
05:22
Just to make it easy, I’m naming them the same. And I’m going to get rid of this print()
statement, because we don’t need it. So what I’m doing here now, inside of this view, is it’s going to get called when the user accesses this page.
05:37
Yes? Then, all the code in here runs, every time that the user accesses this page. I’m going to make a call to our database and retrieve all the Project
objects that are stored in there. And finally, I’m going to return a render()
call that takes the request
, takes the name of the template that I want rendered, and passes these objects that we retrieved from the database forward to the template as well.
06:01 Because then, in the template, inside of a Django template, we’re going to be able to render these objects. So, let’s go ahead and do that in the next video where we’ll create our template and make sure that we’re actually displaying what we got from the database.
reblark on Feb. 26, 2020
It’s a tricky thing to try to copy your code but to change the key names. But, I am doing it and I think it helps in providing a deeper understanding of what is happening. Here is where I got confused. In models when you create the data base, you used the name “Project” by simply capitalizing project. My corresponding directory names were pix and pixie basically for projects and project. When I did this code to create the database, I failed to simply use “Pix”. It took time to figure that out but I did and everything works. I had to really search for this resolution and it was worth the effort. Naming is a crucial aspect of computer science and of life. Ursula Le Guins “EarthSea” trilogy was all about naming.
Martin Breuss RP Team on March 1, 2020
Congrats for figuring it out. 🙌
Did I understand correctly that you initially hadn’t capitalized the model name?
Just FYI: the model names don’t need to be a capitalized version of the Django project name. It just made sense in the projects example, since the objects we are handling in the project
app are, well, Project
s. :)
When you build larger Django applications you will frequently have more than one model per app, and they can be all sorts of things.
As a naming convention that you can keep in mind: the model names should always be singular. Think of it in a way that the model code will be used many times to create single instances of that class.
reblark on March 10, 2020
In the bit about using the print command as a debugging tool, when I refreshed the page, the results in the terminal window had two lines <QuerySet [<Project: Project object (1)>]>
It seems like Python must have printed the code line: projects = Project.objects.all() just prior to the print statement. Yes?
Martin Breuss RP Team on March 11, 2020
Sounds to me like you might be using print()
on the queryset somewhere in your views.py
file.
That would explain why it prints out to your console when you make a request on your browser (i.e. refresh the page).
R morel on May 4, 2020
def all_projects(requests): return render(requests, ‘projects/all_projects.html’)
Scretch on June 14, 2020
I really like your approach of building by errors. I am definitely one to cringe when that happens but you make a good argument of learning from these messages. I imagine dark times when devs didn’t have that in the early days and had to find the errors manually. Oof....
Martin Breuss RP Team on June 15, 2020
👆👆👆👆👆👆👆 ❗️❗️❗️❗️❗️ 👆👆👆👆👆👆👆
Totally, good point! So thanks to all the previous-time-devs for the work on making nice error messages for us! 🤓
shaundefrancia on Aug. 31, 2020
This is where I got stuck. Please help.
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/
Using the URLconf defined in portfolio.urls, Django tried these URL patterns, in this order:
admin/
projects/
The empty path didn't match any of these.
You’re seeing this error because you have DEBUG = True
in your Django settings file. Change that to False
, and Django will display a standard 404 page.
Martin Breuss RP Team on Aug. 31, 2020
Hi @shaundefrancia
Looks like you went to the following URL path in your browser:
Request URL: http://127.0.0.1:8000/
Check what Django is telling you related to this:
Django tried these URL patterns, in this order:
admin/
projects/
The empty path didn't match any of these.
Do you have an idea what you could try to do next?
bogdanchira on Oct. 6, 2020
Hi,
I did not quite get what the dictionary part do and how you use it?
Bartosz Zaczyński RP Team on Oct. 6, 2020
@bogdanchira That dictionary, called a context, is a means for passing arbitrary data to a Django template. In this case, the template file is named all_projects.html, and the only data you’re exposing to that template is a collection of Project
objects read from the database.
You can refer to the attributes defined in the context from your template, e.g.
{% for project in projects %}
<p>{{ project.description }}</p>
<p>{{ project.title }}</p>
{% endfor %}
Become a Member to join the conversation.
reblark on Feb. 25, 2020
Your top level structure is Project>portfolio,projects, yes? In the views directory you import Poject from projects.models, yes?
If my structure is Gulls>pix,pixie, shouldn’t I (in “views”) import Gulls from pixie.models? forsta?