Build a Data-Driven Website with Django | Alyssa Blackwell | Skillshare

Build a Data-Driven Website with Django

Alyssa Blackwell, Software Engineer / Artist

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
24 Lessons (3h 9m)
    • 1. Introduction

    • 2. What is Django?

    • 3. Installing Python and VirtualEnv

    • 4. Installing and Using Git

    • 5. Setting up a new Django project

    • 6. (Optional) Set up a Dedicated Database

    • 7. Creating a Gitignore file

    • 8. Starting a New App with Django

    • 9. Designing Database Models

    • 10. Implementing Database Models

    • 11. Using the Django Shell

    • 12. Creating our First Page

    • 13. Building Page Templates

    • 14. Loading Static Files

    • 15. Dynamic Data in a Template

    • 16. Adding Custom Styles to a Page

    • 17. Using Forms to Create Objects

    • 18. Editing Existing Data Objects

    • 19. Deleting Objects from the Database

    • 20. Setting up the Second Data Model

    • 21. Database Relationships

    • 22. Creating Relationships Between Data Objects

    • 23. Querying the Database

    • 24. What's Next?


About This Class

This course will teach aspiring web developers to harness the power of Django web framework and create websites that store and manipulate data. Websites that go further than a simple blog and DO something.

Whether you are new to programming, or just new to Django, this course will lead you through the process of setting up your computer for development with freely-available tools, designing a database from scratch, and crafting a website capable of storing and retrieving objects from that database.

Your instructor, Alyssa, has been working as a software engineer for over six years, using Django to complete projects such as:

  • An inventory and checkout system to allow a company to keep track of thousands of devices
  • A tool for analyzing log files collected by WiFi devices
  • A website to generate meal plans to fit a certain calorie, protein, fat, and carbohydrate goal

To demonstrate the techniques in this class, I will be creating a “fountain pen tracker” website, that will allow a user to keep track of a collection of fountain pens and ink. However, this is not a one-size-fits-all course. Students are encouraged to follow along with any project ideas that capture their hearts.

Note: The song used in the introduction videos is Elevator Bossa Nova from


