Debugging: Part 2
In the previous lesson, you saw that FilePathField()
might not be the best choice for your model, so you’re going to change it:
image = models.CharField(max_length=100)
When you check your page again, you’ll see that nothing changed. This is because you just made some changes to models.py
but didn’t modify the database. In order for the changes to be made in the database, you need to makemigrations
and migrate
.
00:00
In the previous video, we ran into the problem that we realized FilePathField
might not be the best choice for our model here. We don’t actually need it.
00:08
So we want to go ahead and change this. However, there’s a couple of things that we have to consider when doing this, so let’s go over it step by step. In our case, we’re really just saving a couple of characters: /projects/img
and then the filename. So I will change this to be a CharField
(character field), instead.
00:29
We can get rid of all of this and just give it a max_length
argument. Our path shouldn’t be—they are always going to be projects/img/
and then the name of your project, so they should never be longer than 100 characters. Okay.
00:43 That’s a simple change. Now, what does it mean for us? I’m going to exit the Django shell. Did this already do our changes? Let’s go ahead and check. Reloading this, nothing changed.
00:57 And you might wonder: why is that the case? I mean, in this case, we actually didn’t change anything, we just changed the data type, right? But also, we did not do any changes to the database at all.
01:10
We just did some changes to the models
file, but that doesn’t mean that the changes are propagated to the database. So, in order to make these changes to the database, remember, we have to do two things. First, we have to makemigrations
to create the migrations file.
01:25
That’s going to then translate into SQL and make the changes to the database. And two, run the migrate
command to then actually apply the changes to the database.
01:36
Let’s go ahead and try that. I did my changes in here to the models
file. Next, I’m going to go and say python manage.py makemigrations
.
01:49
Here, we can double-check. Okay, migrations for the projects
app. What happened is we altered the field image
on project
. Yes, correct. That’s what we did.
02:00 So, let’s apply those migrations, and let’s see what happens now.
02:10
Cool, so it applied the migrations for 0003
—everything is fine. Let’s take a look at our database right now. Great. We applied the changes. So, does that mean our project works?
02:28
Of course not, because we’re still just pointing to testproject.png
without giving the full path. Okay, so there’s some more debugging that we need to do.
02:39 What we need to do is we need to change the paths for those entries that we already have in the database, so what we’ll do is we will go back into the Django shell.
02:53 We’re going to pull, again, all our projects and we’re going to simply change what’s saved in the database.
03:13
Had an encounter with a little friend here. ps
from the project 0
—let’s save it to its own variable p1
(project 1
), the first one, and p2
(project 2
), the second one.
03:30
Okay. So p1.title
is 'test project'
, and p1.image
—the path is just 'testproject.png'
. Cool. Now I’m going to go ahead and change that.
03:42
I’m going to say p1.image
is instead going to be 'projects/img/testproject.png'
.
03:58 Save that to the database.
04:03
And let’s take a look whether that changed something here. Here it is! Now we’re displaying the right path: projects/img/testproject.png
. Django can find the static file and finally can also display it.
04:16
Our second one still does not show up, and the reason is because we haven’t changed the database entry yet. I’m going to go ahead and do that for the number 2
, also. Let’s choose a different one—maybe that todo.png
image. projects/
…
04:37
Make sure that you save it. If I do not save it and go back over here, we did not yet apply the change to the database, so nothing changes here. However, once I go and say .save()
, my changes that I did here in the console are written back to the database and now we have a different path in here and finally, we’re able to display that image. Great!
05:00 Now it starts to look a little bit like our final version. We went ahead and did an intervention inside of our models. Like, we went back into the models and changed something, and we went to directly interact with our database using the Django shell and changed entries in there.
05:21
At this point, just a quick word of warning: changing column data types, as we did just before in the models
, does not always go as easy as it did for us.
05:30
We simply went and changed this FilePathField
to a CharField
, made the migrations, and applied the migrations to the database and everything was fine. However, in some cases, this is not going to work as easily, and that’s when you’re actually changing the data type.
05:46
So, the FilePathField
is also just a character field, so there were no big changes that we had to do, but if you already have something sitting inside of your database and you apply some changes like this, you might run into some errors from Django. What you can always do—especially when you’re working on a small project and if you’re still in development—you can always go ahead and simply delete your database.
06:10
That’s often the easiest way: just right-click, delete it, get rid of it, and then make your migrations again. Again, makemigrations
and run them, and Django is simply going to create a new database file for you.
06:24 Of course, it means that you’re going to lose what’s written in there so far, but that’s why it’s important to test often and test early to make sure that the stuff works in a way that it does, and so that you don’t yet have your meticulously-crafted projects in there.
06:38 But we’re currently just working with some test data, and then it’s no problem to start over again. There’s other ways of solving a problem like that but I’m just giving you this tip that often, especially for simple projects in development, it’s easiest to just delete and start over. Okay.
06:55 That’s it for our debugging excursion. We did some cool changes. We made it work. We can finally see our images and we’re ready to move on to work a little bit more on our templates. See you in the next video.
reblark on Nov. 6, 2019
After all this, I still get the file path name not the image.
reblark on Nov. 8, 2019
plus the file name in projects/img has changed yet the p1.image shows the old name.
reblark on Nov. 8, 2019
Oh, I get it that I am supposed to get the file path name not the image, but when I invoke the page, the file path name is supposed to deliver the image. Yes?
Martin Breuss RP Team on Nov. 9, 2019
Yes exactly. You’re supposed to fetch the path of the file from the database as a Python string.
Then the HTML attribute src
on your <img>
HTML tag will use that file path to link to, and display, the image on your page.
reblark on Nov. 10, 2019
Yes, I do get that and it didn’t work. I am not sure how, but I did fix it.
rolandgarceau on Jan. 5, 2020
projects/static/ is the django aggregated directory structure but the video does not address leaving this out as the path/to/the/image.png
Martin Breuss RP Team on Jan. 7, 2020
Hello @rolandgarceau, thanks for your comment. Could you explain some more what you mean? I’d be happy to clarify if there’s something missing in the video, however I currently don’t quite understand what you’re addressing with your comment. Thanks!
reblark on Feb. 28, 2020
I have done something wrong and I have spent a great deal of time trying to figure it out. It all started when I carelessly typed (in the shell) ps1.save and did not include the (). I got this message. <bound method Model.save of <Pix: Pix object (1)>> when I got through all the steps of changing the data base and redfining the paths to the images (I have 3 instances instead of 2), no matter how many times I try it, I do not get the images and yet checking the database both in the viewer and with the shell shows me that the paths are correct. Also, the “alt” message has never printed. I have found several errors on my own and by reading the error messages. When I check the terminal log for the action, I find this: “GET /static/pixie.img HTTP/1.1” 404 1653 Obviously that is a 404 error and the path is incomplete. The path should read /static/pixie/img/Charlotte.jpg. Here is the relevant code in my html file: <img src=”{% static ‘pixie.img’ %}” alt=”screenshot for pixie”> Earlier, the direct image path did provide the correct image. I have waited a full day and examined this again with the same result. The database entries are correct paths for images and image=CharField(max_length=100) in models.py. Where can I look? Is that “bound” statement a problem?
Ricky White RP Team on Feb. 28, 2020
Hi Reblark.
You’re using the static
keyword in your img
tag, but your image is not in the static folder. If you are fetching an image from a database you just need {% pixie.img %}
. Hope that makes sense.
reblark on Feb. 28, 2020
Hi Ricky. thanks for the response. However, look at line 12 in Martin’s video, Debugging 1, about 5:32, and you will see that he does use the keyword static and the attribute is “image” not “img.” He states that this is a reference to the database, but I thought his database name was Project, not project. He uses project.image. From that point, he just goes to the individual database entries and adds the file path to each image attribute. I have done that and it works fine. But, I still get the file name instead of the image itself. My understanding is that the img tag in the html file is supposed to point at the database which is why he has “<ing srce={% static project.image %}. Does that make sense?
reblark on Feb. 28, 2020
Hey Ricky. Wow, as I pointed out, your suggestion was not quite accurate. But, it was extremely helpful. Essentially, you confirmed for me where the problem was. So, I kept going back to it, looking at it time and time again, experimenting and trying all sorts of things. Then, I saw it, fixed it and it works. So this: <img src=”{% static pix.image %}” alt=”screenshot for pixie”> works and but alt tag still doesn’t work. I don’t care that much, but if you see what is wrong there, I would appreciate knowing it. And. Thank you. You guys are great!
Martin Breuss RP Team on March 1, 2020
Hi @reblark. To answer your questions:
Naming And Accessing
The model is called Project
, the app is called projects
. And in the templates, I assign one instance of the Project
model, which is equivalent to a row in the database, to the variable name project
.
This last part is what allows you to access the images with:
{% for project in projects %}
<img src="{% static project.image %}" alt="{{ project.title }}">
{% endfor %}
Possible Error Sources
Looking at your problem description, here are some thoughts on what might not have worked correctly, and why:
project
object:project
here is a variable that you create in the template. It is not a string. I saw you put it into quotes somewhere, like so:{% static 'pixie.img' %}
. This part would only be in quotes if you are hardcoding a path right there in the template. However, you are pulling the path string from the database, therefore you’re referencing the attribute of an object, and that object is represented by a variable, not a string.<img src="">
quotes: The HTML specification defines that the values of an HTML element’s attributes, such assrc
, are to be delivered in double-quotes. That means there need to be double-quotes outside of your Djangostatic
template tag. In one example you wrote<img src={% static project.image %}>
without the double-quotes. This won’t work in HTML.
I understand that these situations are a bit tricky and not that easy to fully grasp. One example above talks about having too many quotes, the other one about missing quotes… Oh my! 🙄
Keep in mind that the reason for these little specifics is that the web is mixing a bunch of different languages and technologies that need to find ways to work together. And that’s never that easy! 💪
In any case, congratulations for working it out and you’re doing the only right thing, which is repeatedly looking at it, trying to figure out what can be figured out, taking a break, and asking questions if necessary. Then loop and start from the beginning :)
Hope this answer helped to shed some light on what might have been going on.
emalfiza on March 21, 2020
Cool @Martin I am really enjoying and learning Django from your awesome explanation. Just a short sorta question!
Do we need to implement the makemigration and migrate after each even a single letter changes in the models.py? if so why?
Martin Breuss RP Team on March 22, 2020
Hi @emalfiza, that’s a great question! The short answer is “no”. :) But that probably doesn’t satisfy your curiosity in this matter (I hope!)
So the slightly longer answer is that there are two aspects to the code in models.py
:
- Code that translates to the database schema
- Code that handles representation and methods on the model objects in Django
For any code changes that belong into the first category you need to do the migration-dance in order to apply them to your database. For code changes that relate to the second category there’s no need to run migrations, since that code never changes anything in the database in the first place.
Now, what is what? 🤔
- DB-schema code: Everything that creates a column in the database. These are the lines of code that assign something like
models.CharField(...)
to a variable name. - Django Model object code: Everything else. That means extra methods you could create for your models, or dunder methods (e.g.
__str__()
for better representation in the Django admin) etc.
So to answer your “why” question: You only need to run makemigrations
+ migrate
if you want to make a change to the database schema. Not all the code in models.py
does that, so you don’t need to run migrations on every single letter change. It depends on which letters you change. Hope this helps, and keep investigating!
emalfiza on March 22, 2020
Sweet you should be proud of yourself @Martin, its an honor learning Django at this point from someone so awesome like you.
Martin Breuss RP Team on March 22, 2020
Oh, thank you very much for the nice words 😊! Glad my course is helpful for you!
Abhishek Karande on May 2, 2020
like we registered template
folder don’t we need to register static folder
?
Martin Breuss RP Team on May 3, 2020
Hi @Abishek. Django automatically registers all static
folders inside of apps when you leave the default setting in settings.py
called APPS_DIRS
on True
. Counts both for templates
and static
folders.
But in order to display static files you need to run python manage.py collectstatic
. You don’t need to do that during local development, because Django’s Development Server does it for you.
superpando on June 2, 2020
Martin, thanks for this great course. My web page only displays Hello Again!. I have gone over the files and past videos and now I don’t know where else to look to solve this problem. I kinda wish I had a friendly error message!
Martin Breuss RP Team on June 5, 2020
Hi @superpando, glad you’re liking the course. :)
If your page is displaying Hello Again!
, then you need to check inside of your views.py
file and make sure that it doesn’t simply return the HttpResponse
object with that string. Next thing to check is that if it is correctly pointing to a template file, what is the content of that template file. You might have mixed up the templates or might still be pointing to an older version of a view function.
Remember that what gets displayed on your screen goes through the Django Flow:
urls.py
views.py
templates/app_name/your_template.html
Check all of those files and make sure the request flows freely and as you’d expect it to :)
Bill Sanderson on June 7, 2020
I cannot get either direct link or static db link images to show up.
I can see image in static/projects/img/testproject.pmg
but getting 404 error on load. all other db info shows up.
i modified the image location in the db and verified it.
html {% load static %} <!DOCTYPE html> <html lang=”en”> <head> <meta charset=”UTF-8”> <meta name=”viewport” content=”width=device-width, initial-scale=1.0”> <title>Document</title> </head> <body>
<h1>Projects</h1>
{% for project in projects %}
<img src="{% static project.image }" alt="{{ project.description }}">
<div >
<h5 >{{ project.title }}</h5>
<p >{{ project.description }}</p>
<p >{{ project.image}}</p>
</div>
</div>
</div>
{% endfor %}
</div>
</div> </body> </html>
html page output
Projects this is a test test project this is a test
projects/img/testproject.png
this is a 3nd test test project2 this is a 3nd test
projects/img/testproject.png
django server error: Not Found: /projects/{% static project.image } [07/Jun/2020 03:49:13] “GET /projects/%7B%%20static%20project.image%20%7D HTTP/1.1” 404 2212
Bill Sanderson on June 7, 2020
disregard my previous message. I found my config issue. I was missing % on one %} and the static img was in a sub folder but wrong folder. I corrected both and all is working now.
Martin Breuss RP Team on June 8, 2020
Nice job figuring it out! :)
Bill Sanderson on June 8, 2020
Martin.. few suggestions…
-
I agree with other comments you should use standard variable names when using the shell to work with sqllite interactions in videos.
-
If someone posted their complete project to a public github (with django complete setup) . There are security issues with that being exposed. django SECRET_KEY = in settings.py for one. Also they should turn off debug if they wish to expose new django site to internet. # SECURITY WARNING: don’t run with debug turned on in production! DEBUG = True ( not sure if you mention this in original overview) but should remind in last video very helpful…
-
Would be great if on slides in videos. the page # 1 of 29 was show so can find later in download pdf. quicker. maybe add a roll up cheat sheet of all the commands used in class with a quick refrence.
great overview… looking forward to deeper dive into django classes..
Martin Breuss RP Team on June 9, 2020
Hi @Bill and thanks for your suggestions. I am not entirely sure I understand all of what you are writing, but here are my thoughts:
- Variable Names: What “standard variable names” are you thinking of, and which other comments mention them? I looked around but I don’t understand what you are referring to.
- Security Concerns: There are indeed some security concerns that you need to address before you deploy your Django webapp, foremost setting
DEBUG = False
and avoiding to push theSECRET_KEY
variable that you use in production to GitHub.
However, this practice project is not designed to take you all the way to deploying your application, which would involve quite a few additional steps. As such, there is no security issue with pushing an unused SECRET_KEY
to GitHub, nor with leaving the DEBUG
setting as-is. The vulnerabilities only exists when you are working with a live webapp. Then you shouldn’t use the same random SECRET_KEY
variable that you pushed to GitHub, and you should set DEBUG = False
in your settings.py
file.
- Cheat Sheet: I also don’t quite understand what you are asking for in Point 3, but if you are looking for a general Django Cheat Sheet, we currently don’t have one of those. However, you might find what you’re looking for here or here (although they refer to an older version of Django and therefore have some subtle differences)
Hope that helps and let me know if there was something I misunderstood.
alazejha on Nov. 22, 2020
Dear Martin, I checked and double checked all the files, and they are accurately emulating your materials. However, I still get the broken image, i.e. blue square with ? in it. Please let me know the error I’m making. Many thanks!
Martin Breuss RP Team on Nov. 22, 2020
Hi @alazejha, you’ll need to share more specific information so I might be able to help you out. Easiest would be if you shared your code on GitHub and post a link here, then describe what exactly you tried and what is happening instead of what you expect.
You can also compare your code to the Example Project.
Hope that helps and keep trying!
James on Jan. 14, 2021
I am running into behavior that I don’t understand. Here’s what I did:
>>> # manage shell
>>> from projects.models import Project
>>> items = Project.objects.all()
>>> items[0].image
'testproject.png'
>>> items[0].image = 'projects/img/testproject.png'
>>> items[0].image
'testproject.png'
# ??? - why didn't this change?
>>> i0 = items[0]
>>> i0.image
'testproject.png'
>>> i0.image = 'projects/img/testproject.png'
>>> i0.image
'projects/img/testproject.png'
# ??? - why does this work and the above doesn't???
# Even more bizarre:
>>> items[0].image
'testproject.png'
# ??? - items[0] is different from i0...
# If I use the id command I can see that items[0] and i0 are
# in fact different objects at different addresses, but I was
# not expecting this.
Perhaps this is so obvious that I can’t see it, but I don’t understand why I can’t change the image field from the items[0]
reference. What am I missing?
sornasundaram-c on Jan. 23, 2021
Can anyone help me understand why the tutor changed image datatype from FilePathField
into CharField
?
Bartosz Zaczyński RP Team on Jan. 24, 2021
@sornasundaram-c Martin explains this in his previous lesson. In essence, the FilePathField
is meant for choosing a filename from an existing folder, while we need to persist the full path of an image in the database.
Calvin on Jan. 16, 2023
I wanted to make more friends, so I troubleshooted to fix the static/project/img pathing. First by going into porfolio(django’s management folder), then in settings.py
, under STATIC_URL = 'static/'
you need to add a list with these variable naming: STATICFILES_DIRS = []
. Inside the list, you’ll need to add the shortened URL paths so Django will know to look for more static files.
Your settings should look like this when all is said and done:
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / "static/",
'projects/static/projects/img',
]
Refresh your app and test it out to verify.
simma99 on May 31, 2023
Hi. When I run python manage.py makemigrations
, it says No changes detected. Please help.
Bartosz Zaczyński RP Team on June 1, 2023
@simma99 The most common reason is not including one of your Django apps in the INSTALLED_APPS
constant in the project’s settings.py
module. Did you add it there?
simma99 on June 3, 2023
@Bartosz Zaczynski I included the Django apps in installed_apps in settings.py but it is still showing no changes detected.
Bartosz Zaczyński RP Team on June 5, 2023
@simma99 Is it possible that you already made migrations but haven’t applied them yet? There could also be a problem with your models, but it’s just guessing on my part.
sammyutere on Aug. 26, 2023
Hi, Just letting you know following your instructions step by step, I did not get my displayed as you got. So I think there is something definitely missing somewhere, that you have not covered.
Bartosz Zaczyński RP Team on Aug. 28, 2023
@sammyutere Thanks for letting us know. Could you please share a little bit more details about what’s not working and what specific steps you’ve taken following the instructions? What is the discrepancy between the expected and actual results? This way, we’ll be able to better figure out what the issue may be.
sammyutere on Aug. 31, 2023
Hi, In the section Debugging part 2 from the 2 min mark, when I followed the instructions as you did to display the project image. It did not work for me.
deebrown2011 on Jan. 22, 2024
Hi, i’m wondering if somebody can help? i was having some issues with information being correctly displayed in my server after making changes made following the above video. anyway, long story short. i deleted the db.sqlite3 and re-run the migrations etc and now i have a new table but my models.py info is not showing in new sqlite3 database eg, title, description…etc. also my webpage is now blank when refresh it, so it looks like me app is not being recognised. any ideas on how to reinstate the project?
Martin Breuss RP Team on Jan. 22, 2024
@deebrown2011 if you deleted your db.sqlite3
file, then you also deleted all the data in it. That means that your new database will be empty until you add new data to it, for example using the Django Shell like I did in this course.
Martin Breuss RP Team on Jan. 22, 2024
@sammyutere can you give us more information on what exactly you did and what happened instead of showing the image? That’ll make it easier to figure out what might have happened.
deebrown2011 on Jan. 23, 2024
Hi Martin, thank you for your response. much appreciated.
your response was exactly the solution i was looking for! i was searching for while and the answer was simple.
really appreciate the help.
Martin Breuss RP Team on Jan. 23, 2024
Glad it worked @deebrown2011 :D
Become a Member to join the conversation.
reblark on Nov. 6, 2019
so, “.0003_auto_20190601” means that you did this on June 1 of this year.