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.
Hint: You can set the default subtitles language 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.

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 0003everything 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 0let’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

so, “.0003_auto_20190601” means that you did this on June 1 of this year.

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 as src, are to be delivered in double-quotes. That means there need to be double-quotes outside of your Django static 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:

  1. Code that translates to the database schema
  2. 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? 🤔

  1. 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.
  2. 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…

  1. I agree with other comments you should use standard variable names when using the shell to work with sqllite interactions in videos.

  2. 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…

  3. 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 the SECRET_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.

Become a Member to join the conversation.