1. Introduction: Hey, guys, welcome to how to build a data driven website with Jay. No government. One of the questions you might have is what we mean by data trip. So right now, if you go to website building service like wigs or squarespace, you can make a website. You can plug in some text. You could make a walk, but that data doesn't actually do anything it's displayed. That's what those kinds of websites or for So this class is going to talk about websites that taking data so they have a date. It means they store data, and then they do something with it and presented to the user in new and exciting ways. If all you want is a landing page or a blogger or a quick shop, don't reinvent the wheel. Use tools that you already have. The tools that exist for blog's and shops have been polished over years of development, and part of being a programmer is knowing when it's worth your effort to develop something new and when it's more efficient to use something that already exists. That being said, you certainly can use Django to create a blogger or shop, but we're not going to be covering those specific features in this course. The example project I'm gonna use is a fountain pen and ink tracking website where a user will be able to put in pens at the own and thinks that the owned and then track which inks are in which pens. And with Jingo in a little bit of programming, we can do this fairly easily. I'm gonna show you how to set up your development environment and get the tools that you need to actually get started programming. I'm gonna briefly talk about python code and how it works. And I'm gonna show you all the pieces you need to make a website that saves some kind of data, does something with it and displays it to the user. Now, who am I? And what is my expertise on this subject? My name is Elissa, and I have been a professional software engineer for over six years. I've made several websites using Django as well as mobile applications in other types of applications that also used pipe on. My goal for this course is to break down jingle love development in a way that beginners can follow. And I am going to be talking what a clean development floor looks like. So we're going to be using source control. We're going to be using virtual environments, and I'm gonna explain what all of these are and why they're useful. What you need to get the most out of this course is a computer, and this is not something you can do on your phone. You will also need the courage to use the terminal or companion line, which can be scary to some people. But it gives you a lot of power over what you're doing. And I'm gonna guide you every step of the way. A basic knowledge of the development is helpful. I'm going to touch on the programming concepts and things like HTML and see a sense. If you have existing knowledge, that's good. But I'm going to do my best to provide everything you need right here in the course with that, let's get started. The first thing will be doing is setting up our computers with all the tools we need to do development 2. What is Django?: before we get started actually installing things I'm going to be talking about what Jingo, ISS and what types of things do we need to get started. So Django is a blood development framework, which means it's not just a tool that plugs into something else. It is the whole framework it handled front end, which is the part that the user sees what that looks like and how it is displayed. And it also handles the back, which is what does the computations. It's what saves the data and manages the data and passes it to the front. The creators of Jingo have be very easy. It started, and they follow very clean project structure, which means all the different pieces are kept separate. And it's easy to know what you need to change if you want to implement a certain future and the general framework does use its own language, it was developed on top of an existing language called by Thought. So the first thing we're going to need to install in order to get started is high. I Don is a programming language that is used for many things, not just for Jenko, and it's what we call an interpreted language, which means it means a piece of software running on the computer called an interpreter that can kind of take the code and turn it into something that the computer can understand The next two things we need are not officially necessary to do this development, but they are necessary to do it right. So first thing, we're going to set up a virtual environment. What this does is it contains are Pipe Holland packages that we're gonna be using to build this but site into a virtual space so you can have different projects on the same computer and the packages they're using don't conflict. It's okay if this doesn't make a lot of sense to you right now. I just want to get a foundation going so that when you launch into the set up, it's not completely foreign to everybody. The neck. Next thing we're going to need to do this right is a source control or a version control software. What this is for is to essentially actively saving system for your entire project so you can save a file and you can undo changes you made to that file. There's no way to keep track of what you've done over time. Unless you use a source control system, we'll set it up. And then throughout the project, we will create things called commits, which will mark in the software. This is a point where I want to save what I've done. This is really good to know if you ever want to work on a team doing software development, and it can get you out of a lot of tight spot because you are able to go back to previous commits and turn you want and recover things that you have deleted or I made a mistake on in future. Commit or save whites. The source control system we're gonna be using is called Get Knowing Get or a similar software is critical. If you ever want to get into professional software development, the next tool will need. It's fairly basic. We'll just need an editor to actually write the code. It the one and recommended for this course is called. I didn't It's free and it's easy to use, and it has all the features that we need. If you'd like to use a different one, of course you're welcome to do that. The last thing we're going to set up is actually optional, and that is the dedicated database. I'll talk more about this in later lessons, but essentially there are two options you can use a seek life data base, which is little more than spreadsheet file on the computer. Or you can use a dedicated database, which will actually run a server from your computer that will behave exactly the way database. But if you have it up on the Internet now, getting to this 0.1 thing I am not going to cover in this course is how to deploy a website . There are a lot of things to think about when you're exposing website to the wide world, and I wanted to keep this course a basic development course for beginners to python and two wife development. If you're interested in learning how to deploy ended angle website on the Internet, let me know I may make another course after this one, or they may already be, of course, here on skill share that covers that exact topic. So that's everything we need to cover before getting started. So we're gonna move over to the computer and start setting it up for development 3. Installing Python and VirtualEnv: so the first thing will be to install a python interpreter. You can get this from python dot org's. As you can see here and download python. Most of the links that you'll see right on the home page will detect which operating system you're running on and give you the version that will work best for you. For me, I'm installing 3.7 point two. Modern installers should include everything you need. One thing I like to do is check this box at the bottom to put Python 3.7 on the path just to make it easier to use. All this does is tell your operating systems of Windows Mac OS Whatever you're using, um, it tells it where to find Python so that you don't have to run it from a specific folder. You can find it anywhere on the computer. You will also need a tool called Pit. It's used to install public python packages so you can use them, and Jingo is one of these packages, so make sure that is checked. It should be checked by default. There are other optional features that are checked by default. I'm not going to talk about thes specifically in this course, but you can check on python dot org's for more information about the different options that the installer has. For now. It doesn't hurt to leave them checked, because you can always remove them later. Any time I install things, I like to make sure that I know where it's being installed. If you don't really care about organizing your insult programs, you can just leave this as Thebe fault next just had installed. Wait for it to finish, and then we can move on to test that it was installed correctly. The next step. Maybe a little scary to people who are not familiar with programming. We're gonna need to open a command prompt or a terminal. So on Windows hit the Windows Key type C M D to find the command prompt program and then just hit Enter to open it on a Mac, you should be able to open the terminal from the utilities section of your applications, and you'll want to save this to your dog or save a shortcut somewhere because we are going to need it again. And let's be honest. If you're on Lennox, you probably already know how to use a terminal just in case. Ah, the commands to open a terminal is by default control all t. The benefit of adding python to the system hath in the installation process is that if we type python into any terminal, it will open the Python interpreter Right there. I've typed a simple print statement here print, parentheses, quotes and then whatever text I want to print. Hero. Hello. And you make sure to close the quotes and the parentheses hit. Enter and it should type Hello. Using exit with parentheses is how you get out of the interpreter and exit again. Well, get out of the terminal. Reopened the terminal If he closed it in the next step, we're going to start installing some python packages. And if you type pit P I p into the terminal, it should print out some help information. This tells you that pip is actually installed and we can move on to use it to install packages to install anything With pip, you just type pit install. And in the name of the package, the 1st 1 we're going to get is called virtual end in the end is short for environment, and you can see we got a little message here. Pip is very helpful in telling you what went wrong. When things go wrong here, I need to update Pip. The one the ship with the python installation is a little bit out of date. So if you want to update, just run the command listed in the warning message and it should update itself without a problem. And I just like to run the install command again to make sure it was installed. Whenever I get warnings, I want to make sure that I did actually get the package I wanted to get. And at any time, if you want to see what you have installed, hip list will list all of the packages. They're currently installed. And all we have right now is pity. Set up tools and virtual M. And this is good. This is all we want to prevent different projects and their packages that the use from colliding with each other. We want to install the packages in a virtual environment. So they're kind of contained to make this easier. I like to use virtual em proper. If you're installing a windows, you will need the dash win at the end of it. If you're on Lennox or America, you should just need Pip Install virtual and rapper. This will install, and then we can get started creating our virtual environment. And that is where we will install the specific packages for Django and the other things that will need to create a virtual environment. We just right make virtual M, and this is M K virtual envy space and then the name of our environment for this one. I'm just going to call it first Django, because this is the first course undoing with Django, and it seems like a fitting name. This is going to print out which python installation it's using and tell us where it's putting the environment. Since we're using thieve virtual improper, we don't need to remember where the environment is installed. We can find it by name, and it's going to be this name that we gave it for me. It's first Django. You can call it whatever you want. Just don't forget what it's called, or it might be difficult for you to find again. Off camera. I created a folder to put my project in. This is where the code is gonna live. You can put it in your documents folder. You can create a special folder for your projects. I put mine on the desktop because this is just a demonstration, and I wanted to be able to find it quickly. A quick note for people who've never used a terminal before. If you type C D and then a path to change to, you can change directories that way. So in order to get into my project folder, I did see D and then the full path of the project folder. And to see the contents of the folder you're in, just type D I. R on Windows or ls on Mac or Lennox, and it will print out what's in that folder. The next thing we need to do is tell the virtual environment where the project lives. So we go to the folder for a project and we do set project ER and then the the path. A dot is a short cut for the current directory. So we're going to use that hit enter and it will tell you that it successfully added this directory as the project directory now, you may not have noticed when we created this virtual environment, it added this name of thievery, actual environment at the beginning of the prompt in the terminal, in parentheses. Now this tells us that we're currently in the space of this virtual environment. And while it's active, any python packages be install will only be installed inside the virtual environment and not the whole computer. Any python scripts we run will only be able to access packages installed inside the virtual environment to get out. Just type deactivate that will go away. And to get back into a virtual environment, we type work on and then the name of the virtual environment that we want to work on. If you ever encounter an error that says something is not installed, but you're pretty sure it is, the first thing you should check is that you have activated your virtual environment and you're in the right space. If you are feeling a bit overwhelmed by all the terminal work, feel free to take a break. The next step is going to be installing git, and it will require more terminal work. Move on to the next video. When you're ready to continue, I'll see you there 4. Installing and Using Git: for this lesson. We're going to go to get tash SCM dot com and install get Follow the instructions to install the latest version for your operating system. For me, I get this nice button right in the middle that says Download to 0.20 dot one for Windows. It'll take a second to download and then just launched the installer when it's ready to go . And there's going to be a lot of options here and you, most of them you will not need to worry about. Some are operating system specific whether you want to add shortcuts for for the git software on your context menu. Whether you want to associate certain files with get for beginners, I would leave everything as he default. And then, if you would like to customise this a little bit more, you can go research what all of these options mean. The one exception is the default editor used by get the one in that it includes is called Vim, and it is very hard to use. As the message says, it is recommended to choose something that you're more comfortable with, possibly no pad or another very simple text editor because of them can be a little bit of a stumbling block for new users. All the other options should be fine left as default if you become a more advanced to get user, or if you're working on a team that has specific preferences for how things should be set up. Ah, you can customize these, however you wish. And as with python and pip, just to make sure it's installed type of, get into the terminal or command prompt and just make sure it prints out some help information. This shows you that it is installed and accessible on the system path in order for get to know what we want it to track in a project. We have to first work on our project in the virtual environment. So we are in the right place and we have to run. Get in it. This will tell you that it's initialized an empty repository in that folder. Don't worry too much about what this means right now. The overview is that you have told get this is the folder I want you to keep an eye on, and I'm gonna be doing something with it later. If you look at the directory. It doesn't look like anything has changed. What Gin is actually done is created a hidden file, which tells Windows or Lennox or Mac that most people don't need to see that file. The name of this file is docket, and you really don't want to mess with it. You want to leave it where it is and use the commands from get to make changes to the repository. The reason I mention it is because if you copy this Project folder, it will copy that hidden file as well. And then your git repository will exist in the new folder without you having to do anything at all. Now that get is watching this folder, you can you get status to see what's going on right now. We have done nothing. There's nothing in here. It shows us which branch we are on. I'm not going to go into branching in this class, but it's something to look into. If you're working on a team, especially, we're working on the master branch and there is nothing here to commit. That means we haven't changed anything. Once we do change something, we can go in to get and I will show you what those changes will look like. Now, in order to actually write some code, we need a tool to write the code in. Now you can use any text editor. It's much better and easier to use something that is designed. Four code. There are a couple out there. The one I'm recommending is called Adam, and you can find it at Adam A t o m dot io. So it's not dot com, and this one is free and has a lot of features that I think will make it easier for python development. The installer is very simple. It may prompt you for a location to install it in, but for the most part, it just goes Okay, so we have installed get installed, our editor, and now we're ready to install Jingo and get started working with our project files. 5. Setting up a new Django project: in some python projects. This would be the time I restart to create files. But with Jingo being a complete Web framework, they have a lot of tools that will create the structure in some of those files for you. So the next step is to install the Django package with pit, as we've done before, and whenever possible, PIP will automatically install dependencies or things that a package needs in order to run usually other packages. So you'll see some other things in here, aside from Django, that there are also being installed to test it out. Let's start a python interpreter by typing python import Jingo. This is how Python brings in packages that it wants to use, and we're gonna do another print statement. But instead of putting text directly in here, we're going to do jingo dot get underscore version, and this is running a function that will give us back text that represents the version. Now here is another point where we can demonstrate how the virtual environments work If we exit the interpreter and deactivate our virtual environment. When we try, the same thing will get an error in the Python interpreter that says there is no module called Django now. This is because we're outside of our virtual environment. Jingo exists inside the virtual environment, and it's all contained. And what this means is that you can have different virtual environments running different versions of Jingo, and you don't really have to worry about them interfering with each other. As a solo programmer, This isn't a big deal, but if you were working on multiple projects or all with other people updating a certain package to a certain version, me introduce problems. Sometimes it's easier just to keep the older versions. And this is really the benefit of using these virtual environments back to setting up our first Jingo project when Jingle was installed. It didn't put anything into this folder, but it did install a tool that we can use to generate all of that structure. That the Jingo framework needs to operate properly, typing Django dash admin space and then start project all one word and another space, and then the name of the project will generate all these files. Before you submit this project to make sure you're in the folder that you created for your project, and that the virtual environment is active. Thesis able project I'm doing is going to be a felon pen and ink tracking website. And so I'm calling mine FP tracker. At first, it doesn't look like it did anything, but if you list the directory contents, you'll see it created a folder called FP Tracker or whatever you named your site. There are some other files in this folder, but instead of trying to find them in the terminal, I'm going to open up Adam. And there is a feature in here under the file menu to add a project folder. What this will do is show the entire folder structure for a project. So you don't need to be going in and out of the file menu toe. Open up all your files individually. You can open them right from this menu. One thing you may notice is all of the files are green. This is because Adam also recognizes that there is a get repository in this folder and that all of these files are brand new running. Get status will show that the FP Tracker folder in all its contents our untracked, which means get, is not aware of its brand new to get what we want to dio is add this folder to the git repository Tell Get Yes, I want to track this and save it in the next version. A shortcut to add everything that is shown as untracked or modified is to do get add star. You can also identify specific files and folders by name. But if you're sure that everything shown is something you want to add, you can just use a star and it's much quicker. This is called staging your commit. And if you do get status again and we'll show you that you have staged all of these files to be committed Now we need to actually commit. And this is the piece where you tell get this is the next version and you give it a note. The command is get commit, dash em and then you put your note inside quotes. This know is how you're gonna find what your change in which commit if you need to roll something back. If you've made a mistake, if you need to go back to fix it, there are a lot of reasons why you might want to find a specific commit. So it's best to keep these notes short and informative, focused on what you changed in possibly why. That's also why it's good to commit early and commit often if you make commits and smaller chunks. Then if you did make a mistake, if you need to undo something, you don't have to indu large amounts of work just to get at one particular problem that you have. And also at this point, if you're using some kind of online repository hosting service like Get Hub Orbit bucket, this is where you would want to push those changes up there. But I'm not going to cover that in this video. Let me know if you want to see videos on project management, because that is an entire topic unto itself. Now, if we do it, get status again, it will tell us everything is clean and there is nothing to commit. This is because if we do a git log, we can see the history we have submitted that change that set of changes, and now we're working on a fresh, clean slate, so our next commit will only include changes we do from here on out. This might seem like a lot of work. But if you ever encounter a problem that can be solved, if only you'd made another commit, you're really gonna thank yourself for putting in the work to keep things organized. Now that we've used Ringo to generate thes files and out of them to a commit, we can have a look at what's actually in there. So it created a folder of Be Tracker, and if we go in there, there's another folder called FB. Tracker will get to that one in a little bit, but there's also a file called Managed Pie. The dot pie tells us that this is a python file and has a number of commands weaken. Send to it to make you do things. The 1st 1 I'm going to do is called Run Server. One word. You'll see it print out some information, and then it will tell you that it started the development server. This is the piece that's gonna actually run the website. Ah, 127.0 dot co 0.1 is the I. P address or the Web draw. You can type out that address, or you can just write local host Colon 8000 will be ableto look at the website that is running. The Jingo has this demo website, but once we start editing the files and adding our own stuff, we'll be able to see our website. At this address, you can change the server so it runs on a different port, so that would be instead of 8000 after the colon, it would be something else. But for the purposes of this class, we're going to keep everything at its default settings. As I'm developing, I like to keep three things open. The first is Adam, with my project open in the sidebar. Second is the terminal where I can control the running server and view any errors and then the final. Is this a browser with the demo website running? With that, we're ready to start development. However, there is another optional set up step. Set up a dedicated database. This step I recommend for anyone who wants to go into professional Web development, as it's something that's going to be useful but isn't entirely necessary just to learn how to use Jingo 6. (Optional) Set up a Dedicated Database: there is only one more step to getting everything set up in this step is actually optional . As I mentioned in the introduction, the last piece we'll need for a data driven website is a place to store the data or a database by default. Django uses a sequel Light Database. What this is is essentially just a file similar to a spreadsheet that holds all the data. These are fine for development, but they are very lightweight, as the name suggests. And so for people who were wanting to get into Web development a little bit more seriously , I recommend jumping into full databases right from the start so you can get used to working with. Um, there are two full databases that Jingo supports, and one of them is my sequel or my SQL, and the other one is Post Crest. I am going to show you how to set up a my sequel database, because that's what I like to use, but you can use whichever one you are most comfortable with. If you just want to get up and running with the sequel light, that is fine, too. You can download a server from the My escape all dot com website under downloads. You want to find the community server. This is the free one. It's quick and easy to set up, and it as everything you need. Follow the website instructions to install whichever version is appropriate for your operating system. I picked the one for Windows as I am running windows and I trying to get the most basic installation that I needed because Jingo does handle a lot of the management for you, so we don't need many of the management tools that they offer. The website will also try to convince you to sign up and, like participate in their forums. You don't need to do this, but you can if you want. I opted out and just started my download during the initial installation process. It will have you set up a user name and password for this server, and it's important that you remember what the's are because you will need them to connect to a later. I can't show this for you exactly, because I did already have a date to be set up and running. And so my installation process looks a little bit different. What you're actually installing here isn't one database, but rather a server that can hold many databases. So after this is installed, you will need to set up a database for your jingle project to connect to. So we're going to open up the my sequel Command line Client on Windows. This is a program separate from the command prompt or terminal on Lenox and Mac. Depending on how you installed your my sequel server, you may be able to just type my sq well into the terminal and connect that way, regardless of how you connect to the server, The actual commands that you send are exactly the same. To create a new database, there's only one create database and then the name of the database. Don't forget to write this one down. Keep track of it because this is how you're going to tell Jingo to connect to this database . All my sequel commands should end with a semi colon. I forgot mine, and it kindly reminded me with a little arrow that I needed to add it. And that's all we had to dio in the my sequel Command Line Client. And there is one more piece we need and that is a python package that connects the python to the data bees. So Python does not have built in functionality to connect to a my sequel database. But there is a publicly available package, so we're going to Pip install my sequel, Dash Connector, Dash Python and make sure again your virtual environment is active when you install this, and now we're ready to tell Jingo where the database is and how to connect to it. So go into your jingle project in Adam Confined the setting Stop I file. It should be inthe e second folder down. So not the main project folder, but the 2nd 1 and it's just called setting Stop I. There's a lot of generated information in here, pretty much all of us we won't need to mess with for this simple project. But if you end up doing websites that have Loggins or or need took be configured to contact email servers, you will need to come in and it's some of this stuff, but for the most part of, we're going to leave it. How it is, but we do need to find is this data basis section. It's a little bit further than halfway down, and this is where we're going to plug in the information for our database. We can see right now that it has two properties in here. One is called Engine and the other is called Name for the sequel eight Database. That's all you need. But for the mice equal, we're gonna need a little bit more because there is a log in. And since it isn't just a file, it's running at a specific I P address. We do need to tell it where it's running now. Here is where you're going to have to remember what you set up your server to do because I can't tell you the answers to these questions. These were determined by you when you installed the database. Now it doesn't actually matter which order these properties go in, but they do need to have the correct spelling. So engine needs to be spelled correctly, and it needs to be in all caps. Same with name, user, password and host. And another thing that sometimes I forget us well, is that each of these entries needs to be separated by a comma. So you see a comma at the end of each country. This is what tells Python that each of these are individual items in this default database section. Here, the name of the database would be whatever you put under create database. And the name after that is the name the user in password were set up by you to log in to a server. So, um, I used first tango and this is a password not very secure, but it's only running locally on my machine. So it's on a big deal if someone gets that password and then finally, the host for me, I left it by default as just local host and the engine. I can actually tell you that should be my sequel, dock connector dot jingo. And this is because we chose to use theme icicle connector Python package to make that connection. There are other ways to do it, but on Windows it can be pretty tricky. So I opted for the easiest route. Now that we have everything set up, we can run the server with Python managed up. I run server, and we can actually see our new database in action. There's no data saved in it yet, but since the server started up in connected without any errors, we know that it is working 7. Creating a Gitignore file: before moving on. It's a good idea to commit the changes that we've made so far, and I've actually noticed something here that I should bring up because it is kind of important here we see the sequel light database and these high cache files are being detected by get and we don't actually want this. In general, it's bad form. Teoh save generated files to a git repository. Well, we want to do is get something called a get ignore which will tell Kit certain types of files we don't want to worry about. We want to leave them there on the machine, but we don't want to actually save them in our commits. Um, like thes cache files are generated when things are run and they are not really used for anything. We don't put code into them. We don't change them ourselves, so we don't need to save them. And so there is a helpful website where you can actually grab get ignore files that people have developed for other projects. This one is designed specifically for Django, so it includes all the types of files that we might not want to keep in the repository that Jingo might use, and this saves us from having to come up with all of these individual rules ourselves. I grabbed this file and placed it in the top level folder of this project. So it's the same folder that the dot get file is in, and what this is going to do is it's gonna tell, get what to ignore. And as you can see, the pie cache folder isn't have a great color because we're not worrying about it anymore. It's not going to ask us if we want to add it, because it already knows that we don't care about that particular type of file doing another get status. We can see that now only the files we care about will show up. Now, say you forgot exactly what you did to these files and you want to remember what has changed. You can do a command called git diff, and it will print out this text. I will show you parts of the file that were changed. So here it shows us we removed two lines and we added five lines to setting Stop I. That all looks good, so we're gonna add everything and write and do another commit, and I'm going to demonstrate what the commits look like If you don't add a message. This is the default editor. FIM. It's very scary, not really, but it can be scary if you've never used it. The trick is hit I to enter edit mode, and that will allow you to type things in. And then you need to hit escape to get out of edit mode. And then this is the weird part. Type colon w Q. And that is going to tell it to save and quit vim. Those are the basics. If you forgot to set your commit message editor to something else, I like to do a quick its status to make sure everything was committed properly. And if you're feeling extra paranoid, you can do a log and just make sure it's there. Getting familiar with these commands is really gonna help you out in keeping things organized and knowing what you've changed and when you've changed it. And if you're looking to get into the professional software world, knowing how to use a source control software like get is highly highly valued, buckle up for the next lesson because we're going to start getting into the code 8. Starting a New App with Django: next, we're going to set up our data models, and we always want to make sure we're working in our virtual environment first. And the first thing we're gonna do is generate some more files with dingoes tools. Jingo has this separation between Project folder, which is our FB tracker folder and then an APP folder, which is where the functionality lives. So we're going to use manage dot pie to start a new app for our pen tracker. So we're going to do Python managed up. I start app, and then Pence is what I'm going to call this app. And the vocabulary might be a little bit confusing because you might think of the app as the entire project. But as Faras Jingo is concerned, an APP is just a section of functionality that is used by the project. We're going to come back to this model stop I to put our code in, but first, I'm gonna walk through each of these files really quickly and it up. I is used to tell python that this is a module or that the files in this folder can be included in other python files. Admin. DuPuy is where we set up the Jingo admin site, which we won't be doing for this class ap Stop. I already includes the definition for this app so we can include it in the settings model. Stop. I is where we put our model definitions, which is going to be the focus of this lesson test stop. I, as you might guess, is where you put tests for your app and then views is where we're gonna put our views, which are gonna kind of drive the website. They're gonna be doing the computations and querying the database. For now, let's go back to models dot pie. And then we're gonna take a quick moment to plan out what this model is gonna look like. I'm going to be using some more vocabulary that may not be familiar to you If you've never done programming before, If you find yourself really struggling, I recommend checking out a python course. Perhaps you're on skill share, but I'm going to briefly describe the things I'm going to be talking about. The first thing is a class which ah, in programming terms is kind of like a definition for a type of object. The class tells us what types of information we can find out about the object, the properties or fields that it has. And then it also may have functions, which is the other thing I'm gonna be talking about a function is kind of like a mathematical equation. It gets some type of input and it gives you something back, and that's really the the basic thing of it. And as I go, I'm gonna be explaining the different functions we're going to create and what they dio as always, feel free to ask questions in the discussion section, and I will answer them to the best of my abilities. 9. Designing Database Models: when thinking about database design. I like to start with a piece of paper. If you have a whiteboard that will work to, uh I just prefer toe, have something visual right can plan things out and see how they connect to each other to start. Let's think about what we know about the website we want to build. I'm gonna use my fountain pen and ink tracker as an example, but this step is where you're gonna differ wrenching your project from mine if you're deciding to go with something of your own design. So when I'm thinking about the fountain pen tracker, the first thing I think of obviously I need to have some way of tracking depends. So I'm going to write down pen. This is one type of item that I know the website is going to need to track. Similarly, I know I think is another one. There are diagrams called UML diagrams that are an official way of expressing database design like this. But I'm gonna keep things simple and just explain to you what I'm drawing here. Let's start with the pen data model and think about what types of information about these pens we want to save in our database. The obvious ones are gonna be brand name and the model name. And throughout this process, you're gonna be making decisions about whether certain information should be separate or together. I think it would be cool to be able to sort things separately by brand without worrying about the model. If I include both of these in a single piece of information, just name. There's gonna be some tricky things to kind of split up that text. So by separating brand and model, we can deal with each of these pieces of information separately. I'm probably gonna need the same thing for the ink. Except now that I'm thinking about it, model isn't quite the right word. So I'm gonna call this the color way. Now, what else might we want to track about the pence the color of the pen if I have more than one of the same pen, but they're different colors. I want to keep track of that. The name size fountain pens like this one is have a nip, but they write with and they come in different sizes. This one is a fine. There's also broad medium and extra fine. There are some other ones, but we're not going to get into those. What else? Another interesting piece of information might be the date I purchased the pen, so I couldn't see how long I've had a particular pen. Now you can get as deep into this as you want. I'm gonna leave, and at this, I'm going to say this is good for the information. I'm gonna track about my pens now, think. Is there anything else I need to know about the ink? I don't think there's anything built into the ink, but I might want to track a rating. I'm gonna call that good. Now, another thing we need to think about is what type of information are each of these pieces. So Jingo has a concept of fields, and they've come up with a set of field types that they think covers everything, and I think they got pretty close. One of the most common ones are entered your field character field, which is abbreviated as care field. And don't worry if you can't read my writing. I'm writing at a weird angle here, but I will put everything up on the screen what I'm talking about actually creating these different types of fields. Uh, we have things like a date field and a time field, and we also have in date, time field. And then there's things like Text Field, which is meant for larger pieces of tax. Larger than a name of something would be, and we also have some more advanced fields, such as image fields or file fields. Don't worry about the messy writing. I will clean it up in post, as they say. So once you have decided what you want to track, you need to decide what kind of feel do you want to track it in? I think these ones, we'll all be character fields. And if you're a little confused about the color, uhm, I'm going to represent this as a hexi decimal color. So you've probably seen these before. They start with this hash mark, and then they have, like a bunch of letters and numbers strung together. I'm not gonna talk too much about what this represents, but it's just a way of representing color. You can look it up. You can use the color picker and pick it, and it will convert it to Hexi Decimal for you. And I'm going to use this because there's no other easy way to represent a color because it is a little bit more complex as a data type. So by converting it to text, we're making things much easier on ourselves. Um, if you have some data that you can't really represent in one of these fields, you might think about whether that is its own model. So, for example, if I want to put down here, the story purchased that if I wanted to include the entire store as an object, we wouldn't have a field that we could put that, and we could put the name of the store in character field or the address of the store in a character field. But there's no way to represent the store as a whole with any other information. So in that case, we might want to create a store model that contains all of this information. We're not going to do that for this class, but it's one thing to think about when you're designing your own database set up here and you're thinking about what types of data you want to be in there, and this date of purchase is gonna be a date field, as you might have guessed. And then the rating. There's a number of ways we can do this. We can have. We can have a set of text where weaken display like good, great, the best. Or we can use an integer a number, and I'm gonna use an integer for this one. So to recap, we thought about the pieces of data that we wanted to represent in this case, pens and ink. And then we thought about the information about those objects that we want to collect that . So we came up with the brand name, model, name, color, nip size, date of purchase and anything else that we want to put in here if you have any questions about your own projects, if you're just not sure how to represent a certain piece of data, leave a message in the discussion boards and we'll try to help you out. Another thing that you want to think about when you're thinking about database design is the relationships between your objects. We're going to cover this later in the class, so keep or design handy whether you did this in, like a document on the computer or on paper. Keep it handy because we're going to revisit it later. For now, we're going to keep our design here and head back over to the computer to actually create our data models in code. 10. Implementing Database Models: Now that we have a design in mind, we need to create a model class for our pen. So we're gonna write class pen and then in parentheses were going to do models dot model and cases important. So make sure you have the capital M on the second model. And what this does is, it tells python that are pen class is a subclass of this model class. So Jingo has defined a model with various bits of functionality, and we're gonna use all of those and then add some of our own. Another way to explain what a subclass is is it's telling Python that are pen class is a type of model. So it's a more specific version of this model class, and this is what's called inheritance. It means that your class is inheriting things from a parent class, which is model in this case, and also it has some functionality of its own, and this line made Britain is called a class definition, and we've told Python with the colon at the end that we're gonna put whatever's in this class after this line, and it's gonna know we're done when we stop in denting so each line that we put in here, we need to make sure is indented by four spaces so you can see this blinking cursor is a little bit in four spaces in when we're done with the class. We need to move it back out before we define any other classes or functions. Now, for each of the fields that we decided the pen class would have, we need to give it a variable directly under the class. So the 1st 1 we're going to do is brand name. So we're going to do brand underscore name because variable names cannot have spaces in them and they can't start with numbers. They can have numbers in them, but they can't start with numbers. This one is going to be a care field or character field. I'm gonna give a quick little intro to how Python works with this line. Ah, brand name here is a variable like we've seen briefly before. And the equals sign means that we're gonna put some kind of value into this variable, and the value that we want is a character field. So this bit here models dot character field is our way of creating a new field and storing it in this brand name variable. So character field is defined as a class in the models package, so models dot care field, followed by parentheses, is our way of creating an object from that class. So this is actually going to return a character field object and plop it into that variable called Brands name. If you can understand that concept of getting data from one place and saving it in another place, you can understand most of programming. The last interesting piece here is this. Max length equals 100. So in these parentheses you can pass what are called parameters and that these air just bits of information that you can use to change the object that you get back this year, Max equals 100 tells the character field class that we only want it to be able to hold a text of 100 characters or less, and we're gonna need another field that is identical to hold the model name. And each time you you create one of thes class objects of character field, it's its own object. So each of these air gonna hold their own kind of text, one for the brand name and one for the model name. Now, here is where the fields get a little bit more interesting. Say you have some text, but you only have a certain set of options that you want to be able to go into that very. And so Jingo has what we called choices. You can define options and then assigned those options to the character field or any other type of field. So I'm gonna use this to demonstrate the nib sizes so pens can have different size Nibs, which pretty much determines how thick the Linus that they right and they can be broad, medium find extra fine. Those are the main ones. There's some extra ones, but I'm not gonna include those. And to defying the choices we need to create a collection of values. And each of the values has two components. They have what data is stored in the data mies and what text is presented to the user. So I'm going to start by defining this variable called neb sizes and put an equal sign and then open and close parentheses. And this first set of parentheses is going to be the entire collection. And then for each item or each value, you need another set of parentheses. The first bit of text I put in here is what is going to go in the database. So I'm gonna abbreviate, uh, just a one or two letters for each size, and then I'm gonna put a comma and then another set of text, and that's gonna be what the user sees when they're putting in this information. So B is for broad Emmis for medium F it's refined, and e f is for extra fine. And each piece of the collection needs to be separated with the comma. So there needs to be a comma between the B and broad, and they're also needs to be a comma between the that whole first item be in broad and the second item, which is M and medium. To connect these choices to a character field, we just passed them in as another parameter. So when you define name size as its own field, create a care field and we need both the max length variable, which for this I've only set to to and then we need a comma. After that and then choices equals. And then whatever. We named our collection of choices, which here we named it nib sizes, all in caps. Now this field needs to be defined after we have to find the choices. So if we were to try and move this nip size character field up to live with the other ones , uh, the code goes in order from top to bottom so it wouldn't have reached the nib sizes variable, and you get an error saying that it wasn't to find so nib sizes needs to be defined first, and then we can use it to create this field. The next field we defined for ourselves was the color field, and since this doesn't depend on any outer variables, we can define it right alongside the other ones. This one's going to be called color, and it is also a character field. But this one I'm going to represent the colors as Hexi decimal color values, which is, um, a certain way of encoding colors. You've probably seen it if you've done any one development before, but this will only require seven characters, so I want to make the max length seven and in the future. If I decide I want a user to be able to select from a certain set of colors, we can also use a choices parameter for this one. For now, I'm just going to leave it as a regular character field. Now I'm using character fields because the information I want to save about these pens fits neatly into those types of fields. If here, working with things, I have a lot of numbers attached to them, say I want to track the price of each pan or the market value or if I want to track a quantity possibly, um, we can also use an interviewer field or a float field, which is like a decimal number rather than an integer. There's all kinds of fields that we can use. I talked briefly about them in the design portion of this video, but you can also look at the Jingle website for a full list and next we are going to branch out a little bit, and the next type of field we're going to create is the date field for the date purchased. So we define our variable date underscore purchased, and we're going to do the same models dot But this time we're going to write date field, and this one doesn't actually need any parameters. So we're just going to open and close the parentheses with nothing inside them. If we save this file now and start up the server, nothing will happen. And this is because the the database needs to know about changes, and Django needs to actually generate the database information based on what's in these model files. So every time we change a field, we need to do what's called a migration where we we re compared this version to the previous version in the database, and Jingo generates the code to apply it to the database, and this only applies to changes in these fields. If we add a function to a model which will do later, we won't need to do a migration because that that is not something that is saved in the database. Before we migrate, however, we need to tell our project that we're including this app in the project. So we've created this app, but it's just kind of floating around by itself, so we need to go into the setting stop I and this will be new to you if you did not change the database settings in the optional lesson, but pretty much there's a lot of generated code in here that you don't need to worry about . We're going to find the section called Installed APS And in order to include our new app, we need to do the name of the app dot aps and then and include this class which was automatically generated. And it should be the app name and then config both with capital letters on app, name and confess. And this text should be within quotes and it should be separated from the other bits of text in here by a comma. Don't beat yourself up. If you forget commas all the time. It's totally normal and it happens to the best of us. Make sure that you have saved setting Stop I and then we're going to run heights on managed up. I make migrations. This will look at what has changed and print out a little message about what it has generated for you. Now the migration still hasn't been applied. Now we need to do is Python manage Stop! I migrate in this will take the migrations that have been made and apply them to the database. When you run this for the first time, you may seem more print out than you see here because there is an initial migration that's included by default that I ran off screen. But functionally, as long as you run my great at least once, you're not going to see any difference compared to what I am seeing now that we have created our first data model, go into the next lesson to learn how to create objects to put into the database and how to get them back out. 11. Using the Django Shell: Now I'm going to show you how to use a tool called the Shell. If you try to run just a plain python interpreter, you're not gonna be able to work with the jingle models because it's not connected properly . But if you do, python managed a pie shell. It will start a python interpreter, but you will be able to connect to the database and manipulate thes data models without doing any extra work. So now that we have started the shell, the first thing we're gonna do is import our model with the line from Penn Stop models import pen. So from our pens up the model stop, I file. We're importing the pen class and remember that this is all case sensitive and traditionally class names start with a capital letter once we've imported it, we can use that to create a new object of type pen, and we're going to store it in this creatively named variable called Ben. Remember that variable names go on the left than the equal sign, and then the value, which is returned from this pen class function, which is called the constructor, is on the right side of the equals once we've created this object, it doesn't exist in the database yet. We have to put the data into it first. For that, we're gonna use the same method of assigning values two variables for each of the different fields. And the way we do this is to do the variable name that D Penn object is in and then do a dot and then the field name. So pen dot brand name Eagles pilot Penn Don model name equals Metropolitan. Don't forget to put all text values in quotes so that python knows it's a text value and not the name of Variable. Also, be aware that each of these fields was not specifically allowed to be no. So we didn't tell Django that some of these fields may not have data in them, so we do need to fill all of them out before we're allowed to save this object to the database. Now, the character fields are expecting a string of characters or some text, but the date field is expecting an actual date object. So we need to import date time from the date time library and then actually create an object out of it. So here. I've just passed in the year, month, day hours, minutes, seconds, milliseconds for the time I wanted to create. When a user is adding data to the database, the Web page is going to form out this for us. But if we're creating these objects manually, we need to create the date object ourselves. The same thing goes for the nib size. Since we applied choices to this, If we put anything into this value that is not included in the set of choices when we save , it's going to give us an error. But the forms that we put into the website are gonna handle all of this for us doing pen dot save is what actually saves all this data into the data maze as a pen object. If we printed out, we can see that one is the I. D. And you might be thinking this isn't a very useful bit of information to say that it is a pen object and the ideas one. So what we're gonna do is actually add some code that will print out more useful text whenever we print out a pen object. There is a concept in python of things called magic methods. And these are always surrounded by two underscores And this magic method underscore underscore str underscore. Underscore is the string with it. So when this is called automatically, it will convert this object to a string of characters or some text. What we want to do is override it. So if we put at the bottom of our pen model and we want this to be indented so it is included in the class D E f is how we define a function. And then we put the magic method name parentheses and then because this is a classmethod, it gets a reference to itself. We're gonna use this reference to itself to get all the values that we want to print out. And don't forget to define the function. We need a colon at the end of the function definition, and then we do need to in Dent four more spaces for every line of code. That is part of this function definition, and this function is supposed to return a string or return some text, and it doesn't really need to do anything else. So we're just going to start right off the bat with return and then a space. And then whatever we put after that is the text, it's going to return to whatever called this method to get this object as a string in order to access the fields on the object we're trying to convert into text we need to use this self self is a variable that contains everything in the class, so it's going to have the color which we're going to grab first. And then in order to build up the string, we're just going to use a plus and then at a little space in quotes and a little word of warning. If you are trying to add a variable that is a number, for example, of its an integer, it's gonna yell at you because it doesn't know how to add text to a number. So if you want to print out a number and add it to some other texts like we're doing here, you're gonna need to cast it to a string, and the way we're going to do this is actually call this magic method on that object manually by doing str parentheses and putting the variable inside those parentheses. So now When we print a pen, it's gonna do the color space, the brand name, another space and then the model name. You can build up this string however you want, so that when you're printing out items that you get from your database, it is something that is usable to you. Now, instead of creating a new pen, I'm going to show you how to grab an existing pen from the database. So we're going to import our pen class one more time because this is a new instance off the shell here that we've just started up and now we're getting into some of the stuff that Jingo does for us. So on the Penn class, they have included this objects variable that will allow us to query all of the pen objects at once. So but I'm going to do is grab a variable to put the result in, and I'm going to do pen and this is on the class, so pen with a capital p dot objects dot all with parentheses, and this is a function that will grab all of the pen objects. This will actually return a list of all the objects. I only want one of them, so I'm going to write dot first with parentheses. And this introduces a topic called Chaining, where we're running a function on the results of a previous function. So dot all grabs all the objects and then dot first grabs the first of that set of all objects that were returned. If we were to you, just do pen dot First, we will get an error. Because PEN does not have any kind of method definition to get the first object, it doesn't understand what that is. On the other hand, if we were to write pen dot objects dot first, that does have a definition, so that would be a shortcut that we could use. All this is to demonstrate that you should know what the methods you're calling are returning to you. So you know what is a valid thing to do with that object? And we can see it has printed out the color, the brand and the model, just like we told it to. Another way we can get information from the database is bypassing parameters to a get query . The important thing to know about get is that it can only return one thing. So if you give it a parameter that will return multiple things, it will yell at you and throwing error. For example, if we do pen dot objects don't get and then pass in the parameter brand name equals, and then a string of text for whatever brand we want to look for right now, this will work because there is only one pen in here and there's only one brand. Now what happens if we do a get query on something that is not in the database? If we pass in a brand name that does not exist, what happens? As you might guess, it gets angry and throws an error. These errors are actually fairly useful. And if you were to Google this, it would give you the exact answer to how to fix it. So part of programming is being able to read the error messages and find the resource is that you need to fix it Now. We've just finished implementing this pen model and now is as good a time as any to commit our changes. Keep your eye out for parts and development like this, where you have buttoned up one piece and you're ready to start another piece and start making commits to save your progress as you go. I have done a get status identified that all of these things are things I want to keep so I can add them with East are short cut and commit them. While I'm here, I want to point out that the migrations we did are actually saved in the files. This is so that if you're running multiple databases for a certain project, you can apply these migrations to all of them without having to regenerate them one by one . It also keeps a record of what you migrated and when. And this is another case where keeping track of things you've done is an easy way to roll back certain changes. If you find that you have a need for that that wraps up this lesson in the next lesson, we are going to start. Actually creating our first page now would also be a good time to create a skill share project for this class so you can share with everyone else what your data models look like . And what your idea for the website ISS 12. Creating our First Page: Now we're going to start creating our first page. The first thing we're going to do is tell Django where on the website this page is going to be. You probably already know that a U R l is a path to a webpage. So link. And if we want this page still live on our website, we need to give it a place on that website. We need to give it a Europe. When we generated the project, it created a file called You Are l stop, I So we're gonna open up that file first. And this is the route Ural config. Which means whenever jingles trying to figure out where a u r l is pointing it checks here . First, there are two ways to remember which you are old. Stop. I is thes route one or the one that checks first. The first way is to just know that FP tracker is our project folder, not an app folder. So it's kind of the top level. And the other way is to actually check your setting Stop I for which folder is defined as the root Ural Config. And in this generated file, you'll see some instructions for how to include APP specific. Your else, which is what we're gonna do next. First will need to create a urals dot pie in our APP folder. So in the Pens folder and the way Jingo builds you morals is it tries to match patterns one by one so you'll have a list of pattern and will try the 1st 1 If it doesn't match, it will try the next one. And when it reaches a pattern that matches the U, our relatives trying to direct the user to it will execute whichever view is assigned to that pattern. The very first thing we'll need to do is import path from django dot you. RL's This is going to represent our connection between the pattern and the view that we want to execute and just like when we're using the terminal. A dot is a short cut for the current directory. So this second import line will import the views module from the current directory, and our list of patterns is going to be a python list, which is just a series of items between brackets and we're gonna store that in a variable Ural patterns equals we're gonna open our brackets and all the girls are going to go in between them each separated by a comma. But before we can hook up any you URLs to our views, we need to actually create a view. So we're gonna move to view Stop I and of you is just a function you can give it any name you want and it accepts a request parameter they could accept other ones, but we're not quite there yet. And the function will run. It will go through all its steps, and it will return what the Web browser is supposed to display. So some kind of http response and we're going to talk about how to create those as well. When defining the function in Python, we start with D f the name and then between parentheses, we put all our parameters. We just have one right now. But if there's more than one, they would be separated by commas, and then we have a colon at the end, just like a class definition. Also like a class definition, we need to in dent all the lines inside the function so that python knows which lines of code are included in that function. And then where the next functions starts, we will go back out and stop inventing. And inside the views is where all of your processing and you're querying is gonna happen. Some things that you might do in a view, grab objects from the deed. Abi's sort them filter, then change them. Delete them. You may calculate some kind of value for the user. Pretty much everything that your website actually does is going to happen inside of a view . And for this 1st 1 we're gonna make it really simple. We're not actually going to do anything in this function. We're just going to return. Ah, brand new http Response Object. So we need to import this type of object http response from django dot http so that we can use it and then right in our return statement, we're going to do return. Http response and then this is a constructor. So we're creating a new object and we're just going to give it some text. It doesn't matter what text you put in here and just make sure you put it in quotes. And if you're familiar with HTML, which will talk about a little bit later, you can even put HTML tags directly in here, and then they'll be passed to the Web browser just like a regular website. Now that we have our view, we can create a pattern to connect to it. And this first pattern is going to be really simple because it's just an empty string. And this means that after local host Colin 8000 or whatever the domain name is, if this is out on the Internet somewhere, there's not gonna be anything after it. So it's just gonna be an empty string for the pattern. We're going to give it this views dot index toe. Tell it we want to run the index view, and then we can give it a name as well to help reference this pattern from the templates that we're going to talk about in a little bit. And like all of our other lists and collections of values, this does need to be separated from other patterns with a comma, and Jingo has all the instructions right here. So we're just gonna follow the next instruction, which is to import the include module, and it's from the same place as path so we can just add a comma after path and put it right after it. And we're going to do the same thing that we did before where we put a pattern here, except this pattern is going to be added to whatever patterns are actually in the pen start Urals file. So say we put pens slash into this path instead of leaving it empty strength. What that would do is mean that all the Urals in the pens, your old stuff pie has toe have that initial peace before it in order to direct it to the that girl. Once we have our your old set up, we can run the server and then we actually do see an error. I wanted to show what the's errors look like and how you can kind of read them. So here it tells us which file this errors in in which line it's on. So we're going to go to Ah, your old stop I in a p tracker line 21 I can see the problem. We forgot the common here. Once we fix it and save, we can go back to our server and see that it's working just fine. And if we go to our Web browser, Goto local host Colon 8000 we can see that the page is whatever we put in that http response. So I just put some text. So all we get on this page is some text. Now that we have our Urals, in our view, all working together, our next lesson is going to be about template it's and how he can make thes Web pages a little bit more interesting. 13. Building Page Templates: before we get started creating a template, I want to talk about what they are in basic terms. A template is some very basic code explaining what a Web page should look like. And then parts of that code, when it's shown to the user, is filled in with information to make it a little bit more specific. And a template is mostly HTML. So if you've ever done any kind of Web development, you know what HTML is. We'll talk a little bit more about it once we get into the template file. But as an overview, it's just a list of tags that tell the Web browser what kind of elements to put on a page and where to put them. So you have different types of text elements, image elements, things like tables or dibs, that kind of section off the page into different areas. And so a template is an HTML document, but we're going to extend it with Ringo's template ing language, and that's going to allow us to put data into this template that is not going to be the same every time we go to a page so we can create a template for, say, a page that shows information about a specific pen. But we don't need to create a separate page in advance for each type of pen. We can just plug in the details about whatever pen we want to show before the user ever sees it. And since we aren't doing any querying in the template, this keeps the structure of a project very clean. We're doing all of our queries in the views, and the templates themselves are just a definition of what the page looks like. And keeping things separate like this and not mixing it all together makes changes to the website improvements and just overall development much easier to keep track of as a developer. So the first thing we're gonna do is create a template directory inside our APP folder. So this is the Pens folder. And then in that folder, we're going to create a file called index dot html. This is gonna be our home page. You can call the file whatever you want. Ah, but traditionally in Web development, the home page is called the Index. Now we're going to start writing HTML, which isn't technically a programming language. It's a markup language, which means it doesn't process anything. It doesn't change any values. It just describes something Each word, uh, contained within these triangle shaped brackets is called a tag. In most tags, you need a starting tag and then an ending tag. Where you have the same thing is this starting tag, but with a slash in front of the word I've listed here, the four necessary tags that you need on an HTML page and they should be roughly in this structure, so it should have HTML on the outside of all the other tags and then head should contain the title time. And then the body tag is where you're going to put most of the content on the page. And if you watch what I'm typing in, you can see I'm adding some meta tags. These basically tell search engines and Web browsers what your page is about. They are not critical for your pages to function properly, but they are helpful toe learn about. If you want to get into Web development, I'm not going to cover them in great detail in this class. So for now, you can either include the ones that I've included, or just leave them out and then do some research. If you're curious about what they do specifically and what types of values you can put into them once we get to the body that we're gonna put things that the user is actually going to see when they go to this page, I'm going to demonstrate some basic HTML tags here. The 1st 1 is just P and the stands for paragraph. This is gonna hold kind of blocks of tax, just plain text that we want to display to the user. And I'm actually going to change this 1st 1 to an H two, which is a type of header tag. There's numbers one through six, with one being the largest, most prominent header and six being the smallest. So in the age, one would be a very large header. I don't quite want this header to be that big, so I'm using an age two, and then each six is barely discernible from plain text because it's very kind of insignificant compared to the other types of headers. We can include as many of each type of tag as we want, with the exception of the four main ones that I mentioned at the beginning. All of these content tags you can use as you need them so I can add a whole bunch of paragraph tags on here. And most tags have optional attributes on them, so I'm gonna put one in here. It's an A for Angkor and these air links essentially. So the a tag has an attribute called, uh h ref or ref. If you just want to read it out loud like that. And in that attribute, we do equals and then quotes, and then we're gonna put the path toe where this link should go in that attributes. So this is very similar to creating variables and python, with the big exception that the attributes on a tag are already defined. You can't change the names of them or the Web browser won't know what to do with it. So this always has to be called H ref in orderto work, and each type of tag has its own set of attributes that it can have. Now we're not going to put any data into this template. We're going to do that in a bit, Um, but let's say this template is done. This is what we want to show to the user. How do we tell the view that this template is the one that should be shown? So first thing, we're going to go back to our views. Stop. I inside this APP folder Right now, we're using a basic http response. And Jingo has a little bit of a shortcut for rendering templates to create an http response . So we don't need this import anymore, cause we're going to remove the http response and we're going to use render, which was imported by default when we generated all these files. So render will actually create an http response out of this template and some data that we're going to give it and it takes three parameters. We're gonna write return, render parentheses, requests. We're just gonna pass along the request variable that the view receives as a parameter. We're just gonna pass that right along. The 2nd 1 is going to be the file name of the template just index that html and then we're just gonna do some empty curly brackets. We're gonna fill this in later. This is the data that's going to be sent into the template on. Now we're gonna use the template ing language to to extend our HTML. But we're going to do that in the next lesson. So for now, this should be enough that if we reload our page we should see are very basic template that we've just created. And you can go back to your HTML, change it and then save and refresh, and you should be able to see those changes and get this page looking. However you want it to look. And in the next lesson, we're gonna learn how to add images to our web page and also how to add styling. So we're gonna make this look a little bit less trap. 14. Loading Static Files: The first thing to understand about images and CSS files and JavaScript files is that they're considered a static files. So they're not processed by Jingo. They're just loaded in and used the way they are. So we call them static Files and Jingo handles the's in a very specific way. The first thing we need is a static folder. Um, and we're gonna make this right underneath the very top level project folder. So so that it sits at the same level as our FB tracker and pens folders. And inside the static folder, we're going to create another folder, Toehold. Just our images. And then leader will have separate folders for CSS and for job script grab an image to use . You don't have to keep this in your final site, but I want to work through how to set up static files so we know it's working. I just have a picture of pens that I took. And now in our template, we're gonna create something called a template tag. And this is how Jingo inserts information into the templates when they are runned erred by the view. And what we're gonna do is do a curly bracket and a percent sign, and we're gonna close it with a percent sign in the curly bracket. And the text we're gonna put in here is just load static. You need to include this tag in any template that uses static files because otherwise Jingo isn't going toe, load them up and make them accessible to the temple. Now we're going to create an image element in HTML. But instead of putting a path to the image in the source attributes, we're gonna put another template tag in here. We're going to do another curly bracket percent static, and then we're gonna put in quotes of the path inside the static folder to the file. So since the Images folder is inside the static folder, we just do images slash pens J pic, and then we close it with another percent and curly bracket. And when this is rendered, this entire tag is going to be replaced with the path. So we do need to put that tag inside quotes so that we have a valid attributes definition here. And before we do anything else, we need to go into our setting stop high file and by default, the static folder in the place that we've made. It is the's static, your l. But on Windows, we need to define another variable in order to make the static files actually work. So just add a variable called static files underscore D. I. R. S and this is all caps equals. And then what we're doing here is joining the's static path to nothing. Basically. So this is just a line of code that we need in order to tell Jingo which directories are static files are in, and this seems to be specific to Windows, but it won't hurt anything to add this even if you are not using Windows. No, If we go back to our running Web page and refresh, we will see our image shown here at the bottom where we put it. The next thing we're going to talk about is CSS or cascading style sheets. This is a very simple language that styles elements on a Web page. You can start from the ground up and just kind of define your own CSS. But a really easy waiting it started is to use a CSS framework and these are files or sets of files that people have created and offered up to the Internet toe. Let love developers create a foundation for their styling before they start adding specifics. The one that I'm going to recommend specifically because it is very, very simple is called Skeleton CSS, and you can find information about it at kept skeleton dot com. If you scroll down, it will show you what it offers. The most useful thing to look at is this grid. Um, CSS can be difficult to align elements with each other and place things in certain places, and having a framework that uses a grid or some other kind of policeman tool is very useful . So we're just going to download skeleton, CIA says from the link at the very top. And this will give you a zip folder that you should unzip. And then inside there's gonna be two files back in our project structure here, create a CSS folder inside our static folder and drop the files that it gave you right into that CSS folder. He should have one called Normalized at CSS and one called skeleton dot CSS. Any time we want to use CSS in a template, we need to add a reference to it. And the best place to do that is in between the head tags and the tank for including CSS is just going to be link Rehl equals style sheets. And then we're gonna add the past in a h ref attributes and we're going to use the same static tag that we use before. And then the path is gonna be CSS slash normalized at CSS for this 1st 1 And then we can copy this whole line and hosted again and then change normalized to skeleton so that we're linking both of our CSS files and it is important that normalize is loaded first. Ah, and then skeleton should be loaded. Second save and go back to our webpage. If we reload, we see a slight difference. Part of this is the normalized tool kind of making kind of evening out. The elements so there could be placed were predictably and part of it is that thief font is different. Now that we have this loaded up, we can use the CSS classes that they described on their website to rearrange some of these elements, using the grid and using the other tools that they offer in the skeleton CSS. A lot of CSS frameworks that use a grid recommend using dibs to kind of separate the pieces of your page. And so I'm going to create a div. The class of container and a class is just an attribute that allows you to. It's a very common way of applying styles. Two elements and this container class is just going to center and kind of organize all of our body text and then creating a tive inside this DIV. We're going to separate our information into rows and columns to work with their grid that they offer in their framework. And if you really want to have full control over how these elements are positioned, I would recommend reading through the skeleton, See it, says website, and seeing how they recommend using all their tools. The brief overview is that you define a row and then you can have columns within that row, and the grin is designed to have 12 theoretical columns. So as one example, a three column DIV would be about 1/4 of the width of the page. So I have a div with class row and then a div inside that one with the class three space columns and skeleton is going to handle this all for us and position everything correctly just to demonstrate how the grid works. I'm gonna add a second div with the class nine columns, and that's gonna hold our image. So our image should be about three times as large as our column with the text in it. This is why frameworks like this are very powerful. You can pretty much design your page to look like anything you want. It gives developers control over where things are on the page without making them to find their own specific CSS rules to position things based on the page with or even going so far as to define the wit by pixels. They also offer some nice, simple styles for things like buttons and tables and demonstrate. I'm just gonna add an input type equals button, and this is going to put a button on our page. The value attributes tells it which text to display, and I'm going to give one of thes the class button dash primary, which listed on the skeleton CSS website, tells me that that's the class to give the buttons a more prominent look. And if we refresh, weaken, see both of our buttons here and they look simple, but they do look pretty nice. Now that we have static files working, we're gonna move next onto getting some data into our templates. Don't worry too much about getting your pages styled just right yet, because after we get some data into our templates, I'm going to talk about adding custom styles on top of the skeleton CSS. So if you're really itching to get to styling your website, you can either jump ahead and come back or just power through the next lesson to get to the good stuff. Either way, I'll see you in the next lesson. 15. Dynamic Data in a Template: Now that we have our templates set up and we have some basic styling on our page, we want to start putting some data into the template. Since this is the home page, I think we'll win a list of all the pens that they use your owns right now. The temple. It doesn't have access to any data, so we need to change the view so that it queries the database for what it needs and passes it along to the template in the render function that we've been using. So opened the views. Stop I and we'll have a look at our index view. I know we're passing in empty curly braces to the render function as the third parameter. Instead of these empty currently braces, we want to actually pass it some data. The first thing we need to do if we want to use data from our database just like we did in the shell, is that we have to import the pen class from the models file. So from models import pen and then again like we did in the shell, we just want to do pen with a capital P cause we're doing this on the class in the on a variable called pen. Wanna do pen? Got objects dot all and this is going to give us a list just like it did before. Of all the pens in the database, we're gonna put this in a variable that I'm calling all underscore pens. Now we want to create something called Dictionary the hold, all our data. The past of the template. A dictionary is a type of python object to find with curly brackets. And then inside these curly brackets, there could be any number of dictionary entries. A gentry has a key, which is a string, which means it's text and needs to be inside quotes. And then there's a colon after the key and then a value. The value can be any type, so it doesn't have to be a string. We can put text numbers, python objects or even another dictionary as a value to an injury in the dictionary. And another thing is that one dictionary can hold different types of values inside it. So this dictionary doesn't have toe on Lee have text in. It doesn't have to only have numbers in it. We can have one entry in this dictionary where the value is a string, we can have one entry where the value is a number and we can have one injury where the value is just a python object of some kind. For now, we want to create an entry called pen Underscore list, and we're gonna put the value we got back from our query into this entry. So we're gonna do pen underscore list in quotes, a colon and then the variable that we put the pens into, which was called all underscore pens just to demonstrate different types of variables. I'm also going to put an entry in here called Page Underscore Title. And for this I'm just going to give it some text. I'll put fountain pen collection. I can also add a number. Like I said, I can add any type of objects to be the value of a dictionary entry. Now that we have this dictionary with the data we want to send to the template and we put it into this variable called context, we need to put this into the render function. So we're just going to replace this empty dictionary with our context. Variable if we reload our template now, nothing will happen. This is because the template has access to this context data, but it isn't doing anything with it. If we open the template, which was index dot html, we can start actually using this data using jingles template in language. We use this a little bit in our static files lesson, and we're gonna do a little bit more with it today. The template tags for accessing the context data are these variables is a little bit different than before. Instead of using the currently bracket and then the percent sign, we're just gonna use double curly brackets as our first example if we want to replace the text between these H two tags or header tags with the page title in between them, we take out the text that was already in there, and we do to curly brackets Page Underscore title and then to closing curly brackets. It's very important that the text we put in here page underscore title matches, the key of the dictionary injury that we set up. In our view, nothing too terrible will happen if we mess this up. Jingo fails silently with these variables so if it can't find anything called Page Underscore title, it will just display nothing. But then you have the problem where your template isn't doing what you're expecting it to do. So if you're working on a template and it doesn't quite look right, go through in double check that you have spelled the variable names correctly, and they match what was in the dictionary that you passed into the template. If we save and reload our template again, we'll see that the title was walked incorrectly. Weaken. See that our pages now titled Fountain Pen Collection, Just like we put in the view, displaying a list of items is a little bit different because it requires the use of another built in template tag just like thes static tag that we use before we are going to use the percent sign for this one you're gonna do opening bracket percent and then we're gonna write four, and I'm going to talk about this one a little bit first what this template tag is going to do. It's going to iterated or loop through a collection of items, so we are going toe loop through all of the pens in our pen list that we passed into this template. The basic pattern for using this template tag is four item in a list where item is a temporary name that each object gets when we're looping through it. So say there's three pens in our pen list the first time it loops through. It's gonna put the value for the first pen in that item variable. Second time it's gonna put the second pen in that item variable and loop through again. And then the 3rd 1 it will be the value of the third pen. We can use item or we can give it a different name. This name is is entirely up to us. As we're creating the template, however, the list text needs to match a list variable that we passed into the template. So in our case, it will be pen underscore list for my four tag. I did four pen in pen underscore list and the Jingo template tags don't care about indentation or a white space like python does. So we need a way to tell it when the four loop is done. And for this, we're just gonna do curly bracket or sent sign and for all one word and then another percent sign and curly bracket. So each time we have another item in this list, it's gonna paste into the page Everything between the four tag and the end for tag. No. Like I said before, as this four loop is stepping through all the items in this list, it's gonna put the value of each item into this temporary variable that I called pen. So inside this loop, weaken, do whatever we want with it. For now, I'm just going to use thes double curly brackets to print out at Penn Objects. And then I'm gonna put a little break tag between them just to space them out. Now, if we say this and refresh your page, we can see that the one pen we put in there by using the shell is printed out. If there were other pence and will add more pens later, we'll see them all printed out all in a row. Now let's go back to our template. What else can we do with these data variables? Besides printing them out, we can use another built in jingle feature called Filters. Let's try one called the length filter. If we take our pen list, if we do double brackets, pen underscore list and then a bar. So this is Ah, this is a key not typically used by people who aren't programmers. It's above the enter key on most key words. It's a long, vertical line, so we do pen underscore list are and then this length, no quotes or anything and what this is going to do. Instead of printing out the list, it's going to print out the length of the list, so it's going to take whatever is on the left side of that bar and pass it into the function on the right. And Jingo has a number of these built in functions. Length is just one of them, and if you go to the Jingle website, you can read all about the different filters that they have. One word of caution is that you should not do too much computation in the templates. If you find that you're using a lot of filters to kind of change things around and get them looking the way you want them to look, take a step back and think about if he should be doing some calculation in the view on this data. Before you pass it to the template, doing too much in your tablets can slow down your page a little bit. So we want to avoid doing a lot of stuff and mostly just used these filters for formatting data to look a certain way. So the template should be focused on presenting data, and the view should be focused on collecting the data and processing it. Before we move on, I want to organize the template a little bit and put these pens into a table. And in doing so, I'm going to show you another feature of the Django template ING language as a reminder. The for Loop will repeat everything between the four and enforce for each item in the list . So we want to create our table tag above the four loop so before the four loop starts and you want to close the table tag after the end four attack. If I want my table toe, have a header, which I do that's gonna go above the four tag as well because we don't want to create a new header for each item in the list inside the for loop. What we want to do is create a new table row, just tr And then for each field, we want to create a T. D or a data cell. And this is the part that I wanted to show you, which is accessing fields on the objects past Amar template using this dot operator. So just like in python, if we have a variable, begin do pen dot or in underscore name and the template can actually access the brand name from this pen object. So I'm gonna use the stock operator to fill in the brand name, model, name, color and nip size in all of these table cells when we use template tags, It doesn't just print text onto the page, but it actually swamps in the text into the file so we can use this to put text into attributes. If I do this style attributes, I can actually use Jingo to set the color value right there in the page. I noticed later, I did make a little typo here, color in terms of styling refers to the text color. What I really wanted was background color, so I'm changing a here to background dash color. I also went into the shell and created a second pen because I realized that I had set the first pens colored toe white so you couldn't actually see the cell color change. Um, because it was on a white background. So now if we refresh the template weaken, see the pen color displayed as a style attributes on this table cell and then all the other information printed into each cell of the table. And no, since I have two pens in my database, you can see that they both are looped through with this four tag, just a Z you would expect creating a new row for each pen. Now we have data displayed from our database on our website before moving on. I'm going to do a little bit more tidying up and just remove this big image and this extra column. So our table takes up the whole middle of the screen, and the pens are the focus of this page. This is also a good time to commit our changes. So just like always, we're going to do get status, make sure all these changes look right in that we don't have any changes that we made by accident or didn't plan to include in this commit. Then we're going to get add all the files to the committee and then commit with a useful message, I'm gonna put added index, view and template to show list of all pens and our next listen, we're going to take a moment to talk about adding custom styling to your page so you can really make your home page in your overall website. Look the way you want it to. 16. Adding Custom Styles to a Page: Now that we have some Dina, we're gonna work on styling our website to make it a little bit more our own. The skeleton CSS framework is fine, but most websites have a little bit more personality, adding custom CSS. On top of the framework is how we use all the nice functionality that skeleton has and add our own unique look. We have the CSS Code four skeleton, but we don't want to go in and change it directly. Part of this is because, says says frameworks are usually minimized, which means all the white spaces removed and everything is kind of stuffed onto one line. But also there's a better way that's gonna keep things much cleaner in our CSS folder, along with skeleton and Normalized. We're going to create a new file called main dot CSS. You can call this file anything you want, but Main is a nice general option for a simple website like we have. The way that CSS works is that you start with a selector to tell the CSS what types of elements you want to give a specific style, too. The selector can just be the element name a class name an element i d. They're also more complicated selectors that combine different things together. And then after we have a selector, I'm just gonna use body, which is the body element. You put a pair of curly brackets, and inside those brackets, we're gonna put all their styling information, keeping things simple. First, let's just make the background color something that's not white, something more interesting. Finding a color picker you like is a good idea If you're gonna be doing a lot of Web site design, I just Googled color picker and found the 1st 1 that I think it's easy to use. And for one design, we're gonna use the Hexi decimal color values that I talked briefly about before. Uh, if you're color picker doesn't show you the Hexi decimal value I'd recommend finding one that does. If it's not labeled hex, you'll know it's Hexi decimal because it will have a hash tag or an octopus thorpe or a pound sign. Whatever you call that symbol is gonna be in front of it. And then it's going to be a combination of letters and numbers. I want my website toe have a soft, muted blue colors the background. So I'm just going to drag the sliders around on this color picker until I get something I like. And then I'm going to copy the hex value and paste it into my CSS. So to set the background color on your stoop background colon and then the color. And we do need a semi colon at the end of each piece of this style. In order to use the CSS and our template, we do need to include the file just like we did with normal eyes and skeleton dot CSS. You can copy that and just replace the path part, or you can type it in. If you want to help yourself remember how to do all this. It's important that our CSS is loaded last because we wanted toe overwrite parts of the skeleton dot CSS. If we put it first, ours is going to be loaded first and then skeletons gonna load on top of it, overriding our values if we save and reload. This looks fine, but I do want the middle of the page to still be white in just the edges of the background . To be this blue color. We already have a development we can use called container. So we're gonna overwrite our first class style for classes. If we want to select a class, we put a dot in front of the class name so Doc Container will select all elements with the class container and then inside of these brackets, I wanted to be white, so I put the background color as hashtag and then six efs is the exit decimal color for white. You can use a color picker to grab it if you want, but that's an easy one to remember. And then I'm gonna add some other styles in here. If you're really interested in website design, I would recommend looking up like a quick cheat sheet about CSS styles. I'm gonna explain the ones I'm using, but this is by no means a comprehensive lesson on CSS. The margin attributes is going to adjust how far away the element is from the element that it in. So this is going to put our container div 50 pixels from the top and 50 pixels from the bottom of the body. And then I'm also going to use the padding attributes and the padding does something similar. It separates the elements inside the selected element from it. So all of the elements inside this container div are gonna be shifted away from the edges a little bit. And all of these are a number and then p x to symbolize that thes are 50 pixels. Ah, there are other values you can use. There are some you can use percentages of page with. For some attributes like Imagine there's a lot to CSS. So if you want to do something that I'm not doing here, you can do a quick Google search or you can definitely find a class on skill share that gives them more comprehensive. Look at CSS as one last tip. Let's say they want to override a primary button style that skeleton uses. We don't want to override everything, just the button color. If we use the class button dash primary, we find that it doesn't quite do everything we want it to. This is where we would want to use the inspector in our Web browser to figure out why. Open the debug tools in your browser. I'm using Firefox, so the shortcut is control shift. I, I believe, for chrome and his control shift. See using the inspector, You can look at the html of a Web page, any Web page and also click on elements to get more information about them. There is a style section in the Inspector, and this shows you all the styles that air on an element and which selectors they are being selected by. If you're trying to override a style and it isn't working, check the inspector to see why that might be. As a rule, more specific selectors are preferred over more generic ones. So the reason this button class isn't working is because skeleton uses a button primary class that also specifies that it's an input type submit. So if we add this input type, submit selector to our button primary selector. It becomes more specific than the skeleton one and correctly overrides it. Have some fun styling your website make you look exactly how you want it to look. Play with colors. Pinterest is a good place to find color combinations that look nice together that you can use for your website. And don't forget when you have something you really like to post a screenshot into your project, so we can all see what you've come up with. Have a look at the project's other students, have done as well and share any CSS tips or cool styling ideas that you might have in the next lesson. We're gonna create our second page and start setting up our website so users can actually put in data so we won't have to use the shell anymore when we want to create new objects. 17. Using Forms to Create Objects: Now we're ready to let the user put data into our website. We want them to be able to create new pens without using the Jingo shell. So how do we do it? The answer is by using a form, you've definitely used a form on a website before. They're just collections of input elements like text boxes, buttons, drop down menus, check boxes and so on that air, then submitted to the website to collect some kind of information. When signing up for skill share, you probably used a form to create your account. Jingo comes with a really handy feature where it can take a data model and generate a form for that data model to create and edit database objects so we don't have to build the forms from scratch. First, we need to create a form class for Penn object to tell Jingo what we want this form toe have in it. We're going to create our pen form right in models dot pie. Some people like to separate their forms into their own file, but for such a simple website, I don't think that's necessary. In this case. The first thing we'll need to do is import model form from jingo dot forms. There are two different types of forms. A regular old form and a model form. Regular forms are when you need to collect data that isn't mapped to a model. If you just need to collect information and then do something with it but don't need to save it into a matching model in your database, you would use a regular form. We want to create a pen object to store directly in our database, so we're gonna use model form. The class will mostly be created by Jingo, but we do need to set it up. So we're going to create a form class class Penn form, and it's going to be a subclass of model forms. So that goes in our parentheses and then a colon, and we're going to do something a little bit strange here. We're going to define a class inside this class. So in Dent, four Spaces type class Meda with a Capital M and Colin no parentheses for this one. Now this medical ask is how Django gets information about thes model forms. So inside this meta class in Den four more times and we're gonna tell Jingo which model this class should follow, and we're gonna do model equals pen. Since we're in the same file as the pen model, we don't need to import this specifically because it's right there. But we do need to make sure that the form is defined in this file below the pen class form class is defined. First, the pen class will not exist yet. The next thing we're going to do is tell it which fields to include in the form. We want to include all of them. So we're gonna use a short cut. Fields equals underscore, underscore. All underscore, underscore. And that is a string. So put that in quotes. And this is a shortcut that just tells Jingo we want all the fields to be in this form once retail. Jingo, what? We want to be in this form. Jenga will do the rest. Now we're going to go into our view in our views dot pie. And we're going to create this view called Edit Underscore Pen. We need to import this pen form class, and it's run the same police as the pen class so we can just add a comma and inside this view, we're going to create a form using that class, and we're gonna put it into a variable just called form. So form equals Penn form with a capital P in the capital and then just some parentheses because this doesn't need any parameters. Right now, our view is gonna be very simple. We're just going to create this form and pass it to the template. So under here, we're going to return our render. Doug, you did with the index Return render request, and then we don't have a template yet, but I know that I'm going to name it at it. Underscore pen dot html And then I'm just going to create the dictionary right here because there's only one thing in it. So I'm going to do an open, curly bracket form and quotes, and I'm going to give it that form variable as a value. You can also define your context variable like usual if you if you prefer to organize things that way, but both of these methods will work just the same. Next, I'm going to create a template, and there are ways with Jingo to create a sort of base template and then build on that so all of your pages look roughly the same, but that's a little bit more advanced than this class needs to go into. So what I'm gonna do is copy the code out of our index dot html and I'm gonna paste it into a new file in the templates folder called Edit Underscore pen dot html The name that we gave our view. I'm gonna delete everything inside that container did. And we're just going to replace that with the things we need for our at a pen template while we're going to put in this container. Dead is really very simple. We're going to start by just printing out this form variable. So the double curly brackets with form inside, which is what we called the form variable in our dictionary that we passed to the template and we're going to see what this looks like first before we can actually look at this template on her website. We do need to give it a u R l. So we're going to go into your el stop I in our pens up and we're gonna add a new pattern here and this is actually the first girl were using That isn't blank. So I just want to be extra clear on what this means. Oliver, you are girls were assuming have the domain name, which, in our case, is local host Colon 8000. And then the girl after that has to match whatever's in this pattern string. So we want this to be at local host colon 8000 slash pens slash at. So what we're gonna do is create a path, and the text we're gonna put in here is pens, slash Add the view is going to be views dot edit underscore pen, and then we're going to give this a name, which is ad underscore pen. Now, we don't have any buttons linked to this u R l yet. So we're just gonna type into the Web browser, Local host Colon, 1000 slash pens slash ad and it should bring us to our template here. We'll see our form. We'll have text inputs for brand name model date purchased, color a drop down box for the nip size, but will notice a couple things were missing. The first is that our color input is just some a text input we don't want users toe have to type in the hex color code. So the first thing we're going to do is add a color picker for this color field and the other problem is up. There is no hope button to submit this form. So we're going to address both of these issues starting with the color problem. By default, Jingle will assign all of your fields what it thinks is the most appropriate input. So for a character field, that would be a text input. But we don't have to stick with what Django picks. We can override specific fields if we want to. So what we're gonna do is go back into our model form in the meta class, we're gonna use a variable called widgets. So we'll do. Widgets equals and this is a dictionary. So we will do on opening curly bracket in a closed curly bracket. And what you want to put in here as your key is the name of the field. So just put the variable name in in between quotes. So for this, I'll just put color in quotes and then a colon, and then for the value we want to create an object of the type of widget that we want to use instead of what Django is using. And it's actually kind of funny because we do want to use the text input. The only thing is we want to create it with a special attributes. So for this will first need to import text input from jingo dot forms dot widgets. So we can use this in our file. We want to do text input and the parameter we want to give it is a T T. R s, which stands for attributes and then this is also a dictionary. So careful with the brackets and the parentheses, make sure you don't get the mixed up. Then we want to do one entry in this dictionary named Tight, and the value is going to be color as a string. So all this does is tell Django that we want to use a text input element, the type attributes of the element to be color html five, which is the current version that most modern browsers support automatically supports color pickers. All you have to do is create an input where the type is colored. If we save and refresh will see that we have our color picker here. It's not the prettiest color picker on the Internet, but it's fully functional, and it took us just a couple of lines of code to set up. If you want more control over how color options are presented, you can always use choices like I mentioned in the Data models lesson and just give the user a list of choices to select from no onto the issue that there is no button that we can use to submit our form. This is because Jang Go's form and generates only includes Thean puts. We have to actually create the form element and give it a submit button. So we're going to go back to our template and we're going to create a new tag form with an action attribute that is just a pair of empty quotes and then we're gonna put method equals post in quotes. What this is going to do is it's gonna say when this form is submitted, it's gonna post to the empty brackets, which is a short cut for the current page, and it's going to use a post method and we're going to talk more about what that is when we get to our view again. We also need to include something called a See as our F token. This is cross site request forgery token. It's a security measure that basically tells the website that the request for information didn't come from somewhere else. It came from the website, so it's safe and Jingo includes a tag where it's just see SRF underscore token between the brackets with the percent signs and we're gonna put our form next. And then we're going to create a button So it's gonna be input type equals submit. And so that's how we tell it. It's going to submit the form and then ran. The clothes are formed with a tag slash form. Now, if you try to submit this now that it's all set up, you're going to notice that it doesn't actually do anything. When we submitted, it submits to the current page. So it's going to send this to are few. But our view isn't doing anything with this information. So we're gonna go back into our view again, and this is where we're going to use that post method that I mentioned before. So when a webpage just wants to get information, uses a get request and when it wants to put information into the website, uses a post request. There are some other method types, too. But we're not going to cover all of them here. And in order to check the method that was used to activate this view, were actually going to use this request variable. But all our views get that we've been ignoring up until now. We're also going to use our first if statement what an if statement does. Is it checks if something is true or not? And if it is, it executes what's inside the if statement. And you can also add an optional else section where you can put code that will execute if it's not true, so to check if the method was a post or not, we're going to do if request method, and then we're going to do to equal signs in a row. The single equal sign that we've been using is for assigning values to variables, and the double equals is for checking if two things are equal, so it's very important to make sure that you use the double equals when you're checking for equality in a single equals when you're assigning values and we want to check if request stop, method is equal to post in Post should be between quotes and in all caps, and we have a colon at the end, and then we're going to intense. And if the method is equal to post, it's gonna execute everything that is indented after this. If statement and if this is true, we know that we have a form that's being submitted, so we're going to create a form variable. But instead of leaving these parentheses blank were actually going to pass in request dot Post again in all caps. Jingo is built, so it knows how to get the form information out of this post variable. So we don't have to worry about getting each field individually, and it's going to create an object for us using all the information that was submitted in the form. Then we need to do another. If statement IHS form this form variable we just created DOT is underscore valid and then empty parentheses. This is going to check if all the information submitted to us is valid informations. And if this is true, we're going to do another colon and intent again. We're going to do form dot save with two parentheses, and this is what's gonna actually create our object before we're done here. We need to make sure that when a user visits this page without submitting a form, they're going to get that blank form still so at the same level of indentation as the first if statement. So if request that method is equal to post beneath everything, make sure the indentation matches up with that and add else with a colon. This is the code that's gonna execute if the if statement is not true. So if the method is not post, we want to put in our code that creates a blank form and renders the template. Make sure that all the code you want to run if something is true or in the else statement if it's not true, is indented properly and anything you want to run outside of these statements after they're done is not indented. Now, if we return to our form and fill it out, Weakened submitted, it doesn't look like it did anything and all of the and the form still has values in it. But if we go back to our home page, we can see that the pen has been added to the list. Well, we want to do to avoid any confusion is that when the form is submitted, we want to redirect to the home page. And Jingo has a neat shortcut for this. A swell interview. Right after we save the form, we're gonna add a return. One thing to note is that when a return statement is found, the function stops. There it leaves. It returns to whatever called it. So once we return this redirect, we're not going to reach the rest of the coat. But that's what we want. We want to stop running this view, and we want to start running our index viewer home page. So to redirect, we're going to write return, redirect parentheses. Then we're gonna add the name of the view that we want to redirect to for us. That's the index. We can also pass view parameters into this into this redirect. But we don't have any of those yet, so all we need is index, and this is actually a reference to the view function. And it's not a string. It's not a text name of the function, so we don't need the quotes around it. And we do need to import redirect, and it's from the same packages render. So we can just Atacama and imported in the same line. The last thing we're gonna do is go into our index and connect this ad pen button to the ad pen page, and I'm actually going to change this button into a link to make it a little bit easier to work with. So I'm going to take out this input element, and I'm going to replace it with an anchor element. So we're going to do a H ref equals some quotes. And then between this starting anger tag in the closing anchor tag, I'm gonna put add pen. And the cool thing is that if we add our but in primary class, it will. The styling will make it look like a button anyway, but since we did add the the input type equals, submit to our custom styles will need to update that to include anger tags if we want to keep the custom color that we set for now, let's not worry about it. Instead of hard coding the u R L that we want linked thio of the ad pen page, we're going to use a new template. Talk to fill the URL in automatically in our urals dot pie we gave all of the girls names we can use that name in this u R L tag with curly bracket percentage. You are l. And then in quotes the name of the path we wouldn't take. So add underscore. Penn was the name we gave this one and then close it with another percent and curly racket . And when Jingo creates this template, it's gonna fill in the Ural for us. This is also a neat feature because it means we can change the girls. And as long as they have the same name, the template will still nowhere to take the user when they click that button. Now, if we click this ad button, it will take us to our add pen page. We can fill up the form submitted and we are automatically redirected back to the home page . There are a lot of steps here to creating a new form and hooking up the girls and the views . But Jingo gives us a lot of convenient tools, like creating automatic forms and easily redirecting to different pages to make it very easy on us as developers. If we had to create this form by hand and get all the data out individually and then create our database object with raw sequel code, all of this would have taken much longer. In the next lesson, we're gonna explore more ways. Jingo makes development very easy by reusing existing views and templates to edit existing objects in our database. 18. Editing Existing Data Objects: right now, once a pen is in the database, there's no way to change the information. Now. Pens are probably not going to change over time. But you might have designed a website project where the data models do need to be changed. Or maybe you just made a mistake typing the information and you want to fix it. That's why, in this lesson, we're gonna add the ability to edit existing objects. The best part is that we don't need add much, since we can reuse our existing template and our existing view. One thing that Jingo does for us automatically is create I DS for all of our objects. When setting up a database, a programmer usually has to give each object a unique I D called a primary key. But Django does this for us behind the scenes, and this idea is how we're going to identify are objects. We're going to start with our view. So open views, doubt pie and go to the edit underscore pen view. What this view does already is create a form for Penn objects in order to allow editing of existing objects. We just have to tell that form when we're using an object that already exists. And when we're creating something new, the way we're going to do this is by first creating an optional parameter. For this view, that means that sometimes the view will get a value here, and sometimes it won't. And so it means a default value. So in these parentheses, we're gonna put a comma after request and then pen underscore i d equals none with a capital end. What this does is it creates a parameter called pen underscore I D. And of a value isn't passed in for this parameter. It just uses the default one, which is none. None is a special python value that just means there is no value. If you've done other types of programming before, it's pythons version of the Knoll value. Whenever we are editing an existing object, we're gonna give an I D to this view, and when we're creating a new object, we're not going to give it anything. And that's how it's going to know the difference moving down to inside the view function. Remember that we're using this if statement to change how we handle things based on whether the request has been posted or not. So sometimes when this view is called, it's because the form was submitted and that's when the request method his post. And then other times we just want to load the page up. The code we're gonna add here is just before the if formed dot is valid before we actually create our form object. We want to see if the object were changing already exists. So we add, if Penn underscore, I d is not none and then a colon and in Python when we've done it statements before we've used the double equals and that's used for values. But whenever we're talking about comparing something to none, we used the is or is not keywords. Now, if this I d is not none, that means that there's a value in there. So we want to use that I d to get the pen object that we're editing. So we're going to do pen dot objects dot get I d equals pen underscore I d. And we're gonna put this into a variable and this is going to grab the pen object with this . I d. I mentioned before that this get function will error if you give it something where where multiple objects will match. But I ds are guaranteed to be unique. So this get function will never return more than one object. Next we want to create our form object by giving it an extra parameter called instance and we want to set this parameter equal to our pen object that we just grabbed. This will make sure that when the for miss saved it updates existing object rather than creating a new one, we're going to keep the line of code that creates a form for a new object. But we're gonna put it in an else statement so that it only runs when the pen I d is not now a form will be created with an object if we have an I d and without an object. If we don't, we're going to do the same thing further down in the view in the else statement that runs when the request method is not post. So when a form is not submitted just like before, we're going to do if Penn underscore i d is none. We're going to create the form object and this time we don't have a request stop post value . So we're just gonna pass inthe e instance parameter if there is no penalty, so else we just create her blank pen form. You also want to add our pen I d into the data context Variable. Randi was a similar if statement in the template. So we'll just add pen underscore i d equals Penn. Underscore i d. And don't forget to separate entries in this dictionary with the Kama now moving on to our template, the change we're going to make here is just to make the purpose of this page clear to our user. Since this page is used for both adding and editing pens, we don't want them to get confused. So we're going to do an if statement in the template to print out add pen if the pen 90 is empty, if there's no I d and then at it pen if there is one, which means we're editing and existing object the Django template. If statement looks very similar to the python one, so we're going to do and curly bracket percent sign if Penn underscore i d and we're not going to compare this to anything. We're going to use a little shortcut, which is that none automatically evaluates to false. So if we just do if Penn I d, if it has no value in it, it will say false, it's not true. And then if there is value in there, it will be true. So what this is essentially saying is that if there is a pen, I d. We're gonna add whatever's after this into the template. And if there is a penalty, we're gonna put at it pen in age to tags else. And this is just else between the percent sine brackets. We're just going to do add a pen. And this works just like the four tag where we do need an end if tag at the end to tell Jingo where this if statement ends because they don't rely on white space like python does , that's all we really need to do to the template. But you can take this a step further if you want to and customize Thea, add and edit page any way you like. The last thing we need to do before we can use our edit pages to create your all for it. This girl is gonna be a little bit different because we're gonna use a parameter in our girl. What this means is that part of our euro will be passed into the view to tell it what to display. In the early days of Django, the only way to do this was with something called regular expressions. But newer versions, or jingo, have a nice shortcut to create parameters that are numbers or strings of text. To keep things simple, we're gonna use a shortcut for a number to pass in our pen I d through the Europe. It's important to note that for this to work the parameter number in your your l has to be an integer, and it has to be greater than or equal to zero. So no negative numbers, no numbers that are fractional and no numbers that have decimal points. And the idea is that jingle creeds are always positive integers So this is just fine for us . In our euro pattern will put pens slash edit slash and then the next thing we want is the i D to use those shortcut that jingle provides will do this angle bracket, and then i nt Colon which stands for integer. And this is the part that tells jingle that this value should be a number. It should be an integer And then Penn underscore I d is gonna be the name of the parameter And then we close it with another angle bracket the text in here, Penn I d needs to match the text that we set up for parameter in our view, or Jenga is not going to know where to send it. And then we're going to connect this year l two the edit pen view, and we're gonna name the URL at it. Underscore pen. Now, if we go to our website and type in local host Colin 1000 slash pens slash edit slash one. If you've created at least one object, there will be something with a 90 of one. We should see that the edit page for it should see our pen here with all the data filled in . Now, we don't want users to have to memorize the i DS of their pens or whatever object and type them in. So we're gonna use the Ural tag to create some links. Let's open index dot html and scroll down to the part of the template that creates each row for the pens all first at a new column, adding it into the table header and then creating an additional table cell. And in here, I'm going to create an anger tag. So what this is gonna do, is this going to create a link in each row for each pen? And we're gonna use the Ural tag that we've been using for jingles template in language. This time we're going to give it a parameter. So the way to do that is to do the bracket percent, and then you are, well, the name of the girl which is going to be at it underscore pen in quotes and then we're just gonna add are perimeter. In this case, all we have to do is pen dot i d. And what this is gonna dio is look for a you are well named at it pen that accepts one number parameter. If we reload our home page, we should see links added to each pen that say edit. If we click on these, it will take us to the edit page for that pen with the form all filled in. We can make changes, submit them, and then we will see those changes reflected in the list on the index page. Take a moment to commit your changes and get so do your get ad and then do your get commit . And then we can start the next lesson with a clean slate. And the next lesson we're gonna add the ability for the user to delete objects from the database. 19. Deleting Objects from the Database: We're starting to get the hang of this now for each thing we want to add to our website, we follow the same basic process Update any data models if we need Teoh. So far, we haven't had to do this very much. Then we update the views, update the templates and make sure we have Urals pointing in the right place to aunt elite functionality to our website. We don't even need to learn any new skills. We can do this with the skills we already have learned through this class. The first thing we'll need to do is create a view in view. Stop. I called Billy Underscore Pen. This will need the request parameter and then we'll also want another pen. I d parameter. So we know which pen were supposed to be delayed ing. I'm gonna call this pen. Underscore i d insider view. First, we need to get the object that we need to delete. So we'll do pen equals pen dot objects dot get I d equals pen I d. And then using that pen variable. It's really very simple to delete objects. We just have to do pen dot delete with empty parentheses. in that pen will be deleted from the database. If you want to, you can create a template that will kind of confirm deletion of objects. Maybe it says this object has been deleted and shows a link back to the home page. But I'm going to skip that step for the sake of brevity and just redirect from this view back to the index view. This will be done the same way we redirected from the edit pen view. When we do return, Redirect Index. Now, in order to activate this view, we need to link to it from a template. And to do that, we need a your role. Is this starting to feel familiar? Yet in our Euros stop, I will create a New York girl that's similar to the Edit one. But instead we're gonna call it delete pen. So we'll do pens, slash delete slash. And then we're going to use our shortcut here angle bracket I anti colon and then pen underscore i d and bracket. And then views dot delete underscore pen and we're gonna name it to lead underscore, Pet. Don't forget that whatever you name, the parameter in the Ural needs to match what you've called the parameter in the view. Next, we're going to go back into our index dot html template, and we can add another column just like we did for the Edit link. You can get creative here if you like, and you can change. Thes two links on images may be cute little trash can icons or style the delete text to be bold and read in a public facing website. You'll also want Toe Verify that a user really wants to delete something when they click. Dellin. If you're feeling ambitious, you can take a moment now to create another page that will let the user confirm the dilly. Maybe with to link one that will go to the deli view and one that will cancel it. I'm gonna leave out this step again so we can move on through the course. But if you've added anything extra to your website or made any cool creative decisions, I love to see what you've done in your skill share project. For all of these lessons, feel free to pause and take time to experiment with the things we're learning and expand on all the skills that we're working on and to actually put the delete link into these anchor tags, we'll use the euro tie again and just plug in the information for delete pen view and make sure that we pass the pens I d. As a parameter. If we refresh now, you're able to create at it and elite pens all from the website. No more using the Jingo Shell. We've almost covered everything in this jingle course with just one major feature to go in . Our next lesson will set up a second data model in some templates for ink data objects that we talked about when we were designing our database. And after all that is set up, we'll talk about how to connect objects together using database relationships. Don't forget to take a moment to commit your changes in get before moving on 20. Setting up the Second Data Model: We want to set up a second object now Inc object that we came up with when we were designing our database in an earlier lesson. This entire lesson will be a recap, so we'll move through it quickly and give a review on each step. As I go, we're gonna repeat all the steps we took to create our pen functionality will create a new data model, migrate the database at a template to create Inc objects, display all of the links on the home page and add the ability to edit and delete them. The first step is creating a model for Inc object. We're gonna open model stop I and then in here at the bottom. We're going to create a new class. Make sure that the class definition isn't indented, or Python will think it's part of the previous class, which is the pen form class. So we'll do Class Inc. Don't forget, it needs to be a subclass of model, so we'll do Models model in the parentheses for the fields. I decided on the brand name, the color way and the numerical rating for our data model. After thinking about it, I'm actually going to split up the color into a color field like we have on our pens and then also a color name field. This way we can display a color for the ink and show the name that the manufacturer gave. That color will create our fields just like before. Brand name will be a character field. Color will be a character field with a max length of seven. The color name will be another character field max length 100 and then the rating is going to be an integer field. We can save some time by creating our form right away while we're here. So underneath the in class, I'm going to define the ink form class again, making sure it's no indented because it's not part of the ink class. It's a separate class of its own. And then, like we did for the pen form, we're going to create a middle class inside the form class and tell it which model were using, which is the ink model. And then we're going to use that shortcut again to tell Jingo that we want to display all of the fields, and that's underscore. Underscore all underscore, underscore and this one has a field for color as well. So we're gonna use that widget variable again. Override the input on the form just like before widgets equals. And then a dictionary where the entry is called color in the value is a new text input. And then, as we create the text input were passing in in attributes parameter a T T. R s. And then we have another dictionary with a type entry set to color. So all of that, all this is doing, as I explained before is it's creating a new text input object in passing in that the type attribute should be color. And this is going to be the widget that is used for color field. We want to make sure to save model stop I before we move on to the next step before weaken , use this Inc model anywhere we need to migrate the database. Any changes made to data models requires immigration, So we're gonna go back to our terminal or command prompt. It's been a little while. We've mostly used this just toe. Do Python managed out Peyron server to get the server up and running. So don't worry if you forgot in some of this, I'm going to go over it again. We need to be in the same folder as managed op I and we're gonna run python, managed out pie make migrations. This is going to detect changes to our data models and create a script that will apply those changes to the database. Then we run Python Managed Alpi migrate to actually applying the changes to the database at this point are Inc Model exists so you can use the Django Shell if you want Teoh to create some inks and play around with those But I'm going to jump straight into the template to create inks from the website while I'm in the command prompt. I'm gonna do the run server command again. So it's running when I want to look at the site later. Now, to create our template to create new links and also edit them. We're going to start with creating a view we kind of know what we're doing now so we can set up this view to allow editing right from the start instead of going back and changing it. So we're gonna define the view, Call it at it Underscore Inc. And we already know we're gonna need an ink i d parameter for when we add support for editing. So let's do this right now and give it a default value of none. We're gonna set this up just like our edit pen view. So the first thing we want to do is see if a form was submitted. So we'll check if request on method equals equals post all in caps and in quotes. And then we want to check if this ink I d variable is not none. So we want to see if a 90 was passed in. And if there waas, we use ink dot objects, don't get to grab the ink object from the database, and then we create our form with the ink object passed in to the instance parameter and then else if there was no i d passed in, we just create a new form with the request stop post data, and we do need to make sure that we import the ink form class. Finally, we check if the form is valid and then save and redirect to the index down below in our other else. Statements of this runs. If the request method is not post, we want to make sure this l statement is lined up with the correct if statement and we check again. If think I d is not none. If it is. If we do have a value here, we get that object in creative form. This time we don't have the post data, so we don't include that parameter and otherwise, if there's no I D. And if the request was not posted, we just create a blank form. Our context variable should have our form just called form, and we also want to pass in this ink i d. Variable a swell here we could create a new template called Edit Underscore Inc If we want to customize this for creating inks today that just create a new HTML file in the templates folder in fill It in with the information that you want. However, I think we can make this a lot simpler, since all are at it, Pen template really does is display a form. We can repurpose it with a little bit of tweaking if we change the name of the template to at it underscore object are html And then in the template, we change all of the Penn variables to something more generic like Object. Underscore i d. We can reuse this template really easily. If you use this option, make sure that all the views that we're using at it underscore pen have been updated to use the new template file or you'll encounter in error. We also need to make sure that we change the dictionary entries for when we're passing these i ds to our templates. And we need to make sure that we have named you RL's for a new Edit Inc functionality. I'm gonna add two new Urals for adding and editing inks at the locations. Inks, slash add and inks slash edit Edit is gonna need a Ural parameter. Just make sure that it matches the few that it's linking Teoh next in order to see our inks . Once they have been created, we need to actually display them somewhere. Part of the fun of developing websites is thinking of cool ways to display things and styling them so they look really sleek. Take the time to experiment here. If you're working on a project of your own design and you can come up with something really cool. I'm gonna add a list of things to the home page. We can use skeleton, see, assesses grid to create two columns and have our pen list on our English side by side to do this first created. If with the class ro, that's just inside the container, Div. And then create two more days each with the class six columns, so they'll each take up half of the available space. I'm going to copy and paste our entire section of HTML that makes this pen table into both of these six column dibs. I'm gonna leave the 1st 1 alone, and then I'm gonna go through the 2nd 1 and edit it so that it will display our Inc data. I need to go through the table and change all the columns so that they match the ink data. So this should have brand color, name and rating, and I'm gonna leave the to blink columns toe, hold the edit and delete links. I'm going to change the four loop template tag for Inc in Inc Underscore list and just be aware that when we out, they are index for you will need to provide this information to the template or are ink list won't display anything. I'm gonna update the data cells as well, replacing each instance of pen with ink and making sure to target the correct field name. I'm gonna update the edit link so it points to our Inc editing. U R L You can update the delete link if you want Teoh. But be warned that if you try to refresh the index before you create the URL for deleting inks, it will given error, saying that the Ural doesn't exist. If you want to play with the website before you add that you are l just take the tag out and put it back in when you're ready. Finally change the text on the add button at the bottom of the ink table and update the Ural to point to the ad in curole, which we have already created. We also need to make a quick change to our index view to actually grab this ink list and pass it to the template. We're gonna import the ink model first and then in the index view, we're gonna add a second line here. Well, underscore inks equals ink dot object Start all. I'm gonna add this End your data context variable making sure to call it the same thing and called it in the template which was Inc underscore list. And make sure we put Commons between our dictionary entries. Now, if you refresh, you should see a space for your table of inks. You can click the add button and create a few of them if you like. Teoh The last up is to create delete functionality for the inks. So we're gonna open view Stop I back up and create a new view Delete Underscore Inc Give it the request variable and the ink i d As a parameter, just like with pen We need to get the ink object by i d with ink objects, Doc, get I d equals Inc underscore i d And then we just need to call delete again. You can create a dilly confirmation template for this, Or you can just redirect to the index like I'm gonna dio with return Redirect Index at a you Earl for the Delete Inc view inks slash delete and then a you're a parameter called ink I d and just call this pattern. Delete Underscore Inc Now we can go back into our index template real quick and just add this URL in so weak until e inks from the table. Make sure that you're editing the ink table and not the pen table, cause they will look very similar. Refresh the page and make sure everything works. You should be able to create inks at it inks and early inks. Once you get the hang of Django, you can create new data models in connect new pages pretty easily. We did all of that very quickly, And now that we have to data models, we can learn about database relationships and show how different pieces of data can work together. Don't forget to commit your changes in get, and you can also up to your skills your project to show off your second data model and share ideas with others in class. 21. Database Relationships: So when you're thinking about your own project, start by creating a box for each of your objects. For my example, just to talk about the different types of relationships, I'm gonna use four types of objects. We're gonna use the example of a library inventory of books. The first type of relationship here is a 1 to 1. So if we have this idea of a place which has an address, maybe he opened closed hours of some kind. The library, which holds a collection of books, can only be in one place. And if a place is a library, it can't be anything else at the same time. So this is gonna use what we call a 1 to 1 field. A library has many books. So when you think about books, we have a whole bunch of them here, and there are many of them, and they can all be connected to the same library. But a book can't in this representation of the data cannot be long to multiple libraries. There are other ways you could design this, or you could have a book that is shared by multiple libraries, and that would be a many to many, but this is a one too many instead of it being a one. To many field, this book is just going to have a reference to its own library. So this is just a foreign key field now to explain the many to many relationship. Instead of assuming that each customer has a book checked out, we want to talk about which customers have read which books now. This is a many to many relationship, because a customer may have read many books and a book may have been read by many customers . And like the 1 to 1 field, this is demonstrated through a many to many field and the many too many field can be either on the customer model or the book model. If there's a many to many field on customer called Books read perhaps, and we passed the related name to the field. Then on a book we can access the customers read through that parameter. So if we call this read by when we create this many to many fields, the book model will be given a field automatically called Red by that could be used to get the group of all the customers that have read that book. So these are the three basic relationships that should support pretty much any project you can think of. There are some very specific, more complex ways to do these relationships that you might run into. So if you're having trouble with getting your relationships set up just right, let me know, and I'll see if I can help you out. Now, we're gonna go back to the code and actually set these up in our data models. 22. Creating Relationships Between Data Objects: Now that we've thought through the relationships for a website, we're gonna implement them in the database model. So open models dot pie and we want to add a foreign key to the pen model like we talked about so right in here in the pen model we're going to do current Underscore Inc equals models dot foreign key with the capital F in a capital K and as a parameter for this, we first want to tell it which model this key is linked to. This reminds me that we can't have a reference to ink way appear because ink isn't defined until the end of the file. So I'm going to copy the ink class and actually move it up above pen. Now we'll put ink as the first parameter in the foreign key filled, and this has a capital I because we're referring to the class and we also need to give it a parameter called on underscored delete. This is a rule for what happens when the item at the other end of the foreign key is deleted. A popular option is called Cascade. That means if the object that it's linked to is deleted, that delete action will cascade to this object as well. This is more appropriate for model relationships for things like containers using our library. Example From before. If you have a foreign key on a book model that references which library belongs to in that library is deleted. You may want that delete to cascade. After all, if the library a book belongs to is gone, the book is probably gone to for our relationship, where a pen is filled with a certain Inc. We want to use something else instead, we want to use Set. Underscore? No. So what this is going to do is when an ink is deleted that's connected to a pen. The Pens Current Inc field is just going to be set to none. And that's what we want. Another thing we need to think about as we're editing a model that already exists in the database is what value should be in this field when the database is migrated For some fields, you might want to specify a default value. Using default equals in the value, but for this we want the pens current Inc to be empty by default. We don't want tohave an ink attached to it automatically. So we need to tell the database that this field is allowed to be blank. We're gonna use two parameters. No equals. True and blank equals. True. Be aware that in python, true and false, both have a capital first letter. Now we need to migrate our database. Make sure you save the models. Top I file back into the terminal or command prompt and run. Python managed up. I make migrations. This will tell us that there's a new field on the Penn model and then we can run. Python managed out pie, my great. Now all of our pens have a foreign key field, and they can each be assigned an ink. Don't forget to restart the server with Python managed up. I run server if we go into edit a pen. Our form already populates the current Inc field with a drop down box containing all the available inks, but we never over wrote this string magic method, so this information isn't very useful to us. So let's go and override that function really quickly. Like before. Just do d e f and then underscore underscore str underscore, underscore and give it the self parameter so we can access the fields on itself. The object. Build up a string of text using the fields to create something that will tell the user which Inc this is. I want to print out the brand name, the color name and then the rating in quotes, all separated with spaces. Don't forget that since rating is a number, we need to cast it to a string by doing str and then putting the field value in parentheses . Once we return that text from her magic method, we can go back into our edit pen and click on the drop down. Now we see names that make a little bit more sense. We still have the problem where the only way to see which INC is independence to go into the edit screen. We don't want that. So let's edit the index template to add something to display it there. I'm gonna add a column to our pen table called Ink, and I'm gonna style the background color of this data cell with the in color, just like we're doing with the pen color in the first data. Sell something cool we can do. Is you can use this dot operator to access fields on related objects. So the current Inc is connected to our pen object, so he canoe pen dot current inc dot color and it will give us the color of the ink. Just like that, we have a visual representation of which inks are in which pens. Here's another place to take some time to experiment and think of cool ways to use these database relationships in cool ways to display them on your website. You don't have to stop it to data objects, either. If your website deals with more types of information, you can create more data models and connect things together in more complex ways. In our next lesson, the last lesson that will cover new information, we're gonna explore a few queries that might be useful for a data driven website. 23. Querying the Database: To finish up this class, we're going to explore some more ways to get information out of the database right now in our index, we're getting everything at once. All our pens and all our inks. But most of the time you don't wanna do that. You want to get objects with a certain name, a list of objects that are related to a certain other object. And we're going to do these things in this lesson, we'll start with a query to get all pins of a certain brands. We're gonna build this functionality right into our index page and make it so that clicking on a brand name in our list will reload the index page showing only pens with that brand name will start in the index view, in our views dot py, and we'll add a URL parameter here called Penn underscore brand with a default value of None. So when the view receives a value for this pen brand variable, it will filter the pen list so that only pens of that brand will show up. For this. We're gonna do pen dot objects. And then instead of get or all, we're gonna do dot filter. And filter is a cool method because it can accept any field name as a parameter and then equals and lived value to filter that field by. If you want to filter something in a way that doesn't match the value exactly. There are few options. Adding a double underscore after the field name. You can add modifiers like GET will filter for values that are greater than the value you've provided. You can also filter vertex that contains the filter value with double underscore contains. Rather than matching the value exactly. For this filter though, we just want to match the brand name exactly. So we'll just put brand name equals pen underscore brand. And we actually want to only do this filter if there's a value in Penn underscore brand. So we'll do if Penn underscore brand is not none, pens equals pen dot objects dot filter. And we'll pass in our brand name equals pen brand. And then Else, if so, if Penn brand is not given a value, we just wanna fill that list with our pen dot objects dot all when making these changes. I didn't think that all pens was a good variable name anymore since we're filtering them down. So I've changed the variable name just depends. And if you change variable names to don't forget to update the data context variable as well, and make sure that you're passing the right list into the template. We're also going to pass our pen brand variable into the template so we can use it to display what is being filtered. So we're just going to add a here to our context variable in an entry called Penn underscore brand. Don't forget to separate all your dictionary entries with a comma. Next, we're going to create a URL that accepts this pen brand perimeter. And our URL is going to be brand dash. And then we're gonna do a new type of URL parameter. Instead of INT for integer. We're gonna do STR for string. And this will match any string of text that doesn't include any slashes in it. And then we're just gonna hook this right up to the index view and call it index. Lastly, we want to edit the template. We want to include links in our pen tables so that if we click on upend brand, it will take us to the filtered index URL. So for that we're going to use the URL tag, URL index. And then we're gonna give it our pen brand. And then we're gonna give it the pen brand variable by name. So instead of just passing in Penn dot brand-name, We're gonna do pen brand equals pen dot brand-name. And I'm doing this because we're going to add a second filter variable in a little bit. And I don't want the view to get confused about which parameter we're passing it. And I also want to show the user what we're filtering and add a button at the top that will take us back to the plane in next with all of our pens and ink. And I only want to display this button if we are filtering something. So for this we'll use an if tag and all do if Penn underscore brand. And then between this if and the end, I'll just put a header showing that we're filtering by brand, Penn brand. And then I'll add a link just directly to the index with no parameters. Refresh this and give it a whirl. And you'll see that if you click on brands in the pen list, you'll be redirected to a list that only has those brands. To make this more interesting, I'm going to add a second method of filtering to filter by the current ink, repeating all the steps for the pen brand filter, we're going to add another parameter called current underscore ink with a default value of None. This is going to be the ID of the inquiry selected. So we're gonna filter by current ink ID. We're also going to rearrange our queries so that we're chaining them. Django queries can be filtered multiple times so we don't need to pass everything into the initial filter. We can do pens equals pen dot objects dot all. And then instead of doing a brand new query, we can do pens equals pens dot filter. If we do this, we can start with all our pens. And then if Penn brand has a value, we can filter on that. And then we can just add another if statement. If. Current underscore ink is not none. We can do another filter on current underscore, underscore ID. And then we can get both pens of that brand that also have a certain Inc.. We want to pass the current ink ID to the template as well so it can display things properly. And we also want to get the name of the ink, because if we print out the ID, the user is not going to know which Inc we're filtering on. And first I'm going to make this variable current underscore, underscore name. And I'm going to grab the ink object with ink dot Object.create ID equals current Inc. And I don't really need the entire ink object. So I'm just going to cast this to a string and save that into current underscore ink, underscore name, and then pass that along to our data context object. Now we're going to add urls, and I'm actually going to add to the first one we're going to add is just like the paran filter, but we're going to use current ink instead. So I've just done ink dash, current, underscore ink as an integer, and then connected out to the views dot index. We also want to add a URL that will filter both. So it needs to have both parameters in the URL. We want to list this one before the other two, so it's checked first. This is because the first half of the URL matches the brand URL exactly. So if that one's listed first, it may produce a false match. So for this one I'm just going to do brand dash, Penn underscore brand slash Inc, dash, current. So we're going to do both of them right in the same URL. And now I'm going to update the template. The first thing I want to do is update the pen brand URLs so that it includes the current ink filter when it's clicked on. So this is what's going to enable us to use both of them. If we're filtering by one or the other, Django will put a value of none into the, into the value that is none. And this can cause a little issue with our URLs. So I'm going to use an if tag to make sure that we're only passing parameters that have a value. So I'm gonna do if current underscore. And then this URL is going to have the pen brands and the current ink. Otherwise it's just going to have the pen brand. We're gonna do the same thing down in the other section. When we're adding our URLs to our ink color names, I'm actually just going to copy this block of code and use it to paste in. When we're editing the URLs for the ink filter, I'm going to put the anchor on the color name text. So I'll paste it in here. And then we want to switch this. So instead of if current ink, it says if Penn brand and then we want to change our current ink values to be on the ink ID that this link is for. If there is a pen brand filter, this anchor tag is going to have the URL index and then both Penn brand and the ink id. Otherwise it's just going to have the ink ID. If we refresh, we can see both of our queries in action. If we click one query and then the other, we should be seeing both filters applied at once. You might need to create more objects to actually get results for some of these combined filters. But we have the power to create any objects that we want, and that's it. You now have a fully functional data driven website and all the tools you need to build out a project of your own sign. Using the skills from this class, I've created a meal planning website, a device inventory website, and a bunch of other smaller websites that were mostly just for fun. When you finished your project. Don't forget to update us in the project section of skill share. It's always exciting to see what other people are working on because no two people approach a problem the same way. If you have any questions or if you're having trouble with some of the coursework, feel free to post questions in the discussion area because I would be happy to help you figure it out. As always, don't forget to commit your changes and get as you go. 24. What's Next?: congratulations. You've made a website. It doesn't more than just display a block. Or maybe it is a block. There's really no limitations on what you can do with Django Web development once you really get the hang of it. And I'm hoping that with this course, you were able to grasp creating new templates and connecting them to your rails, creating views to support those templates and creating data models to store and organize your data. Now you might have a question. Where do you go from here? I have some suggestions for how you can improve the website that we've created here. And if there's any interest, I would be happy to create another course that goes into the more advanced love development that you can accomplish with Django. Some other things that you might want to do to take your Web site to the next level is learn about Ajax and JavaScript to create Web pages. I respond immediately to changing data, dive into CSS or website design, make it look really snazzy, and you might want to dive into creating Web side that has user log ins and actually deploying this to the World Wide Web and allowing other people to use the website you've built. Don't forget to share your project in the project section of this class. I'd like to see what you're working on. Just take a screenshot. You do old or to take a screenshot of what you've done and then paste it into an image editor of some kind and share it with all the other students in the class. Let us know what your data models look like. What you decided to make your website about? It'll be really fun to see all the things people came up with and all the amazing website ideas that are out there. Thanks so much for watching and don't need to follow me on skill share if you want to be notified when a new course goes up. Thanks again. And I hope you have a lovely day.