Orders & Inventory - Day 7 - Django Bootcamp

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone welcome to day seven we have a lot of code to do today so no real overview other than this just saying hey we're going to be coding and we're going to be doing a q a so let's go ahead and jump right in to the code okay so the first thing is obviously opening up our vs code project and i will say for those of you who are not aware of this on my github page let me just write this down here my github page i'll just put it on the screen and i'll do https colon slash cfv.sh github if you look for bootcamp 1 there is actually where all of the reference code will be if you ever get stuck with something so definitely go there for all that now we want to talk about doing orders and inventory now i will say if you start to actually have more advanced shopping requirements as in you want to have a bunch of products you want to have a shopping cart that starts to add a huge layer of complexity that you wouldn't necessarily do it in the approach that i am in the sense that on our product model what we're going to do now is we're actually going to add a inventory item here which is actually going to reflect the price itself so it's going to be an integer field now again this is this is a very simple version of doing inventory realistically if you had a lot of projects with or excuse me a lot of products with a lot of um variants in the product itself like size of a t-shirt for example you're going to probably want to have inventory in a completely different model and perhaps even a completely different application itself but in my case i'm just going to do a very simple inventory field like this which also means that i'm also going to say a method in here that's called has inventory and this method is really meant to just check if self dot inventory is greater than zero and that's actually the condition that i want to return so that's it right so this will give me a true or uh false value and we'll see using this in just a little bit the next thing is i want to change the integer field from the price to a decimal field and this is because i actually want the default price of a product to be with a decimal field right so uh a u in us dollars you know any given price let's say it's 9.99 right so 9.99 we need a decimal field to use that so i'm also going to go ahead and add in some of the required arguments to this which one is match max digits so the maximum amount of digits we want to allow in this item and then we also want to have decimal places so the maximum amount of decimal places that we want to have so in my case it's just two right so these trailing two and max digits i believe it accounts for all of these things uh but honestly if you are too concerned about max they just put like 20 in there it's not a huge deal it's actually a lot more important when you use other kinds of numbers than price right so if somebody's selling a 20 digit priced item well that's a really expensive item and i don't think you're going to be buying it in this fashion at all anyway so let's get i'm going to leave it in as 10 digits that's definitely an expensive item too but we'll leave that okay so we made a bunch of changes to our models now what do we do when we make changes to our models well it's really simple python manage.py make migrations just like we did when we first made that model and as we see here django automatically is saying hey database get prepared to change and all of those changes are listed in this file which you can look at by hitting command click or control click as it mentions so it added that field of inventory on the product model and then it altered the field of price to being a decimal field right and the default is just zero dollars so you're going to want to change those things inside of the admin itself so that's it that's the actual now product model which is good because we want to actually use this in our order calculation so the next thing is actually jumping in to our order models so going into orders we're going to come in here and now we're going to be doing all sorts of foreign key associations so the first one is i want to grab the user model itself so from django.contrib dot auth we're gonna import the get user model and then i'm gonna go ahead and declare the user model here so get user model and then i'm also gonna import the order uh or rather the product model itself so products that models import product now this actually doesn't have to happen right so you don't have to assign the product to the order itself but i actually want to do that so in here i'm going to go ahead and say class order and this is models.model and at the default i'm going to say that there's a user and there's a product right so again if you were having multiple products this is not necessarily the method you'd use like you wouldn't associate the user on here or excuse me you would associate the user but you wouldn't associate just one product you would have many different products so as you might be able to tell in just a moment the complexity can get can get pretty complex pretty quickly so anyway so let's go ahead and add this user in here so we'll do models.foreign key and that's the user we'll also allow it to be null and then uh on delete like we always do let me just break this part down on delete we will go ahead and say equals to models.set null now the big reason for me that i want a set null on delete is because if the user is deleted from my system for some reason the order record is not next one will be models dot foreign key and this is going to be product null being true and on delete equals to models dot uh set null as well same thing as applies to that if the products deleted i d i do want record of the order still even if that product is deleted so the other thing is you actually might come in here and say product you know sku or something along those lines where you actually store the product sku that's associated to this order as well but i'm actually not going to do that that would just be another way to ensure that if you know if you accidentally deleted one of the products you still had the record of the sku in the product itself because how foreign keys work is this is just a reference to a line in another table right so if that line is deleted then this will be empty right it won't actually have something in there and thus having another field that would reference that might be a good idea in the long run but you know we don't have to get too complicated here okay so now what we want in our order is a few things so i'm actually going to copy this price decimal field thing here just to make it simple on myself and that's we got price this time it's going to actually be let's call it sub total okay next one is going to be the tax and then the next one is total okay so naturally you could put shipping like that shipping price in here as well um and you could use the same method that i'm doing here to apply that to shipping as well i'm just not going to do that it's going to add another step that's a little redundant to what we'll end up doing with tax um so essentially what i'll be doing here is i'll be taking the product price that will be the subtotal initially and then i will multiply that product price by some sort of tax rate thus getting the tax amount and then adding the subtotal and the tax to get the total amount so that's what we'll end up doing here next thing is we'll go ahead and add a paid value so as in how much did this user actually pay for this item right no surprise there next i'm actually just going to put the shipping address right on this order as well as a text field here so blanking on true and null equal into true okay so right off the bat you're going to be like well shouldn't this be its own model itself and the answer is probably you'd probably want to have this as its own model where it is another foreign key item into the order itself now honestly doing that adds another layer of complexity that we just don't want to spend a lot of time doing here right it's kind of takes away from actually getting to the goal what we have which is just purchasing one product and really just having a shipping address if the user enters their shipping address wrong here then it will give us an opportunity to reach out to that user and be like hey what's your shipping address we notice that it's an incorrect one you know those sorts of things and along those same lines we can absolutely use the same concept for a billing address okay and then finally what i want to do is actually have a timestamp and we're going to go ahead and do my models.datetime field and this is going to be auto now and equaling to true now if you're not aware of what daytime stamps are or timestamps there are for a daytime field is essentially whenever you create this model this will automatically add a date time object when you actually create the model itself so this happens on its own with this auto now add equals to true there are other variants of this that you can do but the nice thing about this is that also allows us to kind of declare what our order status might be so let's actually do that so i'm going to go ahead and say order status choices and this is mainly for internal use right so the first choice would probably be like whether or not it was created uh this of course is probably the defaults right so when you create an order it should be considered as created and guys i'm actually having a little bit of an audio interruption here uh sorry about that we're gonna actually have to pause for a few minutes because it is trash day sometimes they come at this time sometimes they don't so let's pause and we'll be back in maybe like three or four minutes but i will be on the live chat answering questions uh to keep you guys as informed as possible as to when all of that noise is going to stop so thank you for bearing with me we'll pick up right where we left off and we're back thanks for uh hanging out for just a moment there guys um unpredictable when the garbage collector comes it might be at 1 pm or it might be now which is you know 10 15 a.m of course that happens while we're live but anyways let's get back to it all right so what i'm trying to do here is have several different ways of denoting where the order is and what status it's in and one of them is going to be stale right so like after some time we actually want to mark orders as stale like they they're no longer really in order because they actually never finished it so the next one being paid now you're probably wondering what is this tuple like why am i using tuples here or tuples of tuples or tuples of tuples however you want to pronounce it the reason for this is this actually gives me a new kind of field inside of my model that i can use for selecting those choices so i'm going to go ahead and write underneath the product itself i'll go ahead and add a status here and this is models.char field and the max length being 20 and now i can go ahead and say choices equals to some of these choices in here and then my default is going to actually be created okay so that's always going to be the initial one so i don't necessarily have to set whether or not it's created so these are a few different choices here now a couple other ones that you might also want to have is shipped like assuming you know if it's paid then yeah the next step would be shipped obviously and then finally something like refunded uh that is yet another one that you might end up having in here now i will say that these are another candidate to be outside of the order model itself like status events right so when it's created then it's created and you have a whole another model that denotes that this order was created with the foreign key but again that's that's starting to add a layer of complexity that we just don't need to illustrate all of this um what we're trying to accomplish here so anyway so now that we've got this order model let's go ahead and make sure that it's in side of our installed applications for the orders app and of course it's not here so go ahead and say orders here and now i'm going to go ahead and again run make migrations now i actually never ran my grade so now that i have these two things i'll go ahead and run python manage.py migrate okay so i get a invalid item here on the database so this might be related to my own personal tests uh so when in doubt something like that i'm like hey i don't know why the database is failing so i'm just going to delete my old database all right so always i do that all the time when i'm running um local tests right so there we go so database is now deleted and i want to create another super user in my case and see if he doesn't matter what the password is okay cool so there we go so now we've got our order model and our product model updated a bit so let's go ahead and run the server here and i will also say actually one thing with our product model that i should have actually put on here was featured right so a boolean field for feature so go ahead and say featured equals the models dot boolean field and default being false okay so is this the featured product because again we're going off of one product we're not having a bunch of products we're not doing search we're not doing a shopping cart we're not doing all of those really cool things um unfortunately but let's go ahead and actually now add this field in here so we'll go ahead and make migrations and then we'll migrate and i'll run the server now and let's go ahead and jump into the admin again and i'll log in here and we'll go into our product i'll create a product here i'm gonna add it to the owner the person who's creating this is the only user i have and i'll just call this product one really really cool name for a product don't you think uh so 29 uh let's say 99 and the inventory item so i'm going to give it a 100 and i will say this is a featured product okay so now that we've got that what i want to do is illustrate how to create our order right so when it when it comes to the order itself we had this created status code which means that when the person says you know i want to order this it's going to be a completely different page and it will actually create this order model for us um so let's go ahead and actually create that page i'm going to go ahead and import from models we're going to import the order and then from products models we're going to go ahead and import the product itself so define and this is going to be like our order checkout or order finalize view let's just call it order checkout view and it's going to take in a request and then of course it's going to return render and in this case we're going to go ahead and return the request i also actually want to just return forms.html which we'll talk about in a second but we'll leave it empty here and the first things first is i'm going to go ahead and give it the order itself that we want to use and it's going to be um let's use qs he goes to product dot objects dot filter and there's going to be featured equals to true again that boolean field ideally only has one featured model and even if it doesn't that's okay because we'll just then go ahead and say if not qs dot exists then we'll return a redirect maybe to the home page okay so let's go ahead and import redirect here now what i'll do is i'll say product equals to qs.first really simple so now i actually have the product itself and i probably want to have the login required here so the login required decorator and you know what it's eluding me on how to actually import it so what is the django login required decorator right do this all the time okay so here it is there is the django login required decorator now the reason i want the login required decorator is because on this checkout what i want to have happen is i want to make sure that this is actually a user so i can feel confident that i can say user equals to request dot user okay so the reason that i can feel confident about that is of course this login required decorator but also if i didn't have that it would be an anonymous user and we definitely do not want to use an honest user when we are trying to use this foreign key here right so i actually want to create this order here all right so now what i'll do is go ahead and just say order dot objects that create and product equals to product and user equals to user okay really simple and not a whole lot to this right um so let's go ahead and actually add this into our urls and just bring it in here order checkout view and i'm actually going to put it right next to this path itself so we'll go ahead and say path and let's just call it check out and then the order checkout view in here all right simple enough so let's go ahead and make sure our server is running oops haha i did the wrong import from the order checkout silly stake there so from orders dot views import the order checkout view and we save that and now we're back so now if i go to the url of checkout just like that i hit enter you know it says send data the reason is because we're rendering out form.html we don't have form data yet uh but we are actually creating order objects so let's go back into the admin itself and from dot models we're going to import order and then admin site dot register that order model so we can actually see it in our order itself so let's go back into the admin i'm gonna go ahead and copy this paste in here go into the admin and here we go so here it is we have three order objects in here no surprise they all say created right and also no surprise that they exist now this is one of those cases where i'm using a get request and it's actually creating the order for me right so this is actually the method that i'm thinking about doing this in the sense that if they're going to the checkout page i want to make reference that they went to that checkout page right and that's pretty much it i want to make sure that i'm using whatever that reference is but i don't necessarily want to do it literally every time they go there right so i'm doing it literally every time they go there which is you know it's fine but that's actually not what i want to do instead what i want to do is i'm going to go ahead and say order obj equals to that but what i also want to say is order obj id equals to request dot session dot get and let's go ahead and say order obj id or as in order object id which we can just keep it simple and call it order id okay so if this is none then we'll go ahead and create that so go ahead and say if order id equals to none then we'll go ahead and create it and now say request dot session and order id equals to that recently created order object so dot id okay so what i want to do now is actually delete all of these order objects here and say okay oh and one other thing is since this is an order object id the next part of this is i'm going to go ahead and actually try and get the order object itself so first off we'll say order object equals to none and then i'll go ahead and do try and say order object equals to order that objects dot get id equals to that order id again we've got the id here so whatever the session variable of that id should actually get this object if not we're going to just do a catch-all exception and say the order id is equal to none which means that this will absolutely create another order object for me okay so let me let me just break down as to why we're doing it this method versus pretty much any other method right so first and foremost we want to make sure that we're tracking when our users are going to check out on this product whatever the product is we want to make sure that we are checking that out and to do that we can assign it to our requested session now if you were using more advanced methods here you wouldn't use the order id but instead you would have something like a cart variable that's very similar to how this would function but it would be for all sorts of products so instead of it being the order it would just be the cart itself and then the cart itself would then turn into an order once you go to finalize it but now what i'm going to be getting is every time this user has a session then i'll know whether or not they're working on this order because the other thing is we don't want to create an order literally every time they go to the checkout because if they go back to the home page and like i'm going to do some a little bit more research and then they go back to checkout and it's like okay now i'm ready to buy it we don't need as new order objects for every single time you do that so now we actually do have a new one because our session didn't have it but if i refresh in here several times ideally we don't actually see our order incrementing at all but what we can do is actually print out what the order id is regardless of where we're at in that session so print or order object or order obj.id and um let's go back into checkout we'll refresh that several times and there we go so we actually now have the same you know actual id here and how do you actually end the session itself well uh a really easy way to do it is logging out right so logging out will create a brand new session and therefore an order object so there is a way to automatically expire your session as well something i'm not going to cover right now but this is pretty cool so now we actually have a single order for this actual you know session right so one single order for it assuming they went to that page to go on and finalize uh the next steps so now what we need to do is actually turn this into a form itself so the finalizing of this order how do we actually do that well this is going to be of course inside of a form so instead of orders here we're going to go ahead and do forms dot pi and we'll run from django import forms and then from dot rather from dot models we're going to go ahead and import the order model in this case i'm going to go ahead and say class order form and it's going to be forms.model form now naturally we've already learned about these things so um what we can do here the actual simplest things that we need from this order form are really just our you know additional data from this particular user which is related to the order which is simply fields of the shipping address and the billing address right so at this point that's all we really need in our order form because we don't have a way to collect payment however this would essentially solve that for us too so eventually maybe we'd have some sort of billing information in there as well and you might be wondering well how come all these other things aren't in here like why isn't subtotal in here why isn't tax in here and all that uh we'll get there in just a second but the things that we notice here is user right so we're already assigned the user there we've already assigned a product to that order as well and then we have our status items in here right so the status items are related to my own management of this right so it's an internal thing it's not really a user themselves would not be declaring these things so of course we don't need to set that so all of these financial things we don't need to set so really the only user input is the shipping and billing addresses okay cool so um the next thing actually we we do want to address and that is the product itself right so if for some reason the product is not equal to the saved product then we're probably going to have to create a brand new one right so what we want to say then is order object dot product dot id is not equal to product dot id then we just create a brand new one and add it also to the session okay so yet again um this is this is slightly different than this call right here so uh this also assumes that we do have an order object right so this is saying this is no order id and also probably um no order object itself either but i'm going to leave out that part because for sure if we don't have an order id then we definitely are going to be creating an order object itself so in here one more condition i'm just gonna put if the order obj is not equal to none then we're gonna go ahead and run this conditional statement now of course if i just created it i probably don't need that so uh new creation equals to false and then we'll just come in here and say this is a new creation and now we'll go ahead and say and new creation equals to false that way we're not hammering our database too much for redundant things right so if i'm i'm creating a new order then yeah i don't actually need to recreate that order uh but since we've got that i can actually just bring in my request session down here if i'm so inclined right because if i actually have the order id i can just keep that as my request session so i don't need to do it over and over again right ideally reducing redundancies as much as possible okay so this now brings us back to the form itself so what do we do with the form right how do we actually bring the form in this whole mess that's going on here um so to do this well we are going to come back into forms up high and naturally i can import this form but one of the things that i want to do is call the clean method so earlier segar was the first one to uh mention this but in when we actually did the forms you can use the clean method to clean the entire form itself so we would say something like this clean data equals to super dot clean and in you know whenever in doubt just add these args and keyword args so this clean data is for the entire form itself and we'll just return whatever that clean data is so inside of here what i actually want to have is i want to check product inventory on the forms submission so basically i want to make sure that when they are clicking to order i want to make sure that there's actually inventory left if there's not inventory left i need to raise a validation error so how do i actually assign the product to this order form now you're like okay well don't you already have a product field in here well you do but you the form itself may or may not actually have the order instance on there for several reasons so i'm going to show you one of the ways to actually assign a product object or any kind of object to the form itself without getting hopefully too complex so what we need to do here is actually override the init method here and it's going to take in self and args and keyword args and naturally we want to have the default still happen so the init method is a initializer method this is called on every single class that python has right so this right here is always going to be called the reason i'm calling super is because i'm inheriting from another class and i'm not positive what's happening in that in my init method itself um so we we definitely call super here for that so in these keyword arguments i can actually pass my own keyword argument in there and call it product equals to keyword arguments and pop the actual product itself or we'll say none and then we'll sell set dot product equals to that product okay so this is definitely new for a lot of you if you've never done this in a model form before so going back into my view then let's go ahead and import this form and we'll do from dot uh forms we're gonna import the order form here so now when i actually initialize the form so go ahead and say form equals to that initialize the form i can actually pass in the product that i have itself so the actual product object which is up there so now this form actually has access to that product object itself right so it may or may not have an instance it may or may not have this object in here um that is another way to do it but i want to show you this way because perhaps you're you know this is outside the realm of what you're actually trying to accomplish yourself um but anyway so now we've got the ability to have this product form in here and we can say if form dot is valid then we're going to go ahead and print out the form.cleaneddata.getshipping address and also the billing address billing address okay cool and in the context itself i'm gonna go ahead and add that form in so form and form all right so now what i want to do is actually just come into my form and i'm just gonna in my clean data here i'm just going to go ahead and say if not self.product okay so self.product is this right here so it may be none if it's not equal to none and if self.product dot has inventory then we're good so really this is again if not self.orp oops this should be if self.product is not equal to none and this should be if it does not have inventory uh then we'll go ahead and say raise forms dot validation error and this product is out of inventory okay uh so actually this method itself we just need to verify that inside of our product object we have that instance method in this case it does have inventory uh so i'm gonna go ahead and comment this out for a moment and just return false here to test out this validation on its own without actually adjusting the inventory altogether and yes you would probably want to use unit tests here as well so we save this and now we refresh in our checkout now i have my shipping address and my billing address if i hit send data um it looks like it's seems like it's actually working part of the reason for that is this form right here so i do want to still send in the request dot post or none as well as that product itself so i do want to still handle the post data so let's refresh in here or actually reload the page and i'll hit send data and this is now saying product is out of inventory okay really really simple way on handling all of that so one of the things actually to note here is i'm actually not using order form as a model form i'm really just using it as a form to clean and verify that we do have product data so i will mention that before we did something related to passwords and i said hey how do you actually verify that the passwords are equivalent this is one of those ways as you can actually call that clean data and call the validation error whether or not there's actually a correct password in this case we just passed a product but this is actually bringing a product over there right so let's say for instance i actually didn't have any of this stuff here and this is actually where the value of being able to pass in that product in there in general is if i didn't have all of those things this is actually where i can now initialize that product with that order and still have that validation thus a lot more resilient to other code changes that you might have right so you might be like oh i don't actually need my product in the session i don't care about that at all and if you don't care about having it in the in this session itself then this would be the method you would go about doing things and then you'd absolutely still be able to validate that product which is why i showed you that i mean otherwise we would just use the session itself and not necessarily use a model form so i'm gonna i'm gonna really leave that up to you but it's it's important to see that you can absolutely you know diverge on how all of this can be done which adds to a layer of complexity that you know it's like oh well what's the best way to do it well it really depends on the product's scope itself okay um so not quite done yet though because what we want to do is actually associate the shipping address and billing address to this order so order object.shipping address equals to this form.cleandata.get okay so that's one way to do it another way is to actually pass in the instance itself uh to this order object this is actually probably the preferred way because we do have an order object we are creating it this of course takes advantage of using a model form and also shows you how to update and change things so let's actually take a look at that um so i am still explicitly writing the fields that i want here sort of obj and billing address the reason being is um i actually don't necessarily need to change all of the fields in this order object so then we'll just do order obj.save okay cool um so again we've got our instance actually coming through in this order form so let's take a look at this uh before i actually run anything in this uh order form itself i'm actually gonna go into the order object the most recent one which i think is just seven i think that's our current active one and i'll just go ahead and say abc on my shipping address and hit save and now if i refresh in here i see that my abc address is in here so this is actually how you update fields as well it's coming back in here it's right here so without the product you don't actually need the product in there to update an instance so i can actually get rid of that all together and this will still allow me to update that order instance itself including whatever i store into it right so anything that i store into that that order form or that mo order model form uh actually has access to it uh which is really cool so that's um that's definitely another option that you may want to use at some point uh in the future but certainly in this product order form because before they check out i want to make sure that i'm getting the correct data all right so i want to make sure that their shipping address is correct their billing address is correct and if they navigate away um i'm still keeping that session and they would actually be able to come back and update that data as you as you would okay so cool so now that we've got this um what i want to do is introduce a new concept that we haven't talked much about and this is a concept of signals signals is whenever you actually create something so right here we're creating something right here we're creating something our django project can actually send a signals to our signal to handle some other types of creation that we might want to do so inside of our model itself what i actually want to do is when it's created i automatically want to calculate these totals right so whatever those totals are i definitely want to calculate them so let's actually create a method for that so i'm going to call this define and calculate and this is going to be self and save equals to false i'll explain the save part in a moment so we want to actually calculate every single piece of this now the first thing is the product itself may be null so if i've got a null product then i'll go ahead and say if not self self. product then we're going to return just an empty dictionary here but if i actually have a product then we'll go ahead and say the subtotal is really just equal to that product price so self.product.price and then i'm going to give a arbitrary tax rate of course this can also get a lot more complex you'd have another model itself and actually look up their various tax rates but i'm just going to use 12 percent um you know very arbitrary so i'll go ahead and say the tax total is equal to the subtotal times that tax rate okay so um unfortunately what's going to happen with the decimal fields built in to django um is the rounding is going to have a is going to be an error so this is not going to be always 100 perfect because multiplying two numbers that have decimal places might actually affect how you work with everything so there's a couple of ways on how to solve this and just you're just gonna have to take my word for it at this point but you can do it in your own tests but a couple of ways on how to solve this is actually instead of using a decimal field use an integer field and just multiply all of these numbers by a hundred you know instead of having decimals altogether that is definitely one way to do it so then your tax rate instead of it being you know 0.12 it would actually be just 12. and then your price instead of being you know 29.99 it would actually be two uh 2999 um and that would actually be the integer that you use and that would actually give you a little bit more accurate values and then at the end when you actually calculate the total that's when you would actually just move over the decimal place there and actually using this this format is actually really good for a credit card processing company called stripe uh the reason i'm not doing is that it's just not super intuitive for the rest of us uh so let's actually stick with what i'm doing here even if the rounding is slightly off and when i say slightly off you know you might what you might actually get every once in a while for a total is instead of it being let's say um you know one dollar and 29 cents it ends up being one dollar and 29 cents point and zero zero zero three you know so something like that uh does occur every once in a while whether it's a decimal field or a float number which is what i'm going to do okay so what this is going to give us is a new total obviously or a tax total itself but what we want to do is actually make sure that we definitely don't have numbers like this so i'm going to replace the tax total by turning it into well we're going to use some string substitution here this string substitution will only give me two decimal places and of course this is now a string so i want to turn it back into being a float number or floating point number and this of course is not perfect i realize some of you that are a little bit more advanced in python you're gonna be like well hey there's all sorts of things on how you could probably solve this and do this better um but you know this to me is like by far the easiest way to solve that but anyway so now we've got a tax total so this is what's gonna actually replace that field itself the next one is just going to be all of my total itself so total is going to be the price plus the tax total and yet again with those floating point numbers we don't actually know how that might end up so i'm going to go ahead and just give another total value here and using that floating port number as well okay and hopefully you're really familiar with python but when you when you do something like this where you're resetting a variable this side will always go off of the most previous variable first and then the set variable will be the final one okay so my totals then are going to be equal to the subtotal and that's our subtotal here and then our tax this time i'm actually going to call it tax instead of tax total the reason i'm calling it tax and subtotal is because that's what i named here right okay and then finally my total being my total okay so um now what i can do is say well i can actually add all of my items in here and associate it to my current instance which is simply just self so that means that i can actually come in here and say four key value pairs in totals dot items i can set attribute self key value so what this is doing is saying hey the subtotal key right i'm actually going to set that on the instance to the subtotal value it's the same thing as saying instance dot subtotal equals to you know whatever the totals subtotal value is all right so that's actually what we're doing here with the set attribute but it's for every single one of these okay and then i'll say if save equals to true then i'll go ahead and just call self.save and again it's instance.save or you know we've been calling instanceobj dot save same same same okay um and then we'll go ahead and return the totals themselves now why is it that i did this well this actually has to do with my signals and how signals end up working okay so what we want to do here is i'm now going to import those signals so from django.db that's signals we're going to import our pre save and post save signals okay so the pre-saved signal well i actually need a way to handle this we'll call this order pre save and what comes in by default with the signal is sender instance and then args and keyword args okay so what this means is that i can actually call something on this instance which is the object or whatever is about to be saved in the database so i can actually call instance dot calculate and save equals to false and so since i'm doing this calculation it's actually going to run through this entire instance method but it is not going to actually save it to the database and instead what we're going to do is the pre-save method will save it for us because what's happening here is at the end of the presave method which we won't see it's actually going to call instance.save so this is going to set all the key value pairs or all the fields themselves and then after it's done it's going to save it on its own now to actually use this we're going to go ahead and say presave.connect and we're going to connect to the receiver method which is what this function is that's a receiver function and we're going to go ahead and say sender equals to the order itself okay um so this is probably a bit confusing so you might be like oh well um what if i actually didn't use the preset method what if i used the you know after it was actually created and ran that way well you could totally do that so i'm actually going to copy this and use the post save method now so this is after it's already saved in the database and it's completely in the database for sure now we've got this order post save there's another argument that comes in here is whether or not it was created so now what we can actually do is say if it's created then we can run instance.calculate and say save equals to true inside of instance.calculate it calls save if we say to save it which means that once it calls save it's going to call the pre-save signal it's also going to call the post save signal so naturally saving in either one of these signals actually calling saved in one of these signals will actually recall itself so you'll actually get a constant loop that's running and running and running so you want to be very careful about doing that which is why i wanted to show you these two different methods of essentially running the exact same thing up here we just never need to call this because pre-save is it's right before it's actually going to be saved so we're kind of interrupting the save process to do some of our own stuff and then down here is right after it is saved and it's actually going to be called saved again so this post save signal will absolutely be called again now i actually use this um fairly sparingly for things like calculate right pre-save actually makes a lot of sense to do the calculation in there uh because we're not then gonna save it again right like in this case i i just saved it to my database and then i'm gonna run save again so i need to save it twice that doesn't to me that doesn't make a whole lot of sense instead we're only saving it one time here that's what i'm calling save being false this is definitely gonna be saving it twice because of the signal itself um and created the nice the nice thing about created is when you actually do create any object in there it will actually update that post save cool um so that signals definitely something that is like whoa that is almost out of left field and maybe a little challenging to wrap your head around um so it definitely takes some time to play around with so let's actually see this in action hopefully everything works i didn't actually test it yet so let's go ahead and try it out so right now i get this product is out of inventory now if i refresh in here i'm actually not saving anything because i have a validation error so let's actually solve that validation error first go back into our product into models.pi now let's actually turn this inventory back into our original condition here which is guessing whether or not it has inventory and let's just verify that there is inventory in that product and yes there's a lot of inventory in there so we've got this order now and in here here's that order now let's go back to our checkout process and i'll just leave it in as abc and we get this error um unsupported type decimal and float yeah no surprise there um so so i actually have an error in my calculation itself that's always fun okay so um what it's saying here is it cannot add a float number and a decimal number right or it's actually having a hard time calculating these things so what we can do instead of floats then to be on the more safe side is we can do from decimal import the decimal class and just change our uh float numbers that we were using to decimal numbers and hopefully that actually solves the problem for us i think that it might so we refresh in here we run that and whoops let's try that again it's send data so it's still giving me this this multiplication i can't do it between a decimal and a float um which is because maybe all of the numbers are not actually decimals so let's go ahead and call this a decimal number as well and here is the fun part of doing math in pure python um without any additional libraries in here okay so we got price is not defined okay cool uh no big deal there so that means this price right here uh just a little little mistake there that should have been subtotal okay so let's keep going and refreshing here and now now all of those errors are gone okay so um again i need to emphasize i can't emphasize enough that using decimals and floats and all this stuff is a huge headache in python it's a huge headache in a lot of programming in general because of what float numbers are and what decimal numbers are but you know we can use the decimal class that's built into python to solve that for our decimal field itself or to make things simple which i purposefully did not make things simple but to make them simple you can just use those bigger numbers and then calculate um the total like a display total instead of actually having uh the actual financial total itself but anyways let's check to see if the calculation happened i refresh in here and hey hey hey what do you know it did actually happen um so that is pretty awesome so what does that mean then i can actually come back into my context for that view i'm going to go ahead and now change this from forms.html to being checkout or let's say orders slash checkout.html because we're definitely going to be changing how that actually works in this case i'm going to go into my templates i'm going to make a new folder in here called orders and inside of this i'm going to go ahead and call checkout.html and let's go ahead and add in all of the same data from our form except now what i want to actually have is also my object itself so i want to do uh object dot maybe my uh totals in here so let's go ahead and do sub total and let's actually put this into at least a paragraph tag just to make things nice and simple for us simple as the name of the game here uh but not simple but not too simple right it's simpler maybe let's call it that okay so subtotal and tax and again tax and final total and total and let's go ahead and complete order or so we think it's not quite there but we will get there all right so let's uh let's go ahead and refresh in here uh i actually don't have those numbers coming through no surprise because uh in my view i did not actually add them in as context i did not add the object itself as context so let's go ahead and add in that object in our context variable itself oops that should be order obj here not object but order obj okay so we save that and let's go back in we refresh and hey there is our totals um with the tags in a proper format and of course if we do some mental math here we do see that these numbers are correct right so they're not there's not a rounding error in this case but of course there certainly can be a rounding error where it's kind of in not intuitive as to why we're getting that numbers per se but the way i actually calculated this shouldn't cause a rounding number because i actually rounded these two numbers then added them and rounded again so hopefully we won't actually see any um calculation errors uh displayed to our user based off of the method i did but you know there always always can be a problem um from time to time okay so we're still not quite done yet right there still is several other things that i do want to accomplish with this now first and foremost if the order is complete well now i can go ahead and say order obj dot paid equals to what whatever the order total is i'm just going to assume that it actually is paid um so order object.total would actually be what that value is right so we actually don't have a credit card in here obviously but we can say that it is paid um so instead of actually doing that what i can do is make another method called mark paid or rather not mark paid and save being false again we are going to be saving here so since i'm doing this instance method it's not a whole lot different than what we've already seen right so we saw the calculate here now i can just do mark paid so define mark paid and the reason for this has to do with well what we've got up here we've got our status as well as the paid amount now i actually actually come in here and say paid uh or custom amount let's say custom amount in here is equal to none um or we could use a default value in there but the custom amount would be if i wanted to change it from the default value right so let's say for instance my total is equal to self.total right so self.total of course is reference to that field and then we'll say if custom amount is not equal to none then our total is equal to whatever that custom amount is and again i'm not doing any validation checks at this point probably should but that would be a way to be able to change what our paid amount is actually so then i would say self.paid equals to whatever that paid amount is which let's actually change this from total to paid amount it's a silly naming convention there but now we've got self.paid is whatever that paid amount is and then we'll say if save equals to true then it's just self.save right and then we'll go ahead and return self.paid now one of the things that i also did not do is change or update the order status itself so the order status i also want to change to being paid so that's this status right here so then we'll just go ahead and say self.status equals to paid easy simple and the reason i'm putting part of the logic in here well there's several reasons one of them being i might want to reuse this method somewhere else right i just like the calculate method i might want to use it somewhere else and then in the view itself i could just call that method the other thing is i could probably add there is definitely another way to look at this is say um changing the status here so order obj.status equals or equals to paid i could totally change that status there and then add a signal a maybe a post save signal that's looking for that change in status that then actually runs the mark paid method itself so it's certainly another option there but um i in this case i actually prefer this mark paid method because then i can i can call this mark paid whenever i want to and whether or not i want to save it now again yet again the reason i don't have to call save is because i'm calling it right after and and when in doubt call save on the instance itself not in an instance method right so in other words i don't want to say save is true here and get rid of this right you know when in doubt don't do that um do it this way okay cool so now let's actually see if it's if it's actually been paid okay so let's go ahead and uh refresh and or well we don't have to refresh in here but we'll go to this checkout we'll hit complete order it doesn't show me anything on the checkout page of course but if we actually look at the order itself uh we now have a status of paid we have the amount that they paid um which of course is identical to the total amount and i'm not going to change at this point but if you had discounts or something like that that could be a place to actually do that but realistically you would probably want to calculate discounts much like we did with tax um and it would just be based off of some other table and then it would be subtracted from the total so the paid amount unless you're doing installments which again adds another layer of complexity the paid amount will probably stick at whatever that total amount a total amount is um so yeah uh of course now we're like okay well i just paid for this how do i actually verify that it was paid for well there's a couple ways to do this first off i'm just going to go ahead and return the redirect and we're going to go to a success page here right so instead of actually re showing the form and all that it actually makes a lot of sense to just go to success thank you for your order um and then what i also want to do is delete the session object of the order id itself after it's been saved so we'll go ahead and delete that value which means now when they go back to that order it's going to be a fresh order itself so let's go ahead and try that uh hopefully the whole thing works i hit complete order yes there we go it takes me to the success page and so now when i go to the checkout again uh completely clean and it's going to try and have me complete the order notice that the shipping address is not there again right so if i create a new shipping address and hit complete order again yet yet again a success call okay so uh one of the things that we did not talk about is like a save method like instead of completing the order is there a way to say oh save their progress right so it's not actually doing this there's certainly a way to do that it's just again another layer of complexity that not all of us will necessarily need to do so that's not something i'm going to cover at this point but we did cover a lot of really interesting things but we're not quite done yet and this is definitely a little bit longer one i think i told you that there's a lot to cover um but what we have to do now is well there's a couple things we have to change how the inventory is and that's actually pretty easy to do and then we also have to have a way to handle if these orders are stale right so the stale part this right here now the shift in refund this is more of a action that you would do um you know in the admin itself probably right you'd probably use the django admin to change what that status is so in the future if the user wanted to see all their orders they'd be able to see what that status might be but let's actually go along with the paid portion right um so the user just paid it was marked as paid um how do we actually update what the inventory might be so inside of mark paid we can do this that hey we are just now paying this whatever it ends up being and so what i want to say is now i'm going to go ahead and do product equals to instance dot product and product dot inventory minus equals to 1 and product dot save okay so i'm updating the product inventory here um so what there's a couple things that we need to consider here number one should i actually be calling it manually like this or should i have an instance method i hope that your intuition at this point knows what that should be uh even if it doesn't we'll cover it the next thing is should i actually um you know have some sort of signal in here that i already updated the inventory i think by the the pure the pure question of me or the the the reason i'm even asking that would hopefully allude you to to what the answer should probably be so um inventory updated models boolean field and default being false right so if the inventory is not updated we'll come down here now is say if self dot inventory updated or rather if it's not updated then we'll go ahead and update the inventory and hopefully you had the intuition to say instance.product and we'll go ahead and say you know item which is essentially you know change the inventory itself and i'll also call save being true okay so um this of course we'll also have to say and instance.product and so we want both of those things um so if the inventory is not updated then we'll do that and and again i actually want to move this self call down here because now what we'll be doing is saying self dot inventory update it being true okay so we don't actually re-update this inventory now what i just showed you is actually a really really simple way to also do things like hey did the order shipped should we send an email so email sent type of thing right so you can absolutely do the exact same idea in there where this will then uh instead of changing the product inventory would change or signal whether or not we actually sent out the initial email for that that's not something i'm going to cover at this point but it is pretty cool that that's where we would end up doing this okay so the next part is actually changing this into its own instance method like we mentioned here so i'm going to go ahead and just get rid of that and copy this item sold here and come in to my product models themselves and again making a instance method here and we need to pass in self so we actually have access to the object or the instance itself and so um if the item is sold we need to say that the inventory is going down so current inventory equals the self.inventory and current inventory you know minus equals to one this is the same thing as saying equals to current inventory minus one for those of you who don't know that about python um and then we'll go ahead and say self.inventory equals to whatever that current inventory or the new inventory is really and then of course if save equals to true self.save otherwise we're just going to return self.inventory okay yet again this is an instance method that we can use anywhere if we need to lower the inventory or remove items from inventory so you could call this something different right you could call it remove items from inventory and give a count there so that's actually probably a little bit better so remove item or items from inventory and then you would say the count whatever that count is in my case that count is one so this is a really good instance method because if you have multiple orders for the same object or for the same product then this item sold is no longer just one single order but instead it's remove items from inventory and the count being won so then you can actually change whatever the count is on the fly based off of the order itself but again we don't have multiple orders in there this is just more trying to future proof this for you when you're actually creating uh and updating your product inventories um just like that okay so let's actually try this out let's try it all essentially from scratch right so what i'm going to do here oh yes no such column inventory updated yeah well you know i violated one of my my big rules and that is if you change your models up high you want to do make migrations and then you'll go ahead and do python manage.py migrate okay so we'll go ahead and come back we'll run the server here again and there we go okay so now i've got this change order here notice that the inventory update is not there but what i want to do is let's go ahead and delete all of this just essentially starting from scratch our product um has a hundred items in inventory so let's go ahead and actually do another checkout now again with the form validation you can actually validate all the shipping address and billing address if the product itself needs it let's go ahead and complete that order and again instances not defined no surprise here just a little silly mistake in our instance perhaps you notice that and that's this right here i said instance instead of self um my bad so let's go ahead and call it self here save that and let's go back into checkout complete this order we got we went to the success page that's good um so now let's actually go into products itself click on this product inventory is 99 now orders we've got paid and we have inventory updated okay um so of course now if we go back to checkout it's a brand new order this is a brand new order for the exact same item so you know if you're like oh well i want to be able to support them ordering multiple things a really quick and simple way to do that is just say hey just order the first one and then order the second one and keep going unfortunately that's how our system works right now simple solve not everyone loves that answer but you know that's that's how you can accept multiple orders here without getting too much more complexity um okay so the very last thing i'm going to do is a management command for actually making things go stale but i will say that in our view itself um we do have or rather in our form itself we have a product has inventory flag here that will run this validation error so if it actually does run out of inventory but the actual checkout itself should probably have some sort of condition in there that's checking that as well so like this product here maybe on this we would say um if not product dot has inventory uh we return the redirect um you know to maybe like no inventory or something like that where it's like a coming soon page or an email capture page that is definitely something that you might want to do in this order view as well i'm gonna leave that out for now okay so we save that so now switching gears yet again okay so this is still all about the orders and making sure that we are doing our best with our orders and the inventory itself um so if a product order is going stale now the way i actually create this order if you recall back like an hour ago is right here right i create it when they go to that view i do not create it when the order is being tried or trying to be completed so that's incredibly important for this next part which is i want to actually make a python managed py command and i'm going to call this uh orders update something like that right right now it's saying it doesn't know of this command so i just want to create that command and so i'm actually going to show you how to do it but i'm going to copy and paste code just to speed things up a bit so let's go ahead and come in to our orders model it's or our orders module itself create a new folder in here this folder is called management this is has to be called management this is how you do it inside of django and inside of there we need to create an init file and inside of that we need to create another folder called commands yes i know it's folders on folders and then yet another one uh for init and then finally the command name that we want to give it in my case it's orders update dot pi so that will actually correspond that name corresponds to this command right here so what i'm going to do here is actually just paste some code that you may or may not be aware of on how it works so we'll just talk about it real quick first off the actual time zone itself so django has time zone time stamps that are related to all of this stuff um so you can actually get what now is in the time zone that you're in and it'll actually give you that value and these two items what that does is the start of the day at absolute midnight which we see here with all these zeroed out numbers minus two days ago right so what i'm trying to do is get in a 24-hour period from really like a day and a half ago but depending on your time zone let's say it's two days ago i want to get the start of that day and the end of that day so this is actually how you go about filtering that so it's going to be greater than gte stands for greater than or equal to today start and then you know uh today start being this time zone right here and then otherwise it's less than or equal to today end which is the end of that day so this filter hopefully will be in between that day and it's more specifically having this status of created right so these are all of the created items that don't have paid on there right so they were never marked as paid i'm actually marking all of them right here with stale so queryset.update actually goes about doing that um so what we say is we can also say for obj in qs and then obj.status equals to stale and then oops and then obj.save now the reason you would do this method over this method has to do with the fact this method will actually still send our database signals so post save and pre-save that will absolutely still send those things so if you wanted to send um some sort of email reminder or something like that hey you didn't complete your checkout um come back and check out so something along those lines is how you would go about doing that um so i'm going to leave that out but qs.update updates all of the items in this query set with whatever value you're passing in there um so now that we've got this command we can actually call python manage.py orders update oops i forgot a an import there so we're going to import the date time okay so let's go ahead and run that and i forgot order simple simple simple okay so from orders.models we're gonna import the order itself save that and then finally we now have that custom management command uh no now of course at this point because i don't have orders that are that old uh this actually won't work as in it won't actually change things to be in stale uh because well there's nothing like that so we could obviously test that but i'm gonna leave that to you guys at this point um and do keep in mind that another way to think about this is you could just do less than or equal to you know if it's if it's less than or equal to to that to today's end uh and it has that same status then you could just call that stale two uh but i really just wanted to do it in a 24-hour period and this is actually how you go about doing that just like that cool and of course that's time stamp field the reason i can use the greater than or equal to a timestamp object or a daytime object is because of this timestamp field right there okay well we just did a ton and it probably went way too fast for the vast majority of you so thank you for bearing with me on that um i am now going to be jumping into questions for a few minutes totally understand if this went a lot longer part of that was i was overly ambitious in what i wanted to cover today uh the other part was that little interruption so sorry about that uh so let me know if you have any questions i'm gonna be jumping in to those questions here in just a moment i just need to load up um my q a thing that's going on here and yeah i think this was a huge conceptual leap for a lot of you if you um are struggling already with django right so like this is definitely something where if you weren't able to keep up totally get it like as far as actually coding with me i don't know if the vast majority of you would be able to actually code with me at the same the same rate um but i will say that uh if most of this understand or if you understand most of this then you are you are definitely ready to get into a lot more advanced django topics um so my challenge to you would be hey how do you actually test all this that as in the unit tests that i did yesterday i'm actually not gonna be spending any more time on unit tests um but this is something that i do recommend that you try and give this a shot so now i'll go ahead and take your questions related to today's stuff um so if you have questions let me know i have uh i you know i i am queuing them up right now okay uh so here first questions good one um let's see here can i explain signals uh yes so whenever you call create like modelname.objects.create that will send a signal whenever you create or call on an object or an instance from a model whenever you call save on that that will also call a signal you can also whenever you call delete that will also call a signal now what these signals are is literally like when these actions occur what do we need to do with those actions right so the signals then send out signals they send out like hey this was just saved this instance was just saved so what do you want to do anything about it if anything at all so then you create receiver functions that can actually handle those signals actually happening if you if you don't have signals or if you don't actually have receivers for those signals then the signals are still being sent they're just not being consumed by anything so you actually don't have to really worry about the way they work but there are a number of different kinds of signals and i think i think actually what i covered earlier hopefully actually clarifies how to actually execute them but really it's just a simple method that happens whenever you save something so it's it's either right before it's saved or right after it's saved both of those actually work but there's also one for right before it's deleted or right after it's deleted both of those things work um so yeah thanks for the question that's a good one um so can we use postage signal to update another model if the save method on the current model is run um yes you can absolutely use postsave to update other models as well now i would say that the design of this can get a little tricky so if you're constantly using signals to save to other models as in not the model that's sending the signal itself you might actually run into a lot of redundancy redundancy and redundant signals themselves so i like to make them as simple as they possibly can be uh when in doubt right so just make it as simple as it possibly can be and then then prior to even using signals if it's too confusing for you just do all of it in a view literally all of it and including all the instance methods that i created do all of it in that view and then start to think like hey what of this might i reuse somewhere else right so that calculate method was a really good example of that that could actually be used on any signal they could also be used on any view that could also be used in an ajax call like if you need to recalculate things that would be another way to do it an ajax call being asynchronous javascript object notation or asynchronous javascript request rather that would actually call a rest api and also do that same calculation if if you had other sorts of things in there so for for that specific example it made a lot of sense to put it in as an instance method but not every method needs that so you can still do the the some some more of that logic inside of the view itself um so yeah just just try things out a lot in this um on your own as much as you can and really challenge like what other kind of logical pieces could i put here and like the email one is an obvious example how can can i email the calculated totals every single time like literally hey why don't you try that out and see if you can actually execute that in a signal without a signal and a view all that sort of stuff um there is something else that's also really cool is instead of using signals inside of the request itself there's something called salary that means that you can actually send it to another working process which could be on another server and actually calculating things for you so like if you start hitting scale and you're having like millions of people ordering things then you're probably not going to do it in this method instead you probably push it to another working process that will quickly calculate things for you um you know but that instance method still could be used it would just not be done on the request like we did it right so like when i actually went to um the view itself and it actually did the calculation you know that's not always going to happen in the view is what i'm kind of getting at there okay cool uh thanks for the question that was a good one um thank you for enjoying the boot camp i guess um thank you for the comment that's what i should say i'm glad you're learning a lot i and i realized today was like we just we just really did a lot and probably too much for an hour um i had a sense that that would be the case when i was preparing this one uh but you know i didn't want to spend too much time on these things while also still getting you as much of a much densely packed content as as possible um next one uh so management command commands are great to work with crontab absolutely so if you're not familiar with crontab it's just a way to schedule execution to happen so on your server you can set up a scheduler that literally calls that python method which is exactly what you would end up doing it with i mean you could always do it manually but you would probably want it to be scheduled of some kind crontab's a way to do that celery which i just mentioned is another way to do that and i do have a course coming out soon called time and task 2 on my website that will absolutely cover celery in a modern fashion i do have a time test one so if you really want to learn it right now time to test one that still covers it and it's still definitely relevant today uh but a new one's coming out to show you how to do all of those fun things um and hopefully more bite-sized pieces not so much content in one thing um yeah okay so how do you know what function in a model um can overwrite uh i'm not quite sure what you mean by that david can you rephrase that and ask again i'll definitely try and get that for you uh soon uh folders and folders yeah it was folders and folders you're right uh okay let's see here so can we add a field for the count of the product because the user might need to buy two or three or four from the same one yes you absolutely can have a field that has count in there you can have it as a choice like a char field choice right like i did before where you you essentially are using um a character field for the various choice options for any given product here let me actually just show you that what i mean um so right here we have you know five possible options for the status itself right you can do that same thing for the product count like you could have a count item very similar to status with strings of the count and then when you go to calculate things you would convert those strings into integers actual integers that would actually show you how to do the calculation uh that's a quick and and probably not super clean way but a quick way that you could go about doing that and also limiting uh the amount that they could put in and also not requiring them to type one two three or four and so on of course you could also use an integer field and allow them to select the number that they want and then having um in your form having some validation based off of whatever that number is for that particular product having validation in there to make sure that it's it doesn't exceed uh maybe the amount of inventory that's in that product and or exceed some arbitrary number that you set um yeah so you know that's a that's a good question and that's you know that's where we start getting to a little bit more advanced e-commerce right so i do have a full-on e-commerce course that covers how to do a lot more of the advanced things here but i really wanted to just emphasize how hopefully how easy it is it might feel like it's not easy but hopefully how easy it is to actually charge something of course without the credit card um but to actually charge something and also monitoring the inventory at the same time so taking into account both of those things but actually adding additional products you could totally do that and then you could also have fields in your product model itself that says whether or not they can order multiple things so that would actually be in the product itself um so yeah thanks for the question appreciate it um is there any node boot camp coming up um not not yet i mean maybe at some point i'll have to do a node boot camp i'm not positive if the boot camps themselves like doing this live i'm not positive if it's the best method to teach you guys um part of the reason being that yeah it's cool to see me do it live maybe maybe you guys really enjoyed that part of things but part of the reason is if i ever have production issues like i did today there was the garbage collector came right right at the beginning you know um so if there's ever production issues like that then i can just edit those things out and i think that's that serves you a lot better when you're trying to learn some of this stuff um but i do think that there's a lot of value in the q a part right so doing the live q a maybe after one of these things is released that actually might be something that i end up doing more of instead of like kind of like a hybrid where it's like pre-recorded and then literally like 30 minutes after i release it on youtube or on my website i do a live session to talk about that so you so it's almost like exactly like the same live stream i might end up doing it that way um if i get a lot of people really liking these live streams then maybe i'll end up doing that um but but again the production issues um like unless i move into a really rural area where the garbage truck doesn't come next to where i am my studio is you know i might i might not be able to to always control actually how that happens obviously you'd be like well just don't do it on the days that the those things come well that's not any fun um so yeah i don't know i don't know if i'll con continue doing boot camps the other thing is like um the interaction is great when we start doing the q a so i think the value is actually much more about the live q a than it is about the boot camp but if you guys feel differently let me know i would love to hear what your thoughts are there um so thanks for that um let's see next one will i cover continuous integration and continuous deployment or ci cd with django at some point yes it will not be covered in this boot camp because i mean it's really important and for those of you who aren't familiar with what it is it's essentially automating the testing process when you actually push it into deployment or automating parts of it so you can constantly deploy and it will also build your application and do all the things that need to happen when you go into production um so it's definitely a topic that i i do need to cover and at some point i will have to get there uh and it's not only for django it's it would be for all sorts of uh python and javascript applications if other things as well thanks for the question okay um is it better to create a company model and link to all models orders in inventory and link this company to the user or link the company directly to the orders inventory um so i think what you mean if you had different companies selling different things um what i would do there is actually assign or associate the company to the product itself and that's it you don't actually need to associate it any further than that because the order has a foreign key association to the product which means the order itself has access to everything that's related to that product which would include the company itself much like the user right so that's another example of of that um so thanks for that question you know um something that i think i i think i just realized is our order oh yeah okay good i was gonna say our order isn't even associated to the user and it is you know just kind of slip my mind for a moment um anyways okay cool uh thank you for that okay um so here's a good question how do you use the currency data type instead of decimal field um yeah so there is a third-party package that allows you to use a currency field instead um i actually hardly ever opt to that instead i turn like i was saying earlier i turn um the decimal numbers into a whole number so the decimal places don't make as much of a problem for me so the currency data type there is i would say the third-party documentation probably has a lot on this um but you know if you're losing fractions of a cent like or even fractions of like if you're using losing a thousandth of a cent um that's probably something that happens fairly commonly anyway so you either round up or round down on that and i think at the end of the day you'll probably end out ahead and maybe that's not the best answer to being perfectly accurate but i think the rounding actually has to happen uh in this case i'm actually curious to see uh what a accountant would say about that in this case like a proper certified public accountant um because i personally think that those minor minor rounds should actually go one way or the other and if you round them up all the time then um you will have to account for that in your accounting somewhere because eventually it might end up being a dollar you know so it's really not that much that actually would make that much of a difference so um yeah thanks for the question um okay let's see here thank you for the nice compliment i appreciate it um yeah i enjoy doing this i don't know if you can tell um when's the next live q a um i might do it later today so like maybe like uh nine hours from now um but i'm also not positive if i will because i have to prep for tomorrow last week last week's stuff um i didn't need that much preparation for because i know it so well but like what i did today i definitely need to test all these things out i do know it really well but just doing literally all this off top my head um it's probably not gonna happen right so yeah i don't know if i'll end up doing one later today thanks for the uh i missed self.instance probably um if you find any code errors please just submit a pull request on the github repo which is instead of cfe.s youtube just go to github um and you'll be able to find it there thank you for that comment okay so david i think this is what you're referring to from earlier you define a model that inherits from some models let's say model.form how do you know what functions you have in that parent model so you can override it good question okay so a quick and easy way to find out what's associated to any class which is actually what you're asking um so every class every python class has a bunch of methods that are built into it and then if you inherit from that class meaning you pass the class in as the the primary object much like models.model for example you can actually print out dir on an object of that class that's actually a really quick and easy way to find what's associated to that so an init method for example that's a very basic python stuff that's that's associated to i think every single class definitely has a method even if there's not a whole lot going on in that class um so that's like a built-in standard um that python has for all of their classes so if you're referring to things that django has just literally dir around one of those objects you'll be able to find out all of the different things that are in there and sure they don't necessarily give you all the answers about it but that will allow you to then do further research on your own okay guys so i'm only going to do a few more minutes on this because this was supposed to be about an hour and it's turned into being about an hour and a half maybe a little longer okay so is there any major difference between manually programming the signal and using the receiver decorator no they work exactly the same the receiver decorator is something that some people like to use on signals and more specifically around the actual receiver function which is totally something you can do um i just really like calling the actual signal itself especially if i need to do it multiple times um so yeah i'm not sure if that answers your question for whatever reason i just never really got into the receiver decorator but some people really like it i think it's an extra import that you just don't need i guess thanks for the question okay um can i do a live q a around this time for europeans someday um absolutely i uh once the boot camp is done i'll try and do more live q a's around this time this is a this is a really good time i think for a lot of us for those live q and a's um for me doing them at 9 00 pm or 8 pm um after a long day is sometimes pretty challenging and i i want to actually be very very like energetic while i do these live q a's you know what i mean um so yeah thanks for the question okay um so i got a few other questions here that i'll just try and answer real fast if we add a user to the fields with a button and some data how do we save this model i'm not sure what you're asking uh velado sorry about that um you're in nepal you're you can't actually do international payment services aka no credit cards is there a way to host your static files and images where they don't ask for a credit card as in for free um i don't know i don't know maybe somebody else can answer that question as far as static files um hosting something i haven't haven't covered yet this is a good question a little bit out there you do not need to include or you should include your migrations with your git repo um right because um if you need to change make changes to your production database and you're pushing that code those those migrations are going to be critical for that um through git thanks for the question okay um all right guys so looks like we've got a few more things will we have more complex boot camps after this one perhaps perhaps we'll see um i just talked about boot camps and where i may or may not go with them but that's any anyways that's it everyone thanks so much for coming out for day seven i realized there was just a lot jam packed in this so feel free to let me know if you have any questions on the video itself later so put those in the comments and i hope to do some more live q a's in the future i really think what would be what might be really good for a live q a is that you guys somebody sends me some code that i review in the live q a to give um some actual feedback to that user or that person um and on their code themselves and then everybody else can also benefit from that um if that's something you really want to see happen also let me know in the comments of this video not necessarily in the live chat that's going to end but the actual comments um once it actually goes on youtube that actually might be something really good so then we can all learn from mistakes that might be made with other users things or just solving a challenge that they're having not necessarily mistakes just hey how do you do this i don't know how to do it that might be something that i end up doing at some point so thanks so much for watching guys i really appreciate the support and i will see you hopefully tomorrow
Info
Channel: CodingEntrepreneurs
Views: 14,854
Rating: undefined out of 5
Keywords: django, django-bootcamp, ecommerce, django3.1, python 3, web application development, python web apps, djangocfebootcamp2020oc, live coding, live stream
Id: TtxOwoZlNFY
Channel Id: undefined
Length: 101min 29sec (6089 seconds)
Published: Tue Oct 13 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.