Python Flask Tutorial: Full-Featured Web App Part 5 - Package Structure

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there how's it going everybody in this video we'll be restructuring our application to be a package rather than running it as a module now I usually start off all my flask applications as packages because you dodged a lot of headaches by creating it as a package from the beginning but I see a lot of people using modules like we've done so far so I wanted to show you the process of converting these into using a package and also the reasons why you'd want to do that now if you remember in the last video I said that I would be putting our database models into our main application rather than splitting them into a different file like we did with our forms and that's because the imports can get a little weird so let me actually split these models into a different file so that we can see what happens and what the problem is so I'll create a file here within my main project and I'm going to call this models dot py to hold our database models and now let's move those models over to that models dot py file so I'm going to grab the user and the post models there and I'm going to cut those out of our application and paste those in to our models dot py file and we can see that our classes use the model class from our DB instance so we need to import DB as well so let's grab that by saying from flask blog which is our application file import DB and our models also use the date/time library here so let's move that import from flask blog as well so I'm going to go to flask blog here and grab the date/time module so I will cut that out and I will paste that into the top of our models here so I will save that and save our flask blog as well and now within our flask blog module we're going to be using those models within our views so we need to import those here as well so we can import those just like we did with our forms by saying from models import and we want to import user and post ok so now let's run our application and see if everything worked now since I mentioned that there was problems with this we can probably take an educated guess that this isn't going to work but let's go ahead and try it anyway so if I pull up my terminal here and try to run this app location just like we have been doing I'll say Python flax blog PI and run that and we can see we got an error we got an import error cannot import name user and actually what's going on here is kind of a big mess now I'm going to walk through this but if you don't quite understand it then don't worry about it right now the solution that we're gonna put in place is going to be a lot more simple than what this walkthrough of this error is going to be okay so this is called a circular import but even this circular import is extra confusing now I knew that this would fail but at first this was really confusing to me as to why this was failing on the user import and not somewhere else so let's walk through this step by step and explain why it failed on the user import so we're actually running our flask blog script from the command line and when we run that script it I'll pull this up it imports the user and post from our models module and any time Python imports something from a module it still runs that entire module now some people aren't aware of that they think that it only runs the section that is being imported so when it runs the entire models module then it comes into our models script here and then it tries to perform its imports so then it gets here to this line and says from flask blog import dB so at this point this is where I would expect that this would fail because we've already seen the flask bog module that's where we just came from and I figured it would just say hey I've already seen this flask blog module and I haven't seen this DB variable that you're asking for so if I switch over here to flask blog the reason that hasn't seen this DB variable yet is because it's created after our import statement so it's down here so then it would throw an error saying that it doesn't that it can't import this DB variable but it doesn't do that it fails on the user import so why does it do that so what's actually going on here is that when we ran flask blog from the command line we're running it directly with Python and when we run a script directly Python calls the name of that script double underscore main and we've seen that before with our conditional down here at the bottom that's why we hit this conditional to run our application so we're running this last blog script which Python calls double underscore main and then we say from models import user and post and then it comes in and runs our models script and when it gets to this line here from flask blog import DB Python actually hasn't seen flask blog yet because Python named flash blog double underscore main so it will actually run our flask blog module for a second time from the beginning so it comes in here and then it Bri does all of these same imports reruns this models import again and when it gets to that models import it says okay I've already seen this models module but I don't know what this user class is and the reason it doesn't know what this user class is is because it is below our imports in the models module so that is why it fails on the user import and not on the DB import now I know that this is confusing but just keep bearing with me so if I were to come into my models module here and I was to change this flask blog import instead to double underscore main and save that then this should still give us an error but it should give us the error that I initially expected saying that it can't find the DB variable instead of failing on the user so if I go back to the command line and clear out that output and then try to rerun this application again then we can see that we still do get an import error but it's saying that it cannot import named dB and just to walk through this one more time the reason that it fails on this import now is because when we come in here to our Flash blog module it runs this and it gets down and runs our models import and when we come into our models now we're running this import here from main import DB and it's already seen this main module but it hasn't created this DB variable yet so that's why it fails on that import now we could fix this by moving our models import here down below the creation of our DB variable so if I move that below there and save this and then rerun our application from the command line so I'll clear out that and run that then we can see that this seems to be running and if I pull up the website here and rerun this or reload it then we can see that it is running now so even though our application is running now the way that we actually solved this problem is still really ugly and if we were to run our application where flash blog wasn't set the double underscore main then all of this would fail so for example when we created our database and the last video by doing DB create all in the command line that will no longer work so let me show you this by actually deleting our current site DB file and I'm just going to delete it here from my sidebar and now we'll try to recreate this from the command line so to try to recreate this I will stop the running server with control C and clear that out and I'll start up Python just like we did in the last video we can say from flask blog import DB then we can see that at this point that this fails and that's because it's looking for DB in one of our imports and double underscore main and at that point double underscore main is no longer our flask blog module so I know that all of that was confusing but if you don't understand it then it's no big deal the solution that we're going to go over is a lot easier than going through the problem itself I just wanted to justify why we were restructuring this project and the packages which is going to fix this now just to give credit where credit is due I first saw a good explanation of this and a talk that miguel greenberg gave in a 2016 PyCon talk called flask at scale and that is where i first saw a good explanation of these import issues okay so the solution here is to set up our code in a way to where we're not running flask blog directly that way it won't get that name of double underscore main so the way we're going to do this is to turn our application into a package and using a package will make all of these imports more simple and allow us to separate things out better than we've done now so in order to tell Python that your directory is a package you just need to create a double underscore and knit file so let's create a package with the name of our application so I'm going to exit out of Python here and now I'm going to pull back up our project and our editor and within our project I'm going to create a new folder with the same name as our application so I'm going to create a new folder here and I'm going to call this flask blog all lowercase and within this folder we'll create a double underscore and knit dot PI file so I will right click on here and say new file and this is double underscore a knit double underscore dot PI and again I know that the text is a little small to see over here in the side bar but I'll show a larger version of this structure here in a second ok so now we have a new package with the name of our application so now let's move some of our current project into this new package so I'm going to open this in finder and if you're working on Windows then you can do this and Explorer so now let's move everything from our applications so far into this package except for the module named flash blog let's leave that where it is so the forms and models and static folder and template folder we're going to move all of these into the flash blog package so I will grab all of those and move those in to our flash blog package now this pie cache don't worry about that it's just something that gets created we can actually just delete that for now ok so now in our project directory we can see that we have this flask blog package and this flask blog module so now I'm going to go back to sublime text and I'm going to close everything down here for now ok now we want to open up that double underscore and knit dot pie file so our init file in our package will be where we initialize our application and bring together different components so I'm going to have our previous flask blog module open here and we can separate out certain parts so I'm going to open up our previous application module and now I'm going to grab all of the imports and the parts where we are creating our application so I'm going to copy from our imports all the way down to the creating the instance of our database so we'll cut those out and paste those in to the Annette PI file and now in our old application module now we're left with a lot of route information so let's actually separate out our routes into their own module so that everything has its own place so I'll create a new file within our package called Ralph's py so create a new file call this routes dot py and now let's grab all of that route information and paste it into routes and I'm gonna grab the dummy data and the models import as well so I will copy all of this route information I'm basically going to copy everything except where we're running our application so we don't want the if name is equal to main conditional so I will cut out all of that clean this up a bit and paste that in two routes okay so now all we're left with in our original application file is what we were using to run the application so let's leave this here and when we want to test what we've got we'll still be running this file that's only job is to grab the app and run it so first of all since running the application is the only purpose of this file now let's rename this to run dot pi so that that's clear so I'm going to come over here and right click on this file and rename this and I'm going to rename this to run dot PI that way we don't confuse the name of that module with our new package that is now named flask blog okay so we're still running app dot run within this file so we need to import the app to run from our package and to do that we can simply say from flask blog import app and when you're working with packages that is going to import from the Annette PI file within that package so that app variable has to exist within Annette PI and it does you can see that we're creating it here so it will have that okay and lastly we need to go through our other files and clean up our imports so some of the imports within this PI file were only used in our routes so we still need to import flasks here but render template and URL for and all of those were only used in our routes so let's move those there so I'm going to copy this entire line and paste those in to the routes and we don't need this flask object here we only need render template URL for flash and redirect so now if we go back to the knit dot pi file then we can remove all of those imports except for flask so we'll keep that okay so we still need this SQL alchemy here since we use it for our app initialization down here on line 8 now the forms we were also only using within our routes so let's grab those and move those there so I'm just going to cut those out and now paste these into our routes and also now when we do these imports instead of importing from models and forms like we did before now that we're in a package we are going to use the package name and then the module name so it's going to be flask blog dot forms and flask blog dot modules so let's save that and also if we scroll down here a bit in our routes then we can see that our decorators are using this app that so it uses the app to create these decorators so we need to import that app variable into our routes also so we can import that from our package so just like we saw before we can say from flask blog import app now if we go back to our app initialization then we need to import our routes here also so that when we run our application it can find those now even though we fixed the problems with the messy imports we still have to watch for circular imports so remember that our routes are importing this app variable here so we can't import the routes at the top of the file or else we'll get into one of those circular imports again so instead let's do the import of the routes after we've made the application and installation and put it down here at the bottom so I'll say from flask blog import routes and save that okay so we're almost done here so let's also check our forms and models modules as well so let's open both of those up so first let's check our forms so in forms we're not using any other modules from our package we're just using packages that we pip installed so nothing needs to be changed there so lastly we'll check our modules or models okay and here's where we had our messy workaround from before now instead of importing from main we can simply import from flask blog because now we know that's not going to be called double underscore main anymore so we can just say from flask vlog import DB and that's going to come into the Annette PI file and import this DB variable here okay so that should do it but before I run this let me show you the tree structure of what we've done in this video so you can get a better idea of what this looks like so I've installed a nice command-line tool here called tree that allows me to print out this structure okay so we can see that in our project directory we now have this flask blog package and a module called run dot PI that will run our application now within the flask blog package we have this double underscore Annette dot PI file that tells python that this is a package and it also initializes and ties together everything that we need for our app and we now have a routes file that contains all of the logic for those and everything else should be familiar from our other videos but we've just cleaned up the imports so we have the forms and the models modules and also we still have the static and the templates folders and we didn't change anything within those two directories okay so now let's run our application and make sure that this all works properly so I'm going to clear this out and run our application now remember instead of running flask blog PI we're now going to do Python run PI okay so we can see that we didn't get any errors and it says that it's running in debug mode so let me open this up and reload this page and see if all of this works so I'll just click on a few links here it looks like all this is still working and let's see if our fake email login still works here and everything okay so it looks like all of that still works well so that's good now not only does our application network in our browser but we can also create our database again which failed when we tried this before so if I pull up my command line and stop our server and clear this out and now try to create this database again I can say Python to start up our Python interpreter and from our package so I'll do from flask blog import dB and that worked fine this is just that SQL alchemy message it's not a failure so now we can also import our models so we can say from flask blog dot models import user and post and now remember that we deleted our site DB file so let's create that again so we can do DB create all and run that and now if we do a user dot query dot all then we should get an empty list and that's what we get okay so now I'm going to exit out of our Python interpreter and now I'm going to rerun that tree command again to see this structure and again it creates these podcast directories don't worry about those but the important thing is that we can see that the site dot DB file is now inside the package and that's because we set it to a relative location of being in the same directory as that database so that's fine for now okay so I think that is going to do it for this video now I know that in this restructuring video we didn't get much further in our actual application in terms of adding new features but hopefully you have a better idea for why it's a good idea to structure these applications in this way and how it can save you a lot of headaches down the road so in the next video we will be getting back to adding features and we'll modify our register and login routes so that we can actually create real users and our database and be able to authenticate them and also you know login and logout and things like that so if anyone has any questions about what we covered in this video then feel free to ask in the comment section below and I'll do my best to answer those and if you enjoy these tutorials and would like to support them then there are several ways you can do that the easiest way is to simply like the video and give it a thumbs up and also it's a huge help to share these videos with anyone who you think would find them useful and if you have to mean so you can contribute through patreon and there's a link to that page in the description section below be sure to subscribe for future videos and thank you all for watching you
Info
Channel: Corey Schafer
Views: 174,941
Rating: 4.9830294 out of 5
Keywords: python, flask, flask tutorial, flask package, flask package structure, python package, python package structure, python flask tutorial, python flask tutorial for beginners, flask tutorial for beginners, python web, python web framework, web framework, flask web framework, corey schafer, python framework, python flask, python tutorial, python (programming language), web development
Id: 44PvX0Yv368
Channel Id: undefined
Length: 20min 38sec (1238 seconds)
Published: Fri May 04 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.