Make A ECommerce Site Using ONLY Python - No HTML Or JavaScript!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Thats really awesome. So cool!!

👍︎︎ 2 👤︎︎ u/an4s_911 📅︎︎ Nov 18 2021 🗫︎ replies

Needed an excuse to try anvil, cheers!

👍︎︎ 2 👤︎︎ u/Outrageous-Monk-6281 📅︎︎ Nov 20 2021 🗫︎ replies
Captions
[Music] hello everybody and welcome to another youtube video so in today's video i'm going to be showing you how to make an ecommerce website using only python so you don't need to use javascript no html no css or styling all you need to know is python to follow along with this video and the way we're going to be able to make this ecommerce site is using a platform called anvil now anvil is the sponsor of this video but what this platform provides is a free way to use only python to do full stack development so you can write python for the front end you can write python for the backend you can use python to add components to your website it's a really really cool platform and if you're someone like me who's very good at python or only knows python then this is probably the best thing that you can use to get a full stack website that is fully capable of anything that you would be able to make in something say like react or in any other web framework anyways i'm going to walk through this platform and obviously give you an entire tutorial of how to make this website we're going to be doing everything from creating user accounts so having sign-in and sign-ups for our website to having stripe integrated to collect payments from users this is super cool let me hop over here and show you a quick demo of what we're going to build and then of course we'll get into the tutorial and the platform walkthrough alright so i'm here on the finished product i'm just going to give you a quick demo of what we're going to be building and talk to you about some of the core features that you're going to have in your application once you finish this tutorial so i just want to mention that i'm not focusing a ton on styling here or the actual content of the website more just on the functionality and adding user accounts the stripe integration for collecting payments and then different page navigation and the ability to kind of unlock perks or products for specific users once once they purchase them so here we are you can see i'm on the tech with tim shop this is kind of a course website of course you could change this to whatever you want and after you build this you're going to have a really solid foundation for any type of ecommerce site that you want anyways point being i'm selling courses so if i go here you can see it says view courses we have a python course and a javascript course and then you can sign into an account where you'll get access to the courses that you've purchased or be able to purchase these courses so i'm going to click on sign in i'm going to sign in with my google account i've already done that before so it just signs me in automatically and then you can see i already have access to the javascript course so i'm just going to go back to the view courses page i'm going to now purchase the python course and show you how i get access to it so you can see i clicked buy now it's now showing me the payment kind of form so i can type in my email and the card number and i could purchase this course so let me go ahead and do that okay so i've just filled in the payment information here obviously i don't want to give away my credit card details so i'm just using a fake one and right now this stripe integration is set up on kind of a test platform that's why you're seeing the 49 cents here it's not actually going to charge a credit card it's just for kind of developing and testing so i'm going to say pay 49 cents i do that we give it a second and notice that we are going to get a message that says success we have purchased the course what we can do is go to my courses and you should see that we now have access to the python course so that's kind of what we're going to be building here again you can extend this and change this to whatever type of website that you will like this will give you a really solid base for an e-commerce website with that said let's hop over to anvil let me start showing you the platform and then we'll start making this application all right so i'm here on the anvil website we're actually going to use our web browser to develop this application we don't need to download anything we don't need to have an ide open you could do this in an ide if you want but the online ide that anvil has is really good and that's what i used originally to make this site and i do want to mention that anvil is completely free so they do have some paid plans but you do not need them to make a website and you can actually even publish your website completely for free from anvil with the free plan so what we're going to do is go to this website just click on start building and then what it will ask you to do is to create an account and then once you do that it will bring you to a page that looks like this now obviously i've already created an account i'm just using an email that i use for my youtube videos that i had originally created in a live stream anyways what we're going to do from here is click on create a new app and start from a blank application now of course you could start from a bunch of other apps like this and in fact anvil has a ton of tutorials and full guides that you can actually follow along with if you want to build a different type of website so of course we're doing one related to stripe and collecting payments kind of an e-commerce store you can do all kinds of stuff even related to data science and they have guided app builds as well so if you want to build something different then of course you can follow along with these tutorials they have a bunch of examples as well and then if you want to look at some of the features well i'll kind of quickly run through these but this is very very capable platform it can do pretty much anything that you want anyways we're going to go to this blank app right here and we're going to click on material design that's what i want to start from this just gives me kind of a little menu bar which will be nice to start okay so let's go ahead and click on that it's going to load up what's known as the anvil beta editor this is the editor i'm using they have a classic editor but the beta one is quite good i haven't found any problems with it so we can just use that for now if you wanted to go to the classic you could click that button so i'm just going to kind of walk you through the different tabs and things on this website then we'll start building the different pages that we want so you can see here we actually are starting with a drag and drop editor that allows us to build our custom html so what i can do is in my toolbox here i can click on something like a label or a link and i can just drag it directly onto the page and this will automate and start building the html of this page for me so very useful that's why i'm saying we don't need anything other than python because we can make everything with just drag and drop so let's just drag that label back here and if i want to change this label what i can do is click in the properties tab here and just start messing with say its name within my python code i'll show you that in a second the text its role i can look at an icon maybe the layout for it there's all kinds of stuff and properties that you can mess with pretty much anything you would do in html you can do from this property tab now what i'm going to do is click on this code tab right here and show you that when i do this it gives me the code for this page so this is actually kind of my front end code and this allows me to say link buttons up and do page navigation change different properties and you saw here that when i go to design it says self.label1 what i can actually do is inside of here so inside of the init or inside of a method that i make i can change the properties of label1 i can do something like self.label1 dot text is equal to hello world exclamation point like that so if i go back to design notice that it's not showing anything but if i run my code by clicking on the run button it's going to bring this open let's make it full screen and notice hello world is right here because in my code i change the property of that label or the text of that label sorry and then if you go down here you can see we have our app console background tasks and we have the get integration okay so i'm just trying to show you a few different pieces here now if you want to split between the ui and the code you can do that by clicking on the split view and what these pages are called by default is forms they're pretty much just you know a page right like that we would have in our html or in our actual website okay so let me click on app here this little kind of file directory structure and you can see that now it's showing me my client code my server code and then any assets that i have so for example if i wanted to actually look at the html i could do that i could click on standard page.html it would show me the built-in javascript that it has as well as the html for the page that i have built then i could look at the css i could of course modify this if i want to we're not even going to touch these files in this tutorial okay then we have our client code and our server code so what anvil actually allows you to do as you see here is have some logic for the front end of your website so for the client and then we can have some logic for the back end so on the server side we can actually use python as well to set up some apis or different urls or routes that we can access from our front end and all of this stuff that's related to kind of secure information so our databases purchasing courses we're going to do that from the back end using our server code and we'll do that later in the tutorial okay so that's pretty much all we need to look at for now i'll just go through a few more of these kind of little tabs that we have and then we'll start writing some code so notice we have databases so there's built-in database integration in anvil this allows us to actually store different users that we have the different courses that we're going to have pretty much anything else so we can actually add a table to this default database when i do this i can start setting up all the columns i don't need to know any sql to do this i can just do this with kind of you know the built-in editor they have right here so i can change the name of the table i can add a new column of different types i can add all different types of keys permissions whatever we will look at this more later i'm going to delete this table for right now because we don't need it okay next we have settings so we can change the name of the app i'm just going to go with tutorial for now of course we could change the title as well the description and then the logo if we want to we have different python versions i'm just using python 3 basic python 3. we can go to dependencies we can install different apps or different modules sorry we have our data tables we have collaboration and this will actually allow you if you have the business plan to have someone live editing the code at the same time as you now what i will also do is in the description i will leave this link right here which allows you to just click on this and instantly open a clone of the website that i've built so in case you get lost or something's wrong you can just click this link it will clone this in your anvil workspace for you and then you can modify it all you like you of course can download the source code onto your computer using git or just as a file as well okay that's pretty much it for settings we then have logs not super important we have the theme so we can mess with the color theme here you can see that these are kind of the main colors that i have you can make them whatever you want and then we have search which allows us to just search through all of the code and different things in our application great so that is kind of the walkthrough of the platform hopefully you're getting the gist of how this works now what we're going to do is build our very first page we're just going to start with the design tab so i'm going to go here to form 1 and inside of here i'm just going to change its name so we're going to rename this i'm going to call this my base page now the idea is i want this page right here to actually render all of my other pages inside of it so i want to always have this menu bar on the screen i'm actually not going to have anything in the sidebar although you could put something there if you want and then the main content of our page will go right inside of here which is called the content panel now the content panel you can see is of type column panel and this will allow me just to render different components directly inside of here again so that we keep this kind of top menu bar on the screen all right so the first thing i'm going to do here now that we've talked about that is i'm just going to delete this label and instead of having a label i'm going to add a link so that's the thing that's highlighting in blue or underlined in blue this allows me to actually click on this and then be redirected to a page now i'm going to drag a link there i'm also going to drag two links over here and the reason i'm adding two here is because i want one button that's going to say sign in if i'm not already signed in and another button that if i am signed in is going to allow me to view the different courses that i have so for link 1 this is going to be kind of our title of the website and it will bring us back to the home page so i'm going to call this my title and then for the text i'm going to make this tech with tim shop of course feel free to change all of the wording here so let's go tank with tim shop and then i want to add an icon for this so i'm going to click on icon i could select an icon that already exists here but what i want to do is make it my own icon so i'm going to select the tech with tim's circular icon from my kind of social media kit that i have on my computer and now you can see i get this image showing up so very easy to do that for link 3 i'm going to make this the my courses button so i'm going to go to here and call this my underscore courses like that let's make the text my courses with the proper capitalization and then let's add a icon here to the left that's going to be a book so let's just make it that that looks good for my courses now for link 2 i want to make this called sign in and i want to make the text sign in so let's do that and let's add a icon for this so i want this to be kind of like person so do we have a person maybe we want to just call this sign in so we can go with that i mean we can really make this any icon that we want but that one looks fine to me and now we have our base page so what i'm going to do is just go into the code of this base page i'm going to get rid of this label one because now we no longer have the label one and well that's our base page so if we run our code now we can see we have my courses we have sign in and we have tech with tim shop perfect i'm going to stop this and now what we're going to do is build the home page so this is kind of the base but what i want to have is actual content on the home page of my website and then we can navigate between different pages based on the links that we're clicking so what i'm going to do is add another form here i'm just going to make this a blank panel and the reason i'm going with blank panel is because i'm going to render this page inside of the base page so you can see we have this kind of empty content panel i'm going to put the content of what i'm calling the home page right inside of this content panel you'll see how this works in a second but for now let's rename this to be home and let's start designing this page so for now all i actually want on here is an image so i gotta find image looks like there's an image right there what i want underneath that is some type of label so let's drag in a rich text label which is the second one right here and then i want a button and this button i think this is a button right here let's hover over and see if this says button yes it does for the button what i want this to be is to allow me to view the different courses that i can purchase right so it's going to say view courses like the finished website did so let's start here by adding the image so i'm going to go to image i'm going to call this maybe main image and then for the actual image where would i select that that's going to be source so i'm going to click on source and all i'm going to do is find one of my tech with tim logos that i can use here okay so this is actually the logo that i want i'm going to go with tech with tim extra large okay that's the one that i'm looking for again make this whatever you want for the rich text let's just call this label and for the actual text on this i won't go with anything crazy wait where is the text that's under content i'm going to say this is the tech with tim course shop exclamation point enjoy okay that's all we need for right now now i don't want the text to be this small so i want to make it a bit larger and put it in the center so to do that i'm going to go to layout uh actually that's not what i want i'm going to go to text i'm going to go to align center okay good for the font actually let's just change the font size let's make this font size something like maybe not 50 maybe 40 is good okay so that's actually good for the text i was going to change the font but let's make this down to 30. i think that looks fine then of course if i want i could resize these so maybe we'll make this text a little bit bigger or this image a little bit bigger sorry and now we can deal with the button so for the button what i want to do is go to appearance here and change the roll to be primary color now when i do that notice it's going to make it the primary color that i have set for my color theme of course i could go secondary color but for now we will go actually i think secondary color looks better because i like the orange so we'll go with that we don't really need an icon although maybe we do want one let's go can i do button or like arrow maybe we'll go arrow to the right maybe that makes sense and then for the text of the button i want to say view underscore courses like that we want this to be bold let's make the font size 22 nice and then do we want it underlined it doesn't really matter for now we can go with italics i think that looks fine okay so this is the home page of course i could go to the code not really anything we need to do on here right now but what i will do is i will make it so that we can now render the home page inside of the base page so what i'm going to do is go to code and inside of the init here i'm going to show you how from code i can actually take this home component and put it on this page actually all i'm going to do to do this is say self dot content panel dot add component and what i'm going to do is add the home component like this now to do that i need to import the home component so i'm going to say from and i believe we can just go with home import home like that now let me check my code here and see if this is correct we're actually going to have to go with from dot dot home so let's change it to that and now if i run my code we should actually see that the home page is rendered inside of the base page so let's try this let's go with run and now notice we have the home page right here we have view courses and it's inside of this base page so next what we need to do is set up a few pages for my courses for signing in for viewing courses and make it so when we click these buttons and these links it actually does something okay so let's stop running this and let's actually start by building the view courses page so when we click on this button it actually changes what page that we are on okay so let's go stop let's make a new page here so we're going to make a new form this again will be a blank panel because we're going to render it from this base page i'm going to rename this and let's call this courses like this this will be the page that allows us to buy different courses okay so on here what i actually want to do for now is i just want to put a panel so i'm just going to go to where is it right here column panel i'm going to add that in i'm just going to call this the content panel to be consistent with what we had before and what we're going to do later is we're going to make it so we read the information about our courses from a database and then we render that on the page so rather than statically adding the courses we store them in a database we then read all the courses from the database and we dynamically render them on the page that way if we decide to add any other courses or for you guys maybe products it will automatically add them here we don't need to hard code them in especially in multiple places so i'm going to put the content panel but just so that we see something inside of here i'll put a label and let's just put some text that just says course page we'll delete this later but just so we know that we're going to the right page okay so now that we have courses let's go back to our home page here and let's make it so when we click this button what it actually does is it brings us to the courses page so the way we're going to do that is we're going to click on this button right here and i called this button one let's just call this view underscore courses and let's go down to where it shows events so this is cool what i can actually do is i can set up an event for showing the button hiding the button and clicking so i'm going to go to click i'm just going to click on this like kind of double arrow right here and what it's going to do is automatically create a method for me that will be called when i press this button so it says this method is called when the button is clicked and inside of here i do whatever i want to happen when i click the button so what i actually want to do is i want to clear the content panel which is what's going to be holding all of this stuff we're going to actually make that in a second and then i want to render inside of the content panel the my courses page so very similar to what i'm doing from the base template here from the base template i'm adding this home page and then the home page is rendered within the base page now from the home page what i'm going to do is render the my courses page and kind of delete everything that's inside of this panel so to do that i need to first go to design here and i need to create a column panel so i'm going to grab column panel i'm going to put it right here and i'm actually going to drag all of this stuff inside of the content panel so let's go here and like that and now let's go to this main panel if i can find it and let's rename this to content underscore pen okay so now let's go to code and what i will do here is say self.contentpanel.clear this removes everything so all the components from inside of that panel then i'm going to say self.contentpanel dot add component and we're going to add the courses component like that okay now to do this i need to import courses so i'm going to say from.courses like that import courses great let's save that let's now run and let's see if this button works okay so loading the page let's click on my courses and notice when i do that it brings me to the course page now what i want to do is make it so when i click on this main button here it brings me back to the home page so let's do that then we can set up my courses and signing in okay so let me just remove some of these comments because we don't really need that let's go back to base and let's go to design and let's add something for when i click on this link right here so to do that i'm going to go down to events i'm going to go to click i'm going to now have the title click method and when this happens i'm just going to clear the content panel and then re-render the home page that way we will just get the home page on the screen doesn't really matter where i am if i click on this i just want the home page right so we'll say self dot in lower cases self dot content panel dot clear and then self dot content panel dot add component and we'll just add a new version of the home page okay that's all we need to do now that we have done that what i can do is simply rerun this and we can test it so let's now go to view courses let's click on that notice it brings me back to the home page awesome let's stop this and let me just quickly describe what this is actually doing when i say home with parentheses because i don't think i explained that so as you can see if we look at even like the base page right here we have a class and this class represents the actual page that we're seeing so if i want to treat a page as a component all i need to do is make an instance of that class so what i'm doing is saying make an instance of home and then if i put that inside of add component well it just adds it to the screen right it adds that home component inside of the content panel component and so that's how i'm kind of rendering hopefully it makes a bit of sense but this is the content panel right here i'm putting home inside of there and then from home when i click on view courses the home page then clears its content right it clears what's inside of there and instead renders the courses page perfect there's many different ways that we could do this but for now we're just going to do it in this type of way all right so now that i've done that let's code out the my courses page and then let's deal with our different users so how we can create new accounts sign in sign up etc so let's go to design let's make a new form this will be a blank panel as well and let's rename this here to be my and then courses like that now the only way we're going to access my courses is from the base page right we're going to click on my courses and so i want to make a link here that then renders the my courses page so i'm going to go to the my courses link i'm going to click on click then inside of here we're going to say self dot content panel dot clear and self dot content panel dot add component and we're gonna add the you guessed it my courses component that means that we need to import that so i'm gonna say from dot dot and then this will be my courses import my courses that's all we need to do to set up this link so let me save that let's now go to my courses and let's just add something on the screen we want a panel so i'm going to call this again the content panel and then i want a label and let's just look at this and call this my courses again we will delete that in a second we just need to see what page we are on all right so now that we have that let's test it out let's run the application let's click on my courses notice it brings me here let's go back to the home page let's click on view courses it brings me to the course page perfect now that we did that what we want to do is work with our different users so create accounts sign up sign in etc so to set up our users is actually super simple when we're in anvil we don't even need to make our own custom login forms or anything like that we don't even need to set up a database literally all we do is install kind of a service or a module for anvil and then that will actually pretty well do everything for us we just kind of need to handle when we sign the user in or when we log them in so i'm going to click on this little add button right here and notice we have a bunch of different features right we can go with a facebook api a microsoft api well that's from the business plan we have the stripe integration we have app secrets we have all of this kind of stuff but what i want is users so make it easy to sign up and authenticate users of your app sounds like exactly what we want when i do this it's going to bring me to this page here which pretty much explains everything i need to know about my users so notice that we can sign in with a bunch of different ways right we can do it with facebook we can do with google we could do with an email link or just with email and password now for now i'll just toggle the ability to sign in with both the email and the password or with your google account of course you could select facebook if you want it doesn't really change anything just select the ones that you want okay then we go to login options uh require secure passwords prevent users from changing passwords that are too short or that have been leaked online or sorry from choosing passwords my bad not changing so let's do that remember log in between sessions sure we can select that as well and then we can change this option let's remember the login for one year share login status with other apps users logged into this app will automatically be logged into other apps sharing the same users table they have this option enabled i don't want that and then require two-factor authentication i'm not going to do that as well now we have allow visitors who sign up users can create their own account otherwise need to manually create them we would like users to make their own accounts so we will do that and then new user accounts can be used right away users can log in as soon as they've registered registered sorry otherwise you must check the enabled box so the reason why you would want to undo this is if you need the user to go through some type of authentication process before you actually allow them to fully log in now we also have users need to confirm their email address by clicking a link before they use their accounts so we'll select all of these for right now and then notice is going to show me what the users table looked like so i have information like remember login signed up confirmed email end password failures password hash all this kind of information and again i didn't need to do any of that it literally just set it all up for me okay so now it shows me how i can actually log the user in so i have anvil.users.loginwithform i also have an ability to sign up a user and i have this ability to get a user so if you've ever used flask before this is very similar when you kind of sign in the user and then the user gets stored in the current session that's how it works here with anvil i just call get user and then that gives me all the information stored in the users table so let's start using some of these methods here we're going to do this from the base page and we're going to just call anvil.users.login with form and i'll show you how it actually automates a login form for us so let's go to code here and actually sorry not code let's go to design let's click on sign in and then for here let's do something for the click button click button sorry so now inside of the click button i'm just going to call anvil.users.login with form and this should be all i need to actually allow me to log in a user all right so this looks good to me just note that up here we're importing anvil.users so for some reason this doesn't work just make sure you have this import you need to import that otherwise this isn't going to work for you anyways what i can do now is just run the code and when i click on this sign in button it should just allow me to sign it so let's go to run and now let's see it says sign in okay when i click on this notice says i can sign up for a new account by clicking that or i can just sign in either with google or with my email and password now i'm going to do this with google so let's go here it automatically signs me in now that's because i only have one google account that i've already put the password in for if you had multiple it would give you the google options or your different account options then you could click them and sign in with the account that you want anyways that is working but we need some kind of indication that we're signed in in fact this sign in button should probably go away once we sign in or it should show us kind of our user's name or our user's email or something like that so let's actually go ahead and do that i'm going to go now to my base template i'm going to go to code and i'm going to make something that actually changes the text from my sign in button based on what you call it if we're signed in or not because also if i'm signed in and i click on the sign in button again i probably want to be able to sign out right rather than just signing in with a different account i need some way to log off or to sign up so i'm going to go to sign in with click and actually that's not where i'm going to go first i'm going to make a method first i'm going to say define change sign if i can type here in underscore text this is going to take self and what this is going to do is just check if a user is signed in and if they are it's going to change that sign in button so i'm going to say user is equal to and this is going to be anvil dot users dot get underscore user this will give me access to all of the information in the users table but what i can just do is say if user now if we don't have a user signed in this will return none to us if we do have a user signed in then what we can do is we can get their email and we can make that the text for the sign in bud so i'm going to say if user then email is equal to user and this will just be at email the way we access stuff from our database tables is by just using a dictionary key like this so i say user at email it will give us the email and then what i can do from here is change the text on that link so i can say self dot sign in dot text is equal to email like that otherwise so if we are not signed in then i want the self dot sign in dot text to be equal to sign in like that okay so now i just need to call this method so what i'm going to do is as soon as i render this home page here uh actually we can do before we enter the home page we'll just say self dot change sign in text and then what i also want to do is make it so that after i click the sign in button i call this method because once i've signed in then this will have changed right we will have someone signed in and so we need to change the text so i'm going to say self dot change sign in text and i just call that again after we potentially sign in or maybe don't sign it okay let's give this a shot here so let's press run and let's see what we get now notice that sign in is like this so i guess it didn't actually save my sign in or maybe i've messed something up i'm going to go to sign in though and i'm going to sign in with google and let's see if it now changes to my email okay perfect so it does change to my email now we get this here the other thing that i might want to change is just this icon because this icon doesn't really make much sense now if i'm not signing it so i'm going to do that but first let's see what happens if i click on this and notice when i click on this nothing is happening because i'm already signed in so we will make it so if you click on this it allows you to sign out but we'll do that after we change the icon or the logo i keep calling it logo but i mean icon so let's go back here the base page let's go to sign in let us go to our icon and let's change this to something that kind of looks like an account i'm just going to scroll through here i had one on my other website that i liked but i don't know what it was called i want to say it's called account but it doesn't look like it's called that do we have people do we have person do we have sign in okay uh let me check what the icon was and then i'll be right back all right so the only thing i didn't guess which is user is what i will do here so i will just go with the user icon and then this will work for sign in as well as for what he called if we are already signed it both of those work okay so now that we've done that let's go back to code and let's make it so that if you click on this button and you're already signed in it lets you log in so i'm going to say if actually let's say user is equal to and then anvil dot users.getuser like that if we have the user so if user then we don't want to do that so i'm going to say else like that instead what we want to do is allow the user to sign out so what i'm going to do here is actually ask the user if they want to log in now the way i can do that is by using a built-in function called confirm this will actually open kind of a dialog that will say do you want to log out and then they can click yes or no and based on if they click yes or no this will be true or false so i'm going to say log out is equal to confirm would you like to log out question mark and i'm going to say if log out so if they press the yes button then this will be true if they press the no button it will be false so the if statement will run so if log out then i'm going to say anvil dot users dot log out like that and then i'm not sure if there's anything else i want to do here actually if they do log out then what i will do is i'll just bring them back to the home page so i'm going to say self dot content panel dot clear and then self.contentpanel.addcomponent and then this will be home now that i'm thinking about it though i can probably put this in a method because i'm doing this a ton so i'm just going to make a method here and i'm just going to say define go to underscore home this will take in self we'll just paste this in here which allows us to go to the home page let's make sure our indentation is correct and then what i will do is instead of this here just call self dot and then go to home and i do this a few other times as well i do this right here so let's just say self dot go to home and then up here we can say self dot and then go to home as well okay that is all good let's now try this out and let's see if this lets me log out okay so let's run the code and let's first sign in okay so we're going to sign in with google brings me here let's click on this notice it says do you want to log out let's click yes and then it logs me up perfect that is all good the next thing that i want to do is just make it so this my courses button only shows up if i'm signed in because really how am i going to view my own courses if i'm not already signed into the account that doesn't really make much sense so we only want to show this button if we are assigned it so let's do that we're going to go to change sign in text is this where i want to do it let me look here and see where exactly we actually want to implement this functionality so let's actually make a method here just to make this a bit more readable and let's say define and then let's say toggle underscore my underscore courses underscore link and inside of here we're just going to say that self dot and then my courses dot visible is equal to and then this is going to be anvil dot users dot get user and this is going to be does not equal none so what this is going to allow me to do is set the visibility equal to true so we can see it if we are signed in and if we are not signed in then it will make it false now what i need to do though is i need to call this inside of the change sign in text method because whenever i'm changing the sign in text i also need to potentially change whether or not this button is visible so i'm going to go here and say self dot and then this will be what do we even call this toggle my courses link and now we should be good okay so let's run this and let's see if this works notice that it's not showing the button because i'm not signed in and then when i sign in let's sign it with google you will see that it now shows me the my courses button and changes this text so now i can click on this and we are good to go okay so now we have finished implementing the users hopefully you saw how easy that was to do it was literally like four or five lines of code and a few button clicks to get the users working and i'll just show you that if you click on this data tab right here we have the users table and inside of here we can actually add fields to the table if we wanted to do that so one field i'll add right now because we're going to use this in a minute is called purchased courses and this is because we need something to keep track of what courses a user has purchased so i'm going to add a simple object column this allows me to add a python object inside of here like a list so let's add simple object let me scroll over so we can see this and for this simple object i'm just going to put a list for now just an empty list and that's all we need for this first user okay that is good now what i will do is close this and we are going to start making our actual courses so as i was saying before what i want to do is i want to have a database that kind of stores all of my different products in this case they're courses but for you guys it could be an actual ecommerce product that you're selling and what i want to put in there is the name of the course the price of the course the id of the course maybe an image for the course pretty much any information related to it so i can just grab all that information right from my database so i'm going to make a new table here inside of the database i'm going to rename this and i'm just going to call this courses now we need a few columns for this course so the first thing i'm going to do is add a text column and i'm just going to call this the name now what we can do is manually add the names of our courses so the court first course that i want is going to be javascript and then the next course that i want is going to be python now other than that i want a price column so i'm going to add a number column and i'm going to call this price now for the javascript course we'll go with 37.99 and for python we can go with 49.99 and also feel free to add a lot more items as well i'm just going to go with 2 because we don't need a ton right now but you can add more if you want obviously next we have the name we have the price we're going to want a date time column for when we created this course and what we can do is if i right click on this i should be able to actually insert a date time okay perfect so i can insert a date time by just clicking on this for the time i don't know i'll just select a random time it doesn't really matter what it is so let's go with this that's the time that we created these two courses perfect after created the next thing that i want is the description of the course so i will just say for here learn javascript and become a pro did i spell this wrong uh yes i did okay and then i will say learn python and become a master okay just random stuff just so we have some content other than description the other thing that i wanted was actually the image for this course i'm going to add a media column and here i can add like a file or an image or something so i'm going to find two images in a second and add them here but for now i'll call this image and then lastly i want to have something called my id name now the point of this is just to be a lowercase version of the actual display name so that i can easily reference this course so i'm going to say javascript and i'm going to say python again the whole point this is just to have a lowercase version so that i don't have to get the capitalization correct on my courses which could have you know multiple words uh different capitalization all of that kind of stuff okay so what i'm going to do is take a break here find an image for both javascript and python and then i will upload them here and i'll be right back alright so i've just uploaded the two images that i'm going to use here as kind of the cover image for both of these courses it doesn't really matter what these images are i've just found some ones that are decent sizes and if you want these exact same images then you just need to clone this application again i'll leave the link down in the description when you click on it it will open a new anvil workspace that will have these images and have pretty much everything that i've worked on in the entire tutorial anyways we now have the courses database so we are kind of good to continue here now what i want to do is start talking about the server side of our anvil application so right now we've just been working on the client side we've been doing front end code and that's fine for now however we need a way to actually access the fields in our database and we want to do that from the server so we want to set up kind of a module or maybe an api if you want to call it on our server that gives us information about our courses now the reason we want to do this on the server is because whenever we're accessing information from a database or something that we don't want the client to be able to modify or change we need to do that from the server because if we do it from the client then they could potentially modify this code they could do something malicious so whenever security is important you want to be doing that type of operation on the server and then just calling or sending a request to the server from the front end to perform that operation so what i'm going to do here is make a new server module i'm going to rename this and i'm going to call this course details now this module is going to allow me to get the details of the different courses that i have from my database we're going to set up a few different api calls here or roots or methods or whatever you want to call them that allow us to get one all of the different courses and their information to the price of a specific course we're going to use this when we're at checkout and we're trying to charge the user and then three just get information about one specific course we want all of all three of those different routes we're going to use all of those now you can see here that to make something that's callable on the server you use anvil.server.call as a decorator above a function so this is an example right here let me uncomment this you can see that this is actually callable sorry from the front end because we have anvil.server.callable which means we can use kind of this specific function which is anvil.server.call to actually call this and get the data from it securely so i'm going to change the name of this to say get underscore course underscore details like that and then inside of here i'm going to say return and i'm going to say app tables which is going to reference my database tables then this is going to be dot courses and then this will be i got to look at my other thing here dot client readable now what this allows you to do is actually return a readable view to the front end of your website so it can read all of the information about the courses but it cannot change it so whenever you want to get all the info you just return client readable this means that again the client can read this information they can't change it they can't modify it that's what you want however if you were to return something like client writable i mean you can read what this says but return a view on this table that can be written by client code use keyword arguments to specify view restrictions this does not give client right access to other tables referred to by this table so i mean you can read what that says it's pretty straightforward but the point is that whenever you have information that you don't want the client to be able to change then you return readable if it say something like the client's name or their email or something that they maybe could change that's fine for them to modify then you would return client writable and you could change how the view is writable by adding keyword arguments i'm not going to go through that but there is a ton of tutorials on the anvil website that show you how to do that and in fact i'll just mention now if you want to do something that i'm not showing you here anvil most likely has documentation and tutorials for it in fact if i go here you can see that there is a punch of tutorials oops i didn't mean to open that and if i go here i mean you can click on the different tutorials and then you can also just look up the documentation i think there's docs right here yeah if i click on that it brings you in here and it shows you pretty much everything you can do okay so let's go back we have this view that we want i'm just going to get rid of all this i'm going to show you now how we can call this and how we can kind of view the information that's being returned for it so we've done this on the server side what i'm going to do now is go to my my courses page and on the my courses page what i want to do in the init is i want to load all of my courses from the database so for now let's just write a method and let's call this define load underscore courses like that let's put a self inside of here and then what we're going to do is the following we're going to say courses is equal to anvil dot server dot call and then what you do is you put as a string the name of the method on the server you want to call so if i go to course details this is called get course details sorry we should remove name from here we don't want name as a parameter and then if i go here i just put that and what this does is call that function now let's say you had some parameters you wanted to pass all you would do is put a comma and then you would pass all the parameters so if there was a name there then i would say you know name of course whatever right and if there was a keyword argument i could do something like k like this is equal to 2. that would be fine it would pass that as a keyword argument to the function okay so now we have courses what i'm going to do is just print courses and show you what this looks like for right now so what we'll do is we'll load the courses so self.loadcourses like that right when we load the my courses page okay hopefully that makes sense hopefully you've got that code down let's run now let us sign in and let's go sign in with google okay let's click on my courses and then notice if i go to run app console we say we get a live object and build.tables.table now that is because this is a special object that anvil is returning to us representing the database table if i actually want to be able to view the information i need to use a method on this called dot search now it actually shows you what this does says get rows from this data table if you specify keyword arguments you will retrieve only rows whose columns match those values so let's add dot search here and now let's see what we get and if this is actually going to work for us we might need to it right over this and let's go to sign in let us sign in let's go to my courses and now notice we're getting the search iterator so an iterator is something that we can loop through in a for loop so what this means is that if i want to actually get the information from this iterator i need to iterate over it so let's go ahead and do that now i just realized here that i'm actually inside of the wrong courses module this is my fault for naming them so similarly but i'm going to copy this code so load courses and yeah i guess just load courses and i'm going to put this inside of courses rather than load courses or sorry my courses because my courses is going to be my courses whereas courses is going to be all the different courses you could purchase so we want to start with this one and then we'll go over to my courses after so i'm just going to copy this in here so now we have what we had before and i'm going to loop through this iterator now and let's just print out some information about the courses so i'm going to say for course in courses and what this should do is give me one row of the database so each row will be one course and then what i can do here is just start by printing something like the course and then the name and see if we get the different courses that we want so now let's run and we don't actually need to sign in to do this we can just click on my courses and notice we get javascript and we get python as the two names of our course so now that we've accessed this information we need some way to display it now all of our courses are going to be displayed in the same way right we're going to have an image we're going to have a description we're going to have a button that says the price and when you click on that it's going to bring you to another page so what i'm actually going to do is set up a new form here and this form is going to be an individual component that i'm going to use to represent a single course so i'm going to make a blank panel so what i'm going to start with here is a panel so i'm going to import my panel let's call this the content underscore panel okay let's add an image we will just call this the image like that let's import a label so we'll put a label inside of the panel i'm just going to add some text to it so we can see it so let's just call this description and then we'll say this is going to be a description like that now we want this description to be in the middle so i'm going to go to text i'm going to align center for the font size let's go with 20. that looks like a decent size to me and i don't think we need anything else for that and then we'll add a button so let's add a button right underneath here this button i'm going to call by now this is going to just be align center okay we'll make it bold we will make the font size 20 as well uh we will actually won't underline it but for the role i will go with primary color and then that should be good for now i think that's all i need so i have my uh what do you call it i have my button i have my label and for some reason i think my button's inside of my label so let me try to pull that out uh okay maybe not maybe the label is just overlapping the button okay you know what that's fine for now i think that's fine let's make sure they're named good we have by description and image perfect what i'm going to do now is i'm going to turn this component here into a custom component now see how it says use as custom component what this allows me to do is pass values to this when i create it so that i can actually fill in this what i'm going to call course item in a second with the information for a specific course so the idea is rather than me making like four or five of these for all the different courses that i'm going to have i'll have kind of one standard layout and all of my courses will be represented in this way so i'm going to say use this custom component i'm going to say make this form available as a custom component i'm going to add a property specifically i'm going to add three properties now these properties are what i want to pass to this component when i create it so the first property i'm going to call is the name this will be the name of the course the next one that i want is going to be the image and then i also want the buy button or we'll just call this the button underscore callback now the idea is i need to pass some function here that's going to be called when i press the buy button so we're going to have to set that up in a second but let's change this from a string to be a object the object will just be the function to call when buying course or when i go we'll go with clicking course button okay uh that's fine now for the image this is going to be a can i make this a media let's go with okay let's go with object i think i can pass an image as an object here that will be fine and then let's go with name name will be a string the default value will be nothing and then i also want description so let's make this the description like that and that will be a string as well now i just realized that i probably want a title or kind of like a name of this as well so let's add a label at the very top and let's call this the name now for the content i'll just make it name for now just so we can see it let's make sure this goes in the middle so let's go align center font size want this to be fairly large so let's make that 30 and then do i want to make it bold let's see if i can do that let's go to advanced and actually uh you know what i'm fine with the bold for right now i could do that if i want but we don't need to be bold okay so that is going to be our course item so let's rename this here to be a course item now notice that beside it we're getting this little icon which represents it's a custom component so i'm going to show you how we use this but this is going to make our life a lot easier so i'm going to go to courses now and i'm going to import this course item i'm going to say from dot dot course item import course item now just for kind of example purposes right now i'm just going to load one course item on the screen just so you can see how we do that so i'm going to say self dot content panel dot add component and this is going to be a course item now what i need to pass to this course item is going to be the name the description the image etc so for now let's just pass a name so let's go with name is equal to and we'll just call this python now i'm also realizing at this point we probably need a price as well for this course or actually more specifically something that we want to put on the button so i'm going to go back to course or course item for one second and i'm just going to make another property so i'm going to go configure custom component i'm going to add a property here and i'm going to call this the button text so just what do we want to be on our button okay so let's close that let's go back to courses and let's go here and say button underscore text will be equal to buy for 39.99 we'll put a dollar sign what else do we want uh we need the image i won't pass that for right now we'll go with name button text we'll go description equals the best course exclamation point and then the button callback i won't pass either i'll show you how we do that in a second so let's go to course details now and sorry not course details course item and let's go to the code and let me show you now how i kind of take all of these properties in and actually set the different elements that we have here equal to those properties so inside of my initialization here i'm going to take in a name i'm going to take in a description and i'm going to take in a button text and we'll take in a few other things as well but for now that's all we want then what i'm going to do is say self.name is equal to name and this is going to be named.text actually i'm going to say self.description.txt is equal to description and i'm going to say self dot and this will be by dot and then text is equal to button text and that's all we need for right now so now what's going to happen is if i go back to courses here when i add this course item and let's just make this a variable to make this easier let's say c is equal to that it will take the name the button text and the description and then update whatever i set as the default values here to be equal to those right so that's kind of the point so let's just try this out for now and see if this works and then we'll continue from there so let's go run let's go view courses and then notice we have name description and buy for 39.99 looks like i messed something up it says course item has a method or attribute name and a component called name this method or attribute will be inaccessible okay that makes sense the reason why i'm getting this problem is because what i named the property is the same as what i named kind of the element so i need to rename the element so that it doesn't match with the property that i passed it i guess that's a decent error to run into so then you guys don't run into that yourselves so let's go to course item and let's change this i'm going to call this name underscore label okay just to make that a bit more clear okay name underscore label that's fine uh image uh we'll call this image underscore uh i don't know let's go go with content for description we'll go with description underscore label and then for by we can leave it at this but i'm just going to change this to button because i think that's better assuming we spell it correctly okay so now let's go back into the code here and let's change this this is going to be name underscore label this is gonna be description underscore label and this is gonna be button like that okay so let's try this now and let's see if this works okay let's go view courses and now notice again we're getting the same problem name description buy for 39.99 looks like for some reason we're not updating that so let me take a look at why this is happening and i'll be right back all right so it looks like the problem that we're getting is that i was trying to use text for my labels when instead for the rich text i want to use content now notice i can actually click on these right here and it shows me all their properties so i have my name label and i need to use content rather than using text so i'm just going to change this to content like that and i'm going to change this to content as well and then this should be good okay so let's run this and let's see what we get view courses notice we have python the best course and then 39.99 awesome that's exactly what i wanted now we will continue and hopefully make all of this a bit nicer so i'm going to go into the design of my course item here and for my content panel i'm just going to go to roll i'm going to change this to a card now notice how it kind of raises it up a bit and adds a bit of a border that's going to look a bit nicer so we'll go with that for right now and then let's go back to our courses let's go to design and let's just get rid of this label here because i no longer want that inside of here okay perfect so now courses let's go to code and let's use this inside of here to actually render our different course items so let me go here let me just copy this and let me get rid of this and let's do the following we're going to say c is equal to course item it's going to be name and instead of name equal to python this is going to be course like that and then name and the button text is going to be equal to we're going to use an f string and we're going to say that this will be purchase 4 and then we'll have a dollar sign and then we want the price of the course this is going to be course and then at price then for the description this is going to be course description like that and then we need to add an image so we're going to say image is equal to and this will be course at image and then the other thing that we want is we want the button callback as well as do we want do we have something else i forget if we have something else that we need to pass there let me just close this so we have a bit more room let's go back to course item let's have a look we have our button we have a description we have our image we have our name nope that looks like that's all we need so that should be good and then we have our button underscore callback which for now i'm just going to make equal to none but we will fill this in with the function that we want to call when we press on that button in a minute okay so we have c now what i'm going to do is add this to the component or add this to the content panel sorry so self dot content panel dot add component i'm going to add c and that should be good all right so now that we've done that i just want to hop over to course item and i need to make it so that now we're going to add the image as well as something else that we passed that was new the button callback although we don't need to do that this second so i'm going to go here and i'm going to say self.image underscore content is equal to image and i'm going to now take in the image as well here so i'm going to say image and i'm going to take in the button underscore callback as well okay so we have name description button text image and button callback we now should be assigning all of those when we set the course items we're going to add all of the different courses that we have as course items and we're getting a syntax error here saying bad input i think that's to do with the indentation so let me see if i can fix that i think what's wrong here am i messing up a bracket ah so i see the problem here it is the fact that i have double quotation marks inside of double quotation marks so i just have to change the price here inside of my f-string to use single quotation marks and then we should be good to go okay so let me run this here and let's see if this is going to work for right now okay so it looks like we got an error we got bad input and if i scroll up here we can see that's on this line so let's click on that it's going to bring me here and it's saying that this is a problem all right so it looks like i forgot a comma classic rookie mistake so let's add that right here i also realized that i need to change this to say source so self.image content needs to have source after it okay apologize about the errors guys but that is just part of developing let us run the code and let's see if we're able to fix this and let's go to view courses and now notice we have javascript and we have python perfect the only problem is these are quite large and they're taking up one row each so instead of having them taking up one row or sorry yeah one row each i want them to just be on one single row so we have kind of javascript and then right beside it we have python so i'm going to show you how i can how we can do that how we can kind of align the two different uh elements here or the two different components so let's do that okay so we're going to go to courses and we have courses like this we're getting the course item we're adding this to the content panel what i'm going to do now is i'm going to create what's known as a grid panel and i'm going to add my courses into the grid panel and then render the grid panel in the main content panel so i'm going to say the following i'm going to say coarse and then underscore panel is equal to and this will just be grid panel you don't need to import anything you can just say grid panel like that now this allows me to pick the row and column that i want to insert an item at so now rather than self.content panel we'll just call this coursepanel like that so now after we pass the component that we want to render in the panel i need to choose what row and how long or how wide this component should be so i'm going to say row is equal to and right now i'll just go with 0 but i'm going to change that in one second i'm going to say call underscore xs equals 6. now what this is actually saying is when the screen is extremely small or larger than extremely small extra xs stands for extra small then i want this element here to take up six rows or sorry six columns of the 12 possible columns in a row so a little bit confusing if you've never seen this before but in a grid we have 12 columns now we can have a component taking up any number of those 12 columns so i want this to take up six of the 12 columns which means we can have two components in each row so i'm going to place two components on each row each of them is going to take up half of the row which means that if i have more than two components they can't all be on row zero so the first two will be on row zero the next will be row one the next will be row two etc etc so the way i need to fix this is i need to say 4i comma course in and then this is going to be enumerate and this will be courses so this way we can get access to the index as well and i'm going to say that this is going to be the string of and this will be i divided by 2 or i mod 2. now i think that's correct let me just look at my cheat sheet over here that looks good to me so the idea here is as soon as we get to the second item or the second index that will be the third item which means that that will then move on to row number one because two integer divided by two is one whereas when we have the first item which is index zero and the second item which is index one then we're gonna be on row zero so this will just update based on the number of the item that we're on hopefully that makes sense but now that we have that we need to add the course panel to the content panel so i'm going to say self.content panel like this dot and then this will be add component and we'll add the course panel like that and i think that's pretty much all that we need so let me go to home or i actually don't need to go to home but i'm just going to run the page now and let's see if we're getting our layout a little bit nicer so let's go to view courses and now notice we have python and we have javascript it's a little bit messed up so let me take a look at what's going wrong here but we should be able to fix this fairly easily so i've made a little bit of a mistake here i've said call underscore xs when instead i wanted to say width xs what i was explaining before was the width i just had call there instead so we need to go with with underscore xs and this will then set the width of that item as you can see before we had kind of messed it up when i said call xs equals 6 what that meant is start in the sixth column and so that's why we were getting that problem okay let's try this now and let's see if this is good and let's go view courses and that is much better nice and we're getting a little bit of spacing between these two courses now what we need to do is we need to make it so when we click these buttons something is actually going to happen all right so let's get out of this here let's stop this application and let's now make a checkout page that allows us to buy a specific course so what i'm going to do is go to app i'm going to make a new form we know blank panel and we're going to call this checkup so let's rename this to checkout like that now let's just start designing what the checkout's going to look like and then after that we can make it dynamic so we can pass the price and all the stuff we did like with course item so let's start by adding two column panels here i actually want these column panels to be side by side so where's this i'm gonna go to the other side of it so notice they're taking up half the screen the first panel here i guess i can just leave it as column panel one that's fine this is going to display the information about the course that you're purchasing so we'll have the name the image the description then to the right side i'm going to have the price of the course you know it's a rating it's money back guarantee thing and then we'll have a buy button we'll also have a back button that allows you to go back to view the rest of the courses so inside of this first panel right here i just want to make this a card so i'm going to say card like that let's make this guy a card as well and now let's add a label and this label is going to be the name okay so we'll say name underscore label like we did before now for the content we can just put name right now that's fine we want to make this in the middle so let's go to layout let's go to text center font size maybe 24 is fine that's okay for right now then under there i want an image so let's go with image like that let us call this image underscore content and we won't have a source this second and then we will have more text this does not need to be rich text it can just be a regular label and we will call this self dot description underscore label for the text we'll just make this be description we'll align it in the center and for the font size one a bit smaller let's make it right here let's make maybe 14 just so it's a little bit easier to read okay so this will be information about the course then on this side it's going to be purchasing the course so let's add a rich text label here and let's call this actually i don't want to make this rich text let's just make this a regular text label so let's add regular text right here let's call this the price underscore label for the text let's go with buy or actually we can just put the price i guess we'll go with 49.99 just as some filler text let's make this bold let's make it nice and large make it size 45. let us make it in the middle as well and then do we want to underline it that's fine right now okay so 49.99 under there i want to put the rating so i'm going to go with a actually we're going to go with a label and we're going to have to go with a bunch of labels because each one of these labels is just going to have an icon and this icon will be a star so i'm going to go to my icon here and i'm going to say star so we'll put a star like that and that should be fine but i want to make this star a bit bigger so i guess we'll have to go with font i'm curious if i make the font bigger okay it does make the star bigger so let's go with font maybe 30. okay now let's copy this label and let's paste it and let's put it on the same line as this and let's do this five times we're just going to say it has a five star rating to start so let's add that in oops want this over here okay and one more we'll go right there perfect so we now have our five stars i could try to make these a bit smaller nah you know what that looks fine to me let's add some more text this will go right underneath let's call this rating in lowercase and then for the text we'll say five like this five star rating exclamation point make that bold make that in the center make that a bit bigger let's go 24. i keep putting in the wrong thing let's go 24 okay nice and then underneath this i want to have a buy now button that is nice and large so let's go with a button let's go right here let's make this the secondary color so let's go to roll let's go secondary color we want this to say by in all capitals now exclamation point that will be bold and the font size will be 40. and ideally i would like to make these the same size so let's actually add a spacer in here the way that we can do that is we can take a spacer and just put it right in between and then we can make that a little bit smaller and then these should hopefully be the same size now i could also add some more text here i'm just keeping it simple doesn't look exactly like the demo but that's fine you guys can modify this if you want so now we have the buy now button i'm going to actually call this the buy button like that we have this right here oops how did i do that i didn't mean to drag that out okay let's put that back inside there okay go back in the card there we go uh this is called the price label this is our buy button this is the five star rating this is our description this is our image this our name and we're all good okay so the point of this checkout now is that we want this to be dynamic so this will work for any single product or course so i'm going to make this a custom component and make this form available as custom component add property we need the name of the course we need the we're going to go with price of the course we need this is going to be number other than price we're going to need the description and actually you know what i'm going to do this a little bit differently i'm going to get rid of all of these and i'm just going to take the id name of this and what i'm actually going to do is i'm going to call from the checkout my server to give me information about this specific course so rather than passing it all through all i need to do is just have the name of it i pass the name to the checkout and the checkout will get the information from the server that's going to be a better workflow for us so we'll do that in one second i do want to add a button here though and this button i want to allow us to go back to the view courses page so i'm just going to call this the back underscore button like that oops back button okay now what i want the text to be is just back okay now for a line yeah i'll make that center we'll make this the primary color and we'll add an icon as well that goes back so i think there should probably be a back actually let's just go arrow and then like that and that kind of represents that we're going to go back nice we'll add the binding for that in a second so when we click it it will do something for now let's go to code okay so i'm inside of here now what i want to do is i want to call the server and get information about a specific course that course is going to be the id name now the id name is just going to be the id name of the course that i want to get the information about but let me go to course details here and let's change this from get course details to get all courses and then let's make another function here let me just copy this and this will be called get and then course and then details like that okay so inside of here what i'm going to do is return information about one specific course not about all of them so instead of this i'm going to say dot get and this is going to be get and then course underscore name and i need to take in a course name here okay i think that's all i need actually i need to change this to say id underscore name just so that we know we're referencing the id name call so if you want to get one specific row from the database then what you do is you put the name of the column you want to query by which is id name and then the value you're querying with so in this case it's going to be the course name this will give me one row so i can then return that anyways i need to change a few things now because i rename this to get all courses so i'm going to go to uh where is it courses like this and i'm going to now change this call to say get all courses okay so that's good for that now that we have that i'm going to go to course item or not course item i'm going to go to where were we checkout all right so now i'm in the code for checkout so what i'm going to do is just take in the id name here which we need to pass to the checkout i'm going to make a method and i'm going to call this method update underscore form this will just take in self and id name and then what we'll do is we'll update the values in our checkout based on what we get for the information for the course so i'm going to say self dot update form i'm going to pass this the id name i'm now going to call my anvil server so i'm going to say course is equal to anvil dot server dot call we will call the get course details and then we'll pass the id name okay now we can update all of our fields so let's start with the name self.name.txt this is going to be name underscore label is equal to and then this will be course at and then name like that you can see my cat has decided to join me here next we're going to go with self dot and then this will be description label dot text is equal to course at and then description then we're going to have self dot price underscore label dot text is equal to and this will be an f string and inside of here we're going to put a dollar sign so let's do that and then this will be course at price and then usd okay and then what else do we have we have the image so self dot image content dot is equal to course at image okay so that should now update our checkout so that is all good the next thing that we need to do is we need to make it so that when we click the buy button it actually does something right it allows us to buy now we can't quite implement that yex we need to do the stripe checkout but i will add the method for that so let's go to buy now and let's go to click and now we have the by click method so when you click that it should actually bring up the stripe integration thing and allow you sorry to uh to buy this okay next what i'm going to do is i'm going to implement the back button so we're actually going to need to pass here is something to the checkout that allows us to go back seems a little bit weird but we need something that's going to kind of delete this checkout component and go back to where we were so what i need to also take here is back so we're just going to say back underscore button underscore callback which means when you press on the back button what do we do well we're just going to call this function so let's go to design let's click on our back button and let's go to click and then what we're going to do is pass a function to here which will be called back button callback and i will say self dot back underscore button underscore callback like that that's all we'll do inside of here we'll just call whatever was passed now i need to add my comma again because i keep forgetting that and now we are good with the checkup now we can't quite show the checkout because we need to actually pass the correct information to it so let's go to our course item would it be course item i don't know if it's going to be course item i actually think it's going to be in courses and notice how in courses what we actually need to do when we create a course item is we need to pass a button callback now the button callback is what happens when you press on this button right here so we need to now pass a function to course item that we can press or we can call when we click on that button so i'm going to go to design here i'm going to go to button one and i'm going to make a click so i'm going to go here and i'm just going to say self dot and then this is going to be button callback and we're just going to call that that's it and remember here we're taking button callback okay so let's go to courses and now let's create that function that we want to pass alongside every single course item that brings us to the checkout so i'm going to say define and i'm going to say let's go render underscore checkout now this is going to be self and this will take in our course underscore name okay now what we will do here is we will simply say self dot content panel dot clear and then self dot content panel dot and then this is gonna be add component and the component that we're gonna add is actually the checkout and we're going to pass to the checkout the course name so we're gonna say course name we also need to pass the function that we want to call when we go back which means that i need to make a back function i understand this is confusing i'm going to stop in a second and go through all of it but let's just code out some stuff right now so i'm going to say define back self and this is just going to say self.content panel dot clear and then self dot and then load courses like that okay now here i'm going to pass self dot back like that lastly i need to import my checkout so i'm going to say from dot dot checkout import check okay so let's just take a quick pause and then we'll continue what we've done is we've made this back button now what this back sorry function does is it's going to clear the content panel and then just reload the courses the point of this is that from this component from the courses component we are actually going to be showing the checkup so just like the base page is showing the home page the home page shows us the courses page and the courses page now shows us the different individual courses when we click an individual course it's going to load the checkout from this component and then if we want to unload the checkout so go back to the courses page we need to get rid of that from the screen so we clear that from the content panel and then we reload the courses on the screen great now what the render checkout method or function whatever you want to call it is going to do is it's going to be passed to our individual course items as the button callback so when we pass this function there and then we press the button to purchase the course it's going to clear the content panel and then render the checkout for that specific course that's why we created the checkout right so we'll pass the course name and we'll pass what we need to do if we click the back button which is call this function right here and then we'll be all good okay so hopefully that makes a tiny bit of sense what i want to do now is actually implement the button callback for my course item so what i'm going to do is go here and i'm going to say button underscore callback is equal to and then this is going to be self dot and then this will be render check it now i'm not going to call render checkout i'm just going to pass the render checkout object which is a function so that i can then call that function from inside of my course item so let's go to course item now and what i want to do is for my button click i want to say self.buttoncallback and then i want to actually pass to the buttoncallback the name of the course that i want to render the checkout for so i'm going to say self dot and then i'm actually just going to use the let's go with name underscore label and then this is going to be dot lower now actually sorry dot text and then dot load so the idea is that i'm storing the name inside of my name label so i'll just grab whatever that name is and i'm going to convert it to dot lower the reason i'm making a dot lower is because from my checkout i use the id name right i don't use the um what do you call the actual display name and so i'm just going to use the id name to get access to the course because i know that is in all lower cases okay hopefully that makes a tiny bit of sense let's run this and i'll do a quick recap of what we've done so far so i'm going to run we're going to go view courses we're going to click purchase and we get an error it says rich text object has no attribute text my bad we've made this mistake before i just need to change text to content so let's go back to course item and notice we're using text we're just going to use content like that now let's run and let's see what we get okay so let's click view courses let's go purchase and none type object is not callable okay we're getting an error here i guess that is from self.buttoncallback so it's saying buttoncallback is equal to none i'm not sure why we're getting that okay i'm sure now the reason why we're getting that is because i'm not storing the button callback so i need to say self dot button callback is equal to button callback so that from inside of here when i try to access it i still have it okay hopefully that makes sense i just because we weren't storing that we're only passing it as a parameter now what i'm going to do is press run and let's try this again okay let's go to view courses let's click purchase notice it brings me to the checkout so it's 37.99 for javascript now the back button callback is not working for some reason so let's go and fix that inside of check it okay so inside of checkout we have where are we we are calling the back button callback it looks like the back button callback we are never storing so i'm going to say self dot back button and then this is going to be call back okay back button callback is equal to back button callback but i also am not sure if we're actually passing back button callback to the checkout so let's try this where are we let's go to courses uh wait courses where's courses right here okay now inside of our render checkout we're saying self.back okay that is what we want so let's now run this and let's see if this works when we go back okay so let's go view courses let's try to view the python course okay let's go back and checkout object has no attribute back button callback okay i thought i fixed that problem but let's try this again and see what we're getting okay so we have self dot back button i spelt it incorrectly of course that's the mistake okay let's run it again and let's hope it's going to work this time the app has changed since you ran it click here to restart okay let's restart that's fine okay view courses go here go back it brings us back perfect so this is all working now we need to do is set up the buying and the ability to view our different courses once we are signed it we're in the home stretch here if you've made it this far let's keep going we are almost done all right so we're back in the code we're going to continue now and we're going to make it so we charge the user when they click on the buy now button using stripe first thing we need to do before we do this is integrate with stripe so i'm going to click on the add button here i'm going to click on stripe and it's going to open up this page right here all right so what you can do from this page once you've added stripe is you can connect a stripe account now you don't need to do this and i'm not going to do this and when you don't do that it just by default will run this in test mode which means you're not actually going to charge anybody it's just giving you the dialogues and simulating you charging people but it won't actually charge any money if you do want to charge you need to connect a stripe account there's not really anything different that you need to do you just have to do a bunch of stuff through the stripe website and then connect the stripe account i won't explain that it's pretty intuitive for now let's continue okay so we're at the checkout and when we click the buy button we need to make sure we're signed in before we allow the user to buy because if they buy something and they're not signed in we have no way to associate this product with their account so what i'm going to do is i'm going to check if we have a user signed in so i'm going to say if and then anvil dot users dot get user equals equals none then what i need to do is ask them to log in so i'm going to say anvil dot users dot and then log in with form i believe that's what we had then what i'm going to do down here is check again if they're logged in because they could potentially not log in from this form so i'm going to say if and then it will go with anvil dot users.get underscore user equals equals none then i want to pop up a dialog window telling them that they need to sign in and to try again so i'm just going to say i guess do we want confirm i think i have something for info one second let me let me do this okay we actually we have an alert that we can use and we can use the alert that says please sign in exclamation point and then we can just return from here so pretty much by the time we get past this return statement we know that we have a user signed in so now that we know that we have a user signed in we want to bring up the stripe dialog that asks them to input their payment information and then allow them to pay so i'm just going to say that user is equal to anvil and then this will be users like this dot get user and in fact we can actually do this right above this if statement and then we can put user instead of anvil.getuser again so then down here i'm going to first check before i actually let them pay if they already own the course so remember on our user table where would that be right here we have this new field that i added called columnate i want to call this purchased underscore courses good job we check that so make this called purchase course purchase courses sorry and then this is a simple object that's going to have a list inside of it the point of this is it's going to store the names of courses that we have access to so in this case in checkout i'm going to check if the user already owns this specific course so i'm going to just go up here and i'm going to say self dot course underscore name is equal to id name just so that i have that access in an attribute and i can then use that down here and i'm going to say if user and then this is going to be purchased underscore courses so i'm just checking to make sure they have this attribute and we're going to say self dot and then it's going to be course name is in user and then purchased underscore courses then what i want to do is i want to alert them that they already own this course so i'm going to say alert and if we could spell alert correctly that would be great and then you already own this course exclamation point and then again we will return so this is another check to make sure that uh what do you call it here that the user doesn't already own the course before they purchase it all right so now that we've got through this we've checked that the user does not already own the course and they are signed in we're going to import stripe it's just going to say import stripe like this again you need to add stripe for this to work and then we're going to charge the user using stripe so we're going to say token comma info is equal to and this is going to be stripe dot and i got a check not strike but stripe dot and i believe this is just check out and this is going to be dot get underscore token the amount is going to be equal to the self dot and then course at price and what i'm going to do is i'm just going to go here and notice how it says course here i'm just going to say self.course is equal to course so now we have access to all of the course information from this course variable which actually means i don't need to put the course name here i can instead when we check for the course name i can say self dot course and then just id underscore name like that that's going to be a lot better anyways point is we now say self.course price that is going to be how much we want to charge them then after this there's a few other things need to pass we need to pass the currency which is going to be in usd we then want to pass the title which is going to be equal to the course title so i'm just going to say course like that and then this will be the name so we can go like that then we're gonna get the description so i'm going to say uh the description is equal to and then this will be course at and then description if i can get this inside of the correct square brackets so let's do that this also needs to be self.course and let me close this so we have a bit more room okay come on close that nice so we have tokeninfo equals stripe.checkout.gettoken amount self.course price currency usd title course name description is sorry this needs to be self.course as well description is going to be self.course and then description and that's actually all we need for right now now what this is actually going to do is it's going to pop up a checkout window that's going to collect all the payment information from the user then it's going to store that payment information using something called a token the token is just kind of a unique string essentially that we can pass to the back end of our server and then the server will actually charge the user the reason why we need this is because it's not safe to charge the user from the front end we can collect their information and then we need to pass that information to the back end where they then will be charged so what we're going to do after this is we're going to say anvil dot server dot call and then this is going to be charge underscore user and what we're going to pass is the token as well as the email of the user and the name of the course that we're charging them for so we're going to say user and then this will be at email like that and then after this we will simply pass the self dot course and then the name like that okay now we haven't yet set up charge user we're going to do that in a minute what we want to do here though is after we try to charge the user we need to alert them that this was successful or this was not successful so we're going to say alert success but we're going to put this in a try catch because if this is not successful we need to tell them that something went wrong so we're going to say accept and we're going to say alert like this and then something went wrong exclamation point okay so that should be good for now that's mostly our front end done what we need to do now is set up the charge user api or root or backend or whatever you want to call it in the back end in the server so that we can actually call this so we're going to go now to our app we're going to make a new server module and we will call this rename let's go with purchase maybe it doesn't really matter what we call it but let's name it something that makes sense can delete all this we can comment out this and then we need to call this charge user charge underscore user now let's remember what we were taking that would be from checkout we want the token we want the email and want the course name so we're going to say token email and then course underscore name all right so from here we're actually going to charge the user now the way we need to do that is we have to create a stripe customer the striped customer will store the payment information of the user which it will get from the token and then we can use the stripe customer to charge the user's credit card so we're going to say stripe underscore customer is equal to anvil dot stripe dot new customer and this is going to take in the email and the token okay now make sure you have this imported here anvil.stripe otherwise that won't work okay now that we have that we are going to actually get the price of the course we want to get the price of the course from the back end to make sure the user didn't manipulate the price when they sent the request to this url so what we're going to do is go to course details and i'm just going to make a route here that's going to allow us to actually get the course price and we could actually you know what now that i'm thinking of it let's just do it from purchase because it's going to be very easy to do this i'm going to say the price is equal to and this is going to be app tables and then this will be dot courses and then dot and i believe we use dot get and we can get now by the id underscore name equal to the course name because the course name will be all lower cases then we want the price so we'll just put price like this and it should give us the price now we're going to say result is equal to and this is going to be stripe customer dot and then i believe we use charge now inside of charge we're going to pass the amount which is equal to the price and the currency which is equal to usd okay now we want to just print to the result so let's print results like that and we'll see if this was successful or not okay now we do need to after we do this give the user access to the course but i'm going to do that in a second i just want to see what the result is first and then we can show how we actually give the user access to a specific course so let's run this and see what we get okay running running running view courses let me go here purchase all right let's click buy now notice i need to sign in so it gives this to me i'm going to sign in all right looks like that didn't work okay let me sign in with google that time it worked nice now it brings up this javascript learn javascript and become a pro i'm going to enter my payment information click pay and we'll see if it works okay so there we go by the way if you want to enter payment information you can just enter this and it should work for you what i have here and obviously whatever email you want i'm going to click on pay we get the little check mark give it a second and then we get something went wrong okay so something went wrong which means that we hit that accept block so let's now actually log that exception so we can see what's going wrong and then we can continue from there so let's go to checkout let's go to alert and let's go accept exception as e and this is going to be sorry capital e and this will be lowercase e and we'll go something went wrong and rather than something went wrong let's just put e here so we can actually see what this is equal to and in fact we might have to go string e otherwise we might get a problem okay so let's try this again and let's see what the exception actually is okay view courses go here buy now sign in with google okay for some reason i have to sign in twice we'll look at that bug in a second okay let's enter our stuff and i'll be right back okay so i'm going to hit pay let's see what we get now and none type object is not subscriptable key price okay so the problem is coming from our server i actually think i know what this is let's go to purchase and it's saying that we cannot get the key price from a none type object so app type apptables.courses.get and id name equal to course name is not giving us the correct price there's a few things that could be going wrong here let's go to checkout though and let's see we're saying self.course name the problem is i need to pass id name instead of just name so let's change that now so that we're actually getting the id name when we're trying to look up the course let's run this and let's see if this is going to work this time again we'll look at that double log in issue in a second so let's go to javascript let's go buy now let's sign in okay okay so that time it actually worked so i guess we were just having glitch previous times go tim gmail.com i'll enter the payment information and be right back okay let's try this pay our 37 cents let's check mark and fingers crossed what do we get this time amount must convert to at least 30 pence 0.38 converts to approximately 0.28 amount to small request id um okay i'm not sure exactly why that is happening so let's have a look and see what's going wrong now okay so i've just fixed the problem here what i actually did is just multiply the price by a hundred for some reason when i showed the price uh here it was showing uh 37 cents rather than the actual price which is 37.99 so i just multiplied the price by 100 here inside of the checkout when i'm doing the stripe checkout and then inside of my purchase on my server module i multiplied the price by 100 as well just to ensure that they were going to be the same so that seemed to have actually fixed the problem for me and make it so that this was working anyways let me run the code and show this to you again just multiply your prices by a hundred and you should be good to go so let's go view courses let's go javascript let's go buy now sign in okay looks like the sign in was working let's enter our information okay pay 37.99 let's hit that and let's see what we get now okay all right and we get success perfect that looks good okay so what i'm going to do now is i want to look actually at what our output was okay so our output was live object anvil dot stripe dot charge when i printed if we go to purchase the result right here now inside of result we can actually see if the payment was successful by accessing a specific key this key is actually going to be called success or is it success i actually believe it's called result and then if result is equal to success that means that this was successful if it's equal to unsuccessful well it was unsuccessful so what i want to do is i want to check to make sure that the result was successful and if it was successful then i'm going to give the user access to this course okay so i've actually been making a little bit of a mistake here i've been trying to do this from the back end from the server when i actually need to do this from the front end so i'll show you that in a second but for now what i'm actually going to do is i'm just going to check if the user already owns the course inside of the back end just to make sure i don't charge them if they do already own the course so i'm going to say user is equal to and then this is going to be anvil dot users dot get underscore user and i'm going to say first of all if and we'll go with user at purchased underscore courses is equal to none then we're going to set this we're going to say user at purchased courses so let's go like this is equal to an empty list so the point of this is that for some users they may not have had their purchase courses list initialized yet because the default value is just none so if for some reason the user doesn't have that initialize we need to initialize that because then the net next thing that we're going to do is we're going to say if and then this is going to be course name is in user app purchase courses so let's go like this purchase courses like that then what we want to do is we want to simply return so we want to stop we don't want to charge the user because if we charge them then that means that they would have been double charged for a course they already own so we just return directly from there we don't end up charging them however if they don't already own the course then we can charge them so we're going to charge them like that and then after we charge them we'll give them access to the course so we'll simply say user and then this is going to be at purchased underscore courses is going to be equal to and we'll go with user at purchased underscore courses plus and then we'll put a list here and inside of here we're going to put the name of the course so we're going to say course underscore name like that so then this will add that to their purchase courses and they will have access to the course okay so that should be good what i want to do is go back to courses back to checkout actually and i'm going to go here to info and i'm just going to print out info after i do all this and actually i'm going to print out info and then result because this will actually tell us if we're successful or not so let's go here and let's run this and let's see what we get okay so i'm going to go view courses and i'm going to go purchase and i'm going to click buy now sign in with google okay and let me enter my information and then i'll be right back okay so let me click pay and let's see what we get fingers crossed here that nothing's going to go wrong and we get success perfect and then if we look here we get a key error on result so i'll fix that in a second anyways point is we now should have for our user access to that course the way we can check that right now at least is we can go to data we can go to users we can scroll over and we can see that we now have javascript in the purchase courses so now if that's in our purchase courses we should give them access to it which is what we'll do but first let's go to checkout and let me just print info rather than info result because for some reason we were getting an error there so i'm going to run this one more time i just want to look at what info is giving us okay so let's go view courses let's go purchase let's go buy now sign in okay and let me enter the information and i'll be right back okay let's click pay and let us see what we get for info when we print it out let's see we just get the email okay so that's fine we don't even care about that i guess i was wrong to even be looking at the result variable everything is good okay so we've purchased that now that we've purchased that we should have access to that course as well and now what we want to do is make it so that once you're signed in you can actually access the different courses that you have so how are we going to do that well what i'm going to do here is i'm going to get rid of printing info and i'm going to go to my my courses page and this is where we're actually going to show all of the courses that we own so i'm going to go to courses and i'm going to copy this load courses function that we have because we're going to do a very similar thing here except we're only going to load the courses that we have access to so we're going to go to my courses i'm going to paste this in i'm going to say self.load underscore courses like that and then what i'm going to do is rather than get all courses i'm going to say get underscore my underscore courses like that now we'll do the exact same thing in terms of rendering these courses onto the page except this time we're just going to get my courses which means that here it's only going to give us courses that we have so i'm going to make a new server module here and i'm going to call this course oops that means do that we want to call it here course underscore unlocks and then this is where we're going to put that call or that function that is going to be get all my courses now for some reason i can't highlight this okay let's get rid of that let's comment this out and now let's go with get my courses get underscore my underscore courses like that and we don't even need to pass anything here because we can just get the current user from this function so i'm going to say user is equal to anvil dot user or dot users dot get user we'll say if user equals equals none then we'll just return an empty list because if you are not logged in you have access to no courses otherwise we want to loop through all the courses that they have get those from the database and then return those so we're going to say that courses is equal to this and then we're going to say for course in user and then this is going to be purchased underscore courses like that now one thing that i want to do too is i want to make sure that we have access to this because if for some reason we don't have access to this then this is going to cause an error so i'm just going to go up here and say if user purchased courses like this because again this attribute could not be initialized so i'm going to say actually if not user purchase courses then just return an empty list otherwise what i'm going to do is for course and user.purchase course i'm going to get the information of that course and then simply add that into this courses list so i'm going to say course underscore info is equal to and this is going to be app not files but app tables dot courses dot get this is going to be id underscore name equal to course because remember this is going to be a list of strings then i'm simply going to add course info to courses so i'm going to say courses dot append and then course info like that and then we will return courses like so okay so that's all i need for get my courses now what i want to do is i just want to loop through all of them inside of my courses and then create the items like i would before so actually i think this should probably be fine i can say for i comma course in enumerate courses this should give me access to each of my individual courses i should then be able to show them on the screen and be all good the only thing is rather than showing purchase for i want to instead show view content because now you own the course you don't need to purchase it anymore and for the button callback what i'm actually going to do is we're going to have to put something else because it's not going to be self.rendered checkout we'll say self.rendercourse and we're not going to actually make any content for these courses so for now what it will do is just bring us to an empty page but we will make a function called render course so i'm going to say define render underscore course self and then this is going to be course underscore name like that and then what this will do is say self dot content panel dot clear and that's all we'll do for right now so we actually would normally show the course but since we don't have a course to show because we don't have any content for it we'll just clear the screen that kind of indicates okay you know we were viewing the course all right so let's just try this out we might have a few problems because i haven't looked through everything yet but yeah let's see what we get so let's go and run this and let us see what we get with my courses okay so i'm going to sign in i'm going to sign in with my google i'm going to click on my courses and we get an issue what is the problem list object has no attribute search okay i can see why we're going to get that problem i need to remove the dot search here because what we're going to get instead is a list of all of the courses we already have we don't need to search through them because it's not giving us that client readable view it's just giving us the information from the courses so let's run this now and let's see what we get okay let's sign in let us sign in with google let's go to my courses and course item is not defined okay so we need to import course item so let's go ahead and do that we're going to say from dot dot course item import course item i don't think i'm going to have any more problems although you never know fingers crossed let's run the code let's go to sign in let's sign in with our user let's go to my courses and notice we have javascript and python because while we both we bought both of them now i'm going to remove this in a second if we click view content notice it just clears the screen because that's what we made it do awesome so if we go to view courses let's try to purchase a course now that we're signed in notice says you already own this course that is exactly what we would expect let's try with python and you already own this course okay we are pretty much done just going to fix and polish up a few things and then we're going to handle some different urls and i'm going to show you how to deploy this so let's go to my courses let's go to design let's delete that label because we don't want that anymore and then there was something else we're going to do yes we were going to handle the urls so what i want to show now is that if i go to publish what i can actually do is publish this application and this allows me to have a temporary link sunnylittlewatch.anvil that i can actually use to view my application now if you have the pro version of anvil or the business version or the individual plan in this case you can switch to a custom domain and that means you can actually get whatever domain you want here but since we're just using the free version it just gives us kind of a random domain that we can use anyways i'm going to go to this link you're going to see that it shows us the website this is now live if i go here you can see we're on this website right here the thing is though i can't do something like slash courses right if i do that i don't have a matched url but i want to be able to do that so i'm going to show you how we can handle those different pages in a second for now they'll let you see how this works in the deployed version okay so i'm going to go to sign in and let's sign in with google okay for some reason that didn't work let's try it again let's go to my courses notice it shows the courses because we've already bought them now let me sign out okay let's log out and let's sign in with a new account all right so i've just created an account confirmed the email you can see i'm tim at mailinator.com if i go to my courses i don't have any courses let's actually add some text that says we don't have any courses we'll do that in a second for now though let's go to view courses okay and let's try to purchase one so let's go here let's click on buy now okay let me go and fill in the details and then i'll be right back okay let's click pay and let's see what happens now okay looks like we're good awesome so we have purchased now we go back let's go my courses and notice we have access to javascript but we do not have access to python because obviously we have not bought that sweet so i just want to show you it works on the deployed version you can see this is the url that i'm on okay let me close that let's go back to the anvil editor and let's continue to work okay so i'm going to start by adding that label that says you currently don't have any courses so i'm just going to throw a label right on the my courses page and we're just going to call this let's go with no underscore courses underscore label and we'll say you do not own any courses or something like that okay you do do not own any courses sad face okay and let's make this a headline like that and then what i can do is go to text more let's make it bold let's align it center and we'll leave that there for now now what i'm going to do is i'm just going to make it did i spell this wrong no i think that's fine i'm just going to make it so that when we have any courses it doesn't show this label so to do that i'm going to go to code and then when i load the courses i'm going to say if the len of courses is greater than 0 then no courseslabel.visible [Music] is equal to false okay so if we have more than one course then we'll just make that invisible so we no longer see it okay let's try this now let's run our code let's sign into our account okay we're going to sign in with google and now when i go to my courses we get an error it says no courses label is not defined okay that is most likely because i forgot to put the self beside it so let me stop that let's go to code yep that would be why okay let's go to self let's try this now and let us go sign in sign in with google and my courses and notice it's not showing that label but if we don't have any courses it will show that label i'm not going to show that to you but that will happen okay great so that is all working now the last thing i want to show you is handling the different urls in your web browser so let's go to the base page and we'll do that from here all right so what i'm going to do is i'm actually going to create a new python module inside of this form so just to kind of clarify here all of these different things that we have our forms these are like the front end user interface right we have the design page and the code page but we can just write regular python code inside of a python module that kind of belongs to this form so see where base is i'm going to click on the three arrows i'm going to click add module it's going to add a module inside of here now what i'm going to do is just rename this to urls i'm going to make a dictionary inside of here that's going to reference what url points to what form okay so i'm going to say from dot dot and then this is going to be home import home and i'm going to say from dot dot and this is going to be courses import courses and then from dot dot my courses import my courses okay what i'm going to do now is say urls is equal to this is going to be a dictionary i'm going to say home corresponds to home notice i'm not calling it i'm just writing the name of it and then i'm going to say courses goes to courses and i'm going to say my hyphen courses goes to my courses like that okay perfect so now i have my urls the point of this is just to better organize my code so i'm not defining this right inside of the base form now from base i'm going to import urls so i'm just going to say from urls import urls now i think we're going to need one dot although we'll see if that works or not then what i'm going to do is in the init i'm going to handle the potential different urls that i'm currently at so i'm going to say define handle underscore urls and then what i want to do is say that the url is equal to and this is going to be get and url hash i'll discuss what this does in a second and then i want to look at sorry i need self here as well i want to look at what the hash is and then go to the specific page based on the url hash so first of all what url hash is going to do is it's going to get what comes after the pound sign in our url so we're not going to use the slash to the page navigation we're going to use the pound sign because it's a single page application but the point is that this will get what is after it i'm going to convert this to dot lower so even if you type it in capitals it still works i'm then going to say if the url is in urls like this then what i want to do is go to that page so i'm going to say content panel so self.content panel like this dot clear and then i'm going to say self.content panel dot add component and this component is going to be urls at url like that and then i'm going to call it now this might seem a bit weird if you haven't seen this before but if i go to urls i'm just writing the name of the class right and so if i access the specific url it gives me the class and then what i do is i simply initialize the class and add that as a component to the content panel now i'm looking here to see if anything else if there's anything else that i need to do here doesn't look like i do although what i'm going to do after this is just say else and then self dot go to home so the point is that if you put in a url that does not reference a url that we have access to so if it's not in the url's file we'll just go to the home page and the home page is just going to clear the content panel and then go to sorry where am i clear the content panel and go to home now that actually means that what i can do is rather than putting self.go to home here i can just say self.handle urls and if we don't have a url that's in the urls file then we will simply go to the home page hopefully that kind of makes sense what i'm going to do now is just publish the application because i can only really look at the urls from the publish app i'm going to go to this url here and now i'll show you how we actually go to a specific page so let's go to hashtag and then let us go to what do we want here let's try courses okay now notice when i do that it actually didn't bring me to where i was expecting to go let me try this again and we see that it did bring me the course okay so i just had to hit enter twice there i'm not sure exactly why let's try going to my courses though let me just copy this and hit enter and hit enter again and you can see that now we go to my courses and i am signed in perfect that is all good okay so with that said that's pretty much going to wrap up everything that i need to cover in this video again i will leave a link to clone this anvil project in the description in case you got lost or in case you just want to get access to this project anvil was the sponsor of this video so you need to thank them again for doing that this is really an awesome platform i had a great time making this video and actually working with anvil and kind of prepping before this is a really cool platform to build an entire website from scratch using only python you saw here we didn't use any javascript we didn't use any html or css all we needed to know is python and we actually didn't really need to write that much code considering the type of website we made which was an e-commerce site with payment integration users and everything like that so again a massive thank you to anvil make sure you check them out from the link in the description and with that said i will end the video here thank you guys for watching if you enjoyed leave a like subscribe to the channel i will see you in another one [Music]
Info
Channel: Tech With Tim
Views: 28,464
Rating: undefined out of 5
Keywords: tech with tim, anvil, anvil walkthrough, anvil tutorial, creating user accounts, e-commerce using python, python, python project, diy e-commerce store, e-commerce with python, python course, stripe integration, anvil platform walkthrough, python typing, python typing module, python code, python annotations, pay with stripe, creating e-commerce store, anvil beta editor, python only tutorial, stripe payments, stack development, python stack development, full stack website
Id: NNeT-PhaLZk
Channel Id: undefined
Length: 117min 17sec (7037 seconds)
Published: Wed Nov 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.