Transcript for:
Building Full Stack Apps with Python

welcome to full stack web applications with python yes we're only going to be using python not HTML not CSS not bootstrap not Tailwind just Python and also of course a tool called [Music] reflex did I mention we're not going to use JavaScript either yeah we're not using JavaScript either but we will have a lot of the components that JavaScript seems to be very famous for like those like buttons and certain interactivity that you might actually want in your web app now this is actually really cool because that means our entire application can be built in Python and of course if you get into the infrastructure as code of it all you can use Python for that as well that's outside the context of reflex the idea here is we're going to be handling the front end we're going to make it look great using reflex we're going to make it function great we're going to make it work basically like you would in any web app any modern web app should the other side is the back end how we actually store that data we're going to store it into a database that we control also with reflex now it actually inherits a lot of things from things like SQL model and SQL Alchemy but the idea here is all of it is going to be done in Python and it's going to be done in a way that fits really well with what the front end expects and what the back end needs to do now the other thing is we are going to be doing stuff like user login user registration once we log in we can actually change our components so that there's a different dashboard we can actually write blog posts we can do this all of this is done through python it's actually really really cool in terms of how we might end up doing all of our different projects all of our different applications in just purely python now of course there's a lot of things that we need to learn about this but what you see right here this is all through reflex I didn't have to write anything in the CSS at all to get this sidebar I just went into reflex's docs and I jumped into the recipes here and then in these recipes we see this little sidebar and what do you know hey that looks very familiar to my actual sidebar which is pretty nice but of course I also have user information here I can log in log out I can store data I can retrieve data there's all sorts of things that are really really cool about this now of course this is meant to give you the ability to start building some really cool things and reflex has a whole gallery of super cool things that you can check out and you can draw inspiration from to build out your application I do want to show you more about what it is that we're going to be building especially on the back end so stay tuned to a demo of course if you have any questions please let me know my name is Justin Mitchell I partnered up with Reflex on this series because I think it's a really compelling tool especially for those of you that are just python developers that do want a web application but you don't want to learn all of the things about JavaScript HTML and CSS but rather you just want to stick with python let's take a look at the demo right now in a moment we're going to demo two reflex applications one is a template that we can just grab from The Reflex CLI the other is the actual project we build both of these things take about 10 minutes so feel free to skip it if you'd like otherwise let's Jump Right In now we're going to take a look at a demo of reflex itself first we're going to take a look at how quickly you can do a chat GPT like interface with reflex then we're going to take a look at some of the code from the actual project we build in this course so the idea here is we want to start off with a virtual enironment now if you're on Windows it's going to be a little bit different than this but the idea is you need to create a virtual environment then you need to go ahead and activate it and then you're going to go ahead and run pip install reflex and hit enter this will install all of the things related to reflex itself to make sure that you can actually run and build all of the different code applications that you would want with reflex of course but the main thing that actually comes through in here is the reflex CLI this will allow us to actually run stuff like d-el and seeing that there's this init method now part of the reason I'm inside of this FS python demo directory is because that's what I'm going to go ahead and name my project that's what the init does so if I go ahead and do now reflex and in it hit enter I get a few different options in here the option I'm going to go with is this chat GPT clone so I go ahead and say to this of course is going to give me a template to actually create my own chat GPT clone this means that I need to install open AI just like this then I also need to make sure I have an open AI API key so for example if you didn't have an API key and you went ahead and did reflex run you'll probably get an error here now in my case I actually already exported the open a API key in here so I can actually show you this demo and the idea here is what I can do is open up my local host at Port 3001 in this case that is going to show show me my demo application the one that I just brought in and here it is this is my chat GPT like thing are you great you know something like that and then we can also say something like what is a python function and of course we get a python function here how to install python on Windows this is probably going to give us some fairly good information maybe of course I've got a lot of stuff on that it's a lot easier to install python on on Linux and Mac if you're not aware but the other idea here is I can do a new chant I can do all sorts of stuff and yeah this is just a template this is showing me what this template would end up doing but of course if I wanted to take a look at the code itself and I open it up in something like vs code you will start to see that everything that we just saw was driven through python itself so if we go into this components area we see chat we see hey what do you know message this is showing us the message now some some of these things aren't going to be that obvious right out of the gates right so you may or may not know these things you may already know what text Al line means you may know what padding a top means but even if you don't know what those things mean there's so much documentation that makes it really easy for you to start learning these things and using them and implementing them right away but it also gives us the ability to change how we might want to use open AI right so in here we've got an opening eye State for the various chat the delete Chat Set chat all this in here and of course if we wanted to see the Open aai Class itself we could do a quick search for it on how we end up using various things related to open AI as in process question we see here things related to the question we've got our messages you are a friendly chatbot named Reflex what if we wanted to call it CFE boom now it's named CFE and now we can run it and do whatever we want we can also change the open a model whatever one that we end up using right now is that GPT 3.5 Turbo maybe you want four maybe you want the latest model all of this gives us the ability to just do this right out of the gates that's actually really really nice now of course if you know Python and you know open in AI you know that it's not that challenging to build out something that does the completion the thing that's challenging is building out that user interface and here's an example of that right here code that we can use right away once we understand how to build things in reflex so that brings us to the next part what is it that we're actually going to be building here well we're going to be building a full stack python application which means we will have users that can log in and log out that's a key part of all of this making sure that we can create a user abc123 with an email like some sort of email in here obviously I'm not giving real data here this is just for demo purposes but we can sign up with that user I can save that I can log in with that user and here we go so now we can see articles on here I can go ahead and create a new article this obviously gets saved and submitted in here this new article is now just for this particular user as denoted by the actual email written in there this particular user could then go in and edit things and say updated article right there whatever I'll put some gibberish I can publish it then and then it will go into the general articles in here and there's my new article right there so to make all of this stuff work what we take a look at is the actual code itself so we have a lot of different components that are going on in here so the chat GPT component could be brought over and be used inside of here as well and it being very specific to an end user that's outside the context of this course but once you understand how to build everything that's in here you will start to be able to see how all of that ends up happening and so one of the quickest things we could take a look at is inside of our theme for our app we can actually come into our theme and we can change the accent color in here so if you actually scroll over it inside of vs code you get all of the various options you might use so for example if I wanted to change it from Sky to Violet save that and let reflex automatically recompile which is what it does it might take a few seconds to make it happen but once it does recompile we see that the color changed now this isn't really necessarily that obvious but let's go ahead and change it again to Crimson now I save it once again it's going to go ahead and compile it's going to change everything and then our front end will actually start to look different it quite literally changed the whole thing and I can just toggle dark mode really really easily so doing all of this theming alone takes a lot of work to make it work this well including with dark mode that's a a key part of all of this of course next up what we can do is we can put in contact we can actually fill out a page here with different variables I'm just going to go ahead and add in a few I'll hit submit and then I can actually take a look at contact history I can see all of the people that have sent messages and what theyve sent this of course is because it's tied directly to the database now in the database itself we see models up high here this is all of the database models that are coming through each one of them there's only a few but each one of them has different attributes that you can use this is coming from SQL model and also SQL Alchemy so if you're coming from Python and you know those things that's actually really great if you come from like Jango or something this is not a whole lot different than D Jango it's actually very similar but the idea being that we have these data models that we can then store data into an actual database which is what this sqlite database is right here so of course there's more to it than just the database and toggling themes there's actually the ability for us to do routing URL routing it's actually fairly straight forward so what I've got right here is actually a shortcut to just simply slash login I gave explanations as to why we have these shortcuts in here but the idea being the URL page routing is actually very very straightforward and it's based off of the arguments that are coming through in here and this is also true for our blogs and any any given item that we might enter in here as soon as I go to this blog notice that there's a four at the very end here this is dynamic URL routing as in it does change what shows up based off of the URL route and it does it in a way that's very very logical something that those of you who have done this before will really appreciate how it's approached in here now another thing is when you want to actually have things happen on the back you have this ability to do it with something called state so in this case I have a session State that's injected into a contact state that handles the form we can handle the form data we can submit form data we can grab our logged in user information in here we can then add in all of that data into our database and then we can go ahead and change what's happening with our database based off of whether or not it was submitted all of these things are actually very straightforward inside of reflex there's just a lot to discuss to make sure that this happens so naturally this as a demo shows you the result but it also shows you some of the the behind the scenes of the code itself so I do hope you actually go through the entire course so you can actually start building out all of the things you might want to in terms of building a robust full stack web application and thanks to reflex for making this a lot easier for us python devs even though there is still things that you might need to learn to make all of this end up working and don't forget this is also mobile responsive as well well and it works just like you might expect so let's jump into the course right now now we're going to go ahead and create our full stack python application with reflex the way this is going to happen is of course you have Python 3 installed VSS code installed ideally and then we're going to go ahead and create a virtual environment now hopefully you already know that this is how you can isolate your python projects from each other so that anything you install for that python project is only for that python project not all of them on your system after we do that we need to activate our virtual environment we'll install reflex we'll initialize reflex and then we'll run it that's all we're doing in this section so the idea here of course Windows users and Mac users and Linux users all have different ways on managing the virtual environment after you get all that done then you'll just be using basically reflex Run for the rest of the project with a few other things here and there but that's what we're going to be doing now so first and foremost go into into vs code go ahead and open up a new folder here the name that we give this folder is going to be the name of our full stack python web application project as we'll see in just a moment so inside of this Dev folder here I'm going to go ahead and do full stack python just like that notice that there are dashes and not underscores this will come into play in just a moment I'll go ahead and open this up I'm going to go ahead and use my python 3.12 to create a virtual environment once again you Windows users you might have to use the absolute path to python to make this happen but the idea is soon as you create the virtual environment you'll have this VV folder and then you'll want to go ahead and activate it just like this and then of course if you actually have a Windows you would do something more like this scripts activate and all that so again I assume that a lot of you already know that but for those of you who don't it's actually really really important next up what we're going to do is we're going to use pip which is the python package installer to well install itself and then upgrade it's pretty cool that I can install an upgrade but we want to do this from time to time especially when stting a new project next up we're going to go ahead and do pip install reflex reflex of course is going to be the package that does all of the front-end backend stuff for us in a pythonic way yes it uses other tools to make that happen but the way it does it is incredibly effective as we will learn throughout this whole series next up what we want to do is reflex in it so of course this is going to initialize a brand new project for us notice that it's saying initializing full uncore store python hey what do you know it actually took our original folder name and it is now creating a brand new one based off of that folder name do you remember me saying that anyways so now what we've got in here is the option to pick a template that comes out of the gates with the reflex CLI now each one of these templates has benefits that you can learn a lot from and I do recommend that you explore on your own heck you could even do that right now because there's a lot to it but I'm going to start with the blank one so I'll go ahead and say zero and we're going to take a look at just what the blank application looks like now what I want to point out is several things number one if you're familiar with python already you might be familiar with requirements.txt notice it's already created for you this of course is what we use to recreate our environment from a virtual environment so very similar to like when we ran pip install reflex of course you would do p pipin all-r requirements.txt if you needed to recreate that virtual environment cuz you probably will at some point or at least I hope so next of course is a get Goran here already with a bunch of things that are related to python we might need to improve this a little bit for other python related things but overall I think this is probably good enough next up we got the actual reflex configuration notice that the app name is in there this app name hey what do you know there's a folder with that same app name and inside of that folder there's a python file with that same file name this is done on purpose it's meant to simplify things quite a bit but of course it's going to be different depending on what you name your project folder that's important if you want to follow along with me you want to make sure that you use a lot of the same names through that process and right now would be a good time to solve all of that so this is where we're going to start off with working this is the main project code that we can just use okay so before I touch anything in here I want to go ahead and run reflex run hit enter and of course what we're going to get here is it's going to compile everything related to our reflex application if I save this python file with command s or controls it's going to do it again and then again and again however many times you save it it's going to refresh and automatically do all of these things now if you're not familiar with this process with building web applications it's actually a really nice way to build things so you don't have to restart the server all the time but let's go ahead and take a look at what we get out of the out of the box so I'm going to go ahead and open up Local Host here in my web browser of course I'm using the arc web browser but the idea here is this is what we've got so of course this is just a hello world page and there's a lot of things that we need to continue to do to make this better and we will but what I want to show you that is built in is light mode and dark mode look at that how cool is that right at the gates we have light mode and dark mode that I can just toggle and if I leave it in dark mode and refresh in here it's still working if I can contrl C and then rerun the server again and then refresh in here let's see is it going to be light mode or is it going to be dark mode Let's see if it actually boots up let's go and it's dark mode cool so it actually keeps track of light mode and dark mode for you now if you're new to web development this is not going to be groundbreaking for you at all if you are not new to web development that alone saves you a lot of time and a lot of code that you might have to write in order for this to get to this point which is actually pretty sweet now the next part this is the part that might start to be confusing for those of you who have worked in web development before whether it's using a fast API application a Jango application or otherwise this right here is actually going to the front end this actually handles how the front end works so we're going to play around with this a lot and in the next part we'll see more of it but what I want to point out is this rx. color mode. button the position what if I change right to left save it let's go ahead and refresh in or actually go back to our browser we don't even need a free refresh it does it for us we see that it moved if I change it to bottom left save it we will see that it moved pretty neat huh okay so again these things are not that impressive unless you have experienced trying to build these things yourself in which case they are incredibly impressive and it's really cool that everything's happening right in here this is all of the code that we've written this is all of the code that's managing all of that stuff and so of course we want to explore this quite a bit more the first thing I want to explore is something related to State and pressing buttons and how we can handle that so we can increment and well make changes to what's happening on the browser like these Dynamic changes that you would want to make now we're going to take a look at how we can do some Dynamic content and reflex what that means is we're going to be able to press a button and something else on the page is going to change without us refreshing the page hey much like this light dark mode thing but before I do that I actually want to implement Version Control which you can do in this right here you can actually initialize a repository and it comes out just like that that for those of you who know git is the same thing as doing get in it it's just like that but before I actually commit changes or do anything related to that I noticed that it's saying 4,000 items are being tracked or 4,000 pending changes this is because the default get ignore doesn't necessarily take into account the virtual environment and so I'm going to go ahead and add in that virtual environment now it's about six files great so I'm going to go ahead and come in here and say initial commit and then commit it and we'll go ahead and say yes and there we go so that is the process of tracking your code I will only mention this a couple more times throughout the series but the idea here is I want to make some changes to this fullstack python module now the first thing I'm going to make is I'm going to go ahead and copy this button of check out our docs and I'm going to change this to something like do something exclamation mark save it and now we'll go ahead and take a look at our project and there's our button do something okay so I actually want something to happen so what is that something I want to happen well it actually comes back to the state element here so if I were to put something like let's go ahead and say label equals to this is my label right and then I'll go ahead and use this state element in my text here any any text really so I'll go ahead and do state. Lael and then we'll keep in welcome to reflex but I'll add a little spacing here so I'll explain string substitution in just a second but as as far as the label is concerned if I refresh in here now I see that it says this is my label well what if I don't want it to be this as my label I want it to be something different well I can actually Define a method inside of here and this method itself can change this label so I'm just going to go ahead and call this change label and it'll take in self as an argument because this is a python method or a function attached to a class and I'll just go ahead and do self. label equals to cool label or something like that it doesn't really matter the part about this is I want to change the value that's coming through in here to that new value by clicking this button so let's take a look at how that's done well we've got this RX button here what we can do is we can actually put a event handler on here there's all kinds of event handlers onclick is one of them notice that the actual vs code also showed as on double click C what we can do is we can use that state element again and then literally call the function that's on it which was simply change label right so in here we've got our label down here we've got change label simple enough right so if I save that and click on this what do you know it says cool label if I click on it again it does not say the old one so if I wanted it to say the old one we'll go ahead and say you know original label was basically the same thing but I'll just go ahead and put it twice and then self. labels that but we'll go ahead and say if self. label equals to cool label. period then we will not change it to that otherwise we'll go ahead and do something like self. Lael equals to self. original label great what do you know very simple conditions let's come in here do something cool label hey now it's flipping back and forth fantastic so this is how we can dynamically update the state now this is not that practical of an example in the sense that you probably would never do something like this but the point is it's extending a lot of the browser capabilities so when it comes to this onclick method here can we do this somewhere else right so let's say for instance I'm going to put it in this text here I'm going to go ahead and put onclick change label I'm going to do that same thing I'm not going to put it on this button I in fact I'll comment out this button so it's gone so get started by editing right this text mostly makes nonsense to me so let's go ahead and do it click on it what do you know it actually changes it does the same exact thing so this Dynamic of an onclick method is something that JavaScript does really really well but we're not doing JavaScript here we are just doing python it all gets compiled in certain ways and certainly does use JavaScript on the front end but we don't have to do anything with it it just does it and so this Dynamic is really one of the coolest things about reflex the fact that I can change things like this let's see another example that's maybe a little bit more practical maybe not but the point is we want to see how we can do more of this Dynamic inside of our applications as we start to build out more aspects to it now we're going to take this Dynamic editing to a whole another level so instead of like clicking some element and doing some editing like that which is not always that practical we're going to take a look at how we can use an HTML form input so I can actually type and change the label that way so it's going to be fairly straightforward but what I want to do is I'm going to clear out this state I actually don't want to have all of this because I want it to be pretty different once I do that I also want to get rid of inside of this rx. text I want to get rid of this onclick method here and I will also get rid of the comments from the button itself great so now that we've got that I also want to change the label to being welcome to reflex we'll just go and paste it in there like that and I'll go ahead and update this a little bit by getting rid of this right here I'll still talk about the string substitution it's just not something we're going to cover just yet but the idea being that if we come in here underneath this text here I'll go ahead and do rx. input and then we'll pass something in as far as the input is concerned now the first thing that I want to do is I want to have a different Handler before we did that on click Handler there's another one called on change and you can actually create a Handler that will listen to when changes happen so what does that mean exactly well if I come in here and say handle input change that is typically how I name these things so I'll go ahead and say something like handle and then underscore we would do something like title input change or something along those lines where I put handle in front so I know that this is going to handle some sort of event and then of course the event is near the end so I basically say handle what's the input itself and what's happening so that's kind of how I name these things but the idea here is we'll call it handle input change it takes in two arguments the first argument since it is a method of the state class or a function of the state class has to be self the second argument is the actual new value the value that's being changed so what we can do then is we can say self. Lael equals to that new value pretty fantastic so with this in mind I can come back into my input here and I can do state. handle input change and that's it so we just declared an input we have a way to handle that input that handling of input does have effect on some other place so let's go a and save this and now it says welcome to reflex I'll now say welcome to CFE pretty cool right but if I refresh the page the input goes away the change the actual label did stay the state did stay which is pretty interesting but what we want to do is we want to have the default value in here as well so that means that in my input I can break this down a little bit I can now say you know you might think oh I'll put value in here as state. label which seems like it's right especially if you know inputs on HTML so in in the case of HTML you've got input type being text and then you can say value equals to my value and then you can actually have different handlers on here so that's essentially what this is doing however the way value works with these dynamically updating things is we don't put value directly instead we put default value this will preset whatever the label ends up being so now I can see that those changes are affected and there's my original value here so now I can say welcome to CF and the actual input shows me that and now we're starting to get somewhere with this Dynamic content it's pretty great so it's really just that simple now what we're going to come to learn is there's all kinds of events and all kinds of event handlers so events are pretty much anything that can happen on the front end of your web page so clicks very obvious that is a click event then you think of something like a mouse over so wherever the mouse position is there's a mouse over event all kinds of events in here that are related to just general web pages reflex could then listen for those events to happen and do something related to it we've now seen two examples of that we saw the click of it on click right no big deal there we've also seen now an input event where it's on change when it actually changes the value that's inside of that input now of course we can chain things together like on click as well so I can do state like did click something like that and we can go ahead and do Define did click and then we can print out something like hello world did click or something like that save it and then of course if I save an error that's happening it's going to show up right there you may have to recompile things but if you see that it is compiling at 100% then you're in good shape if you don't see that if you see something different like if I typed out some giberish here it would show you that there's an error in there it show you where it is as well like python should nevertheless I'm going to go ahead and print it out save it it should automatically recompile if for some reason it doesn't automatically recompile just cancel it out and rerun it but the point here is I want to see this did click event happen on the input itself so if we come back in here clicking in the input click click click click click I just clicked it a bunch of times open up that terminal window again there's all those click events that are happening in there as well so that means to me at least that I can do a lot of things in this click event that don't relate to what happens on the front end it doesn't relate to what the user ends up seeing so I'm clicking clicking clicking but this is actually really cool cuz that means that I can do pretty much anything you might think for python itself and it's really tied to a lot of those events and event handlers so yeah a lot of dynamic that we can do a lot of things that we can build out every front end element that you want to render out is a reflex component so if you look at the component library right in their documentation you can see exactly what I'm talking about now what this means is we don't manually write any HTML whatsoever it gets rendered out as HTML but we don't need to write it so if I inspect the element on any given page we can see that it is rendering out different HTML elements in here and so this input right here no surprise is something that we added which was the rx. input the actual input component and then we did not render out the actual HTML element itself now there's many different reasons for this one of the main ones is the fact that we can then handle all of the things related to it we can set the default value we can handle all of the events and all of this happens right inside of python if we did it any other way outside of reflex we would probably have to define the HTML element in some way and then have additional JavaScript to make sure that all of that stuff is working in the way that it should or we use a template rendering system there's a lot of complicated stuff that could go into just this one single element but instead we have the reflex component for it that just shortcut a lot of things so what we're going to do is we're going to use these components quite a bit throughout this course but what I want to start out with is I actually want to recreate my main container element here so the idea being that I actually want to have maybe a nav bar up here for all of my pages I want to be able to navigate from page to page and having a consistent Navar is what I want I want to have that idea so in this case I'm going to go ahead and Define something called my base page and then we're going to return back back well I'm going to stick with the RX container idea here so I'll go ahead and do RX container and something like that now of course inside of python itself what we can also declare is the data type that's coming back so this is a way to declare that data type it is of data type RX component we can also just leave it empty technically speaking this will work but this is better practice to actually declare the data types that are in there so the next thing is we're going to go ahead and replace this RX container with our new base page we quite literally made our new own component for our base container it might work it might not it's probably not going to work as you might have guessed but what we see here is opening up the terminal I've got takes zero positional arguments but three were given now naturally if you know python well you know that this means that the actual function itself needs three arguments in here at least three arguments and once it does it will go ahead and say okay you're good to go now one of the other ways we can encapsulate this is by saying args because these are all positional arguments you can also do keyword arguments which are keyword arguments but if you look in the actual function itself we don't actually have any keyword arguments in other words I don't have ABC equals to 1 2 3 in here or whatever value that might be as soon as I did that would be a keyword argument of course now what I can do then is I can actually see what the data type is of each one of those arguments to do that we just go ahead and say print out type x 4x in ARs and now we can actually see the different data type elements that are in here and there we go so we've got reflex. components that's that first one reflex. components second one reflex. components third one right it's actually giving us the value of all these are by default those components in there and so naturally what I can do is I can unpack all of these in here as well just like that and so what that will do is it will actually give me those components right back if I did have those arguments coming through it's just going to be a blank page if I do have them coming through it's not going to be a blank page right so that's kind of the point here we want to make sure that we have this base page in here but of course for what reason exactly well the first thing is do I want to actually have this button available everywhere and do I want to have it on the bottom left well I'm going to go ahead and say yes I'm actually going to go ahead and change this to being args up here so we've got our bottom left up there so we'll unpack all of the other arguments before that bottom left and sure enough everything's still working correctly the next one is we've got this built with reflex function here um or rather link that is coming from RX logo so I'm going to go ahead and use that and I'll go ahead and paste this in here right above it so as you might imagine I'm going towards the component being well the base page being really one argument that's coming through it here so in other words what I can do is if it is one argument I can say the child element has to be of data type RX component so the child element being the one single thing that's being in here I can then use that inside of my container just like this now I'm going to expand on this quite a bit but the idea being this child element will always be replaced on all of my pages this is what I'm going to add in whereas these two things are always going to show up no matter what page I have and all that and then of course I also maybe want to have a nav bar so I'll go ahead and say navbar and we'll go ahead and give this RX component as well just like the other one and then this is going to return something for now that something we'll just go ahead and give it RX heading something like that so I'll go RX heading and I'm going to call this my you know let's call it a SAS application okay so there's our naad bar we're going to come in here and now I've got a base page with my own component that I can reuse over and over again and there it says sass that's too big that's not a very good Navar we'll change it in the next part but the idea being that I can reuse these components can design them as I see fit now what I did right here was a bunch of pythonic type things with the exception of this child element here this child element can now be replaced with any other RX component right so that's kind of the key is we want to make sure that it is being replaced with any other RX component so that also means that in here again thinking like a pythonista we we can go ahead and say if not is instance child. RX component right so of course it should be that but if it's not that then what I'm going to do is I'm going to say my child equals to RX do U let's just say heading or yeah we'll leave it in as heading just like before here and I'll go ahead and say this is not a valid child element here okay so that's my new child element and all I'm going to do here is Return base page p and say ABC and basically invalidate that we'll save it refresh in here and what it shows me is this is not a valid child element and of course what this shows me is that I can use various things in Python conditions in Python to ensure that components render the way that they should now this is not the only way to do a condition of some kind and perhaps we want to do conditions based off of other arguments that might come in here like say for instance we want to say hide navbar right and that being false that might be another condition that we just change how this gets in rendered out which would be something like if hi Navar then we return back the basically the same thing but now we get rid of that Navar in there and so down here we would obviously not have this base page that's an invalid one but we could come into this one and right below the vstack we would say something like high Navar being true and then that of course would change how that page ends up being rendered out now this is is not the only way we do conditions this is just one way that we can do it inside of the Python of it all these aren't conditions that are related to the state they are just related to how it's being rendered out the state conditions are a little bit different so we're not going to do those just yet but the idea being we now have a component that we can reuse across many different pages but before we reuse it let's actually build a proper navbar and then we'll start doing the proper Pages as well now let's go ahead and Implement a nav bar now reflex has a bunch of different recipes that we can use so if we go into the docs we see recipes in here and then if we scroll down a bit we've got layout and then navbar so there's a bunch of different options for the Navar itself the one I'm going to use is the buttons option so if I hit code here I see all of the code that I can use for this nav bar so I'm going to go ahead and just copy this one and then we'll come in here and I'll paste it right above Navar and so what we've got of course is the fact that this is just simply Navar buttons which I'm just going to change it to Simply navbar and then I'll go ahead and get rid of my old Navar here because we no longer need it next up I want to go ahead and make sure that my index page the index component itself is actually not hiding the Navar we we do want to see it so I'll go ahead and get rid of that also so now that we've got a better Navar let's take a look at what it does so back into our fullsack app we've got reflex in here it's actually showing us a nav bar and of course if I were to change the colors dark mode light mode it actually does show that as well and if I were to break it down what do you know it's also Mobil responsive which is fantastic all of that is built in so the next idea here is why is the actual image not coming through well I'm going to go ahead and Save The Reflex logo here into my project and we'll go and put it in to the project itself and we'll go ahead and save it inside of our assets here just like that so that I refresh in here now it's actually showing up so in other words when we see the image component right here this is going to grab the source from our assets right and that's why that image was broken is there was no logo. jpeg in there by default so now we've got that solved it works in light mode dark mode if I were to break it down that logo should still be there and I should be able to still navigate as well pretty fantastic as far as how uh the nav bar ends up working but now we've got a couple of other things we need to address of course we can go through everything about the nav bar that's really fascinating but once again we see that it's component RX box is just another kind of component rx. desktop only oh that's really cool so let's go ah and break that down real quick if I break that down I could probably comment it out so if I comment it out let's go ahead and actually open it up again and then comment it out from Line to Line but I'll comment it out like that save it and then refresh on my page or it should refresh that nvar goes away the blue is still there which is interesting but if I break it down the nvar comes back open it up break it down all of it's coming back and fourth so the reason that that blue is still there is because of this box right here so we can see that the box has the color and all sorts of things that we can adjust later but what we also notice is there's buil-in components for desktop only for mobile and desktop we could probably even see rx. mobile only there's a mobile only one there's rx. taet only as well and what we would see is let me put a comma here rx. taet only and so these things will be rendered when the browser actually fits these break points these sizes in here so just another way to conditionally render different things out and how they end up working and so I'll stick with the da bar recipe that they gave us we will still need to address things related to this D Bar of course because we will want to make it actually functional but the idea here is we now have a naar that shows up and we can reuse it across different pages now before I actually Implement a new page I want to decouple this full stack python entry point app file right right because it's now getting way too big it has the nav bar it has the base page what I want to do is I want to actually start separating things out so that my entire component my entire application is a lot more uh reusable and easier to maintain so let's go ahead and take a look at how we're going to do that right now so naturally in order to maintain our code a lot better as in make changes incremental changes over over time it's better to break apart this module so what we're going to do here is inside of the fullstack Python folder we're going to go ahead and create a new one called UI and then I'll put a slash here and do base. piy the vs code will automatically make a folder for us if you weren't aware of that and if you hit enter it's a really nice little shortcut so inside of Bas stop High we're going to go ah and add some stuff but before I do I want to make my init file with the dunder or two underscores here init twocor dopy that way it is a full-on python module the UI element itself again if you're not aware of that next up what we want to do is grab inside of the fullstack python. py module I'm going to come in here and I'm going to grab the base page here so I'm going to go ahead and cut this out and I'm going to bring it into base. pi and of course I have a bunch of imports that are not available yet so first off we'll import reflex as RX as the default import then we need to bring in the Navar of course so for that I'll go ahead and create another UI element called navp and here this we will bring in our Navar so I'll go ahead and cut out this nav bar here as well as the Navar link we'll bring it into Navy now and once again we will import reflex so import reflex and we will go ahead and import it as RX okay great so of course in base. pi now I want to go ahead and just do a import for this so I'm going to go ahead and do from. naav we're going to import that nav bar just like that and there we go so we've got our navbar and our base page now in this main module here we can go ahead and bring in that base page so from. ui. base we're going to go ahead and import the base page and of course now all of those Imports are working a little bit better and so what the point of this is so that it's a lot easier to manage things and to make changes over time and of course if you're tracking it with Git then it's a lot easier to see when those changes happen so that's really the point here but now we need to make another major change and that has to do with how it's being rendered currently this is fine as far as a navigation fine but not great we want to make it a little bit better in other words I want this actual nav bar to be full width of the browser page and of course it'll still be uh responsive here but the idea being that I want it to be full width and then also have my main content area to fit along with that full width so let's see how we can do that right now identifying how components are being rendered out is something that I think you should experiment with on your own so you can have a better sense as to what's going on with any given component and all the styles that are being applied to it so in the case of the Adar we see that there's this dark blue here and we see that it has a certain width and certain padding all sorts of things that are going on with it so most modern web browsers in my case I'm using Arc but you could be using Chrome Safari Firefox most modern web browsers has a way to inspect any given element on your HTML page so the way I do it on a Mac is control click you might have to right click if you're on a Windows but the idea is we can do this inspect here and I can see the things that are being highlighted so if you look up here you can see that things are being highlighted now actually going through and trying to figure out what's being highlighted is a little tricky to do so what I do instead is I actually go in to Any Given component and I add in an ID here so I'm going to go ahead and say my uh container and for the base container let's call it my base container for example and then we've got this color mode button I'm going to go ahead and pass in an ID for this and I'll go ahead and say my color and we'll go ahead and BTN or maybe light mode color something like that now I've got two different IDs in here that will help me identify the different components so the first one we'll do my base container I'll go ahead and copy this ID here we'll save everything of course make sure that reflex is running I'll go back into the browser into the inspect elements I'm going to do a command F or control F and do a search for that element so this is what's actually being rendered this entire thing that's the component that is that base container in other words this container right here has this ID and therefore this is the actual HTML that's being rendered and of course it has a bunch of nested things in here including well another element that has RT box and so of course if you know CSS you might start going through here and being like Oh I want to customize the CSS a little bit let's go ahead and change something here and I'm going to go ahead and add in padding being one or let's do like 10m just to make it extra big and I'll put comma at the end here so I just added in some padding and if I refresh in here I can see the result of that padding and of course if I go back and do the inspect element do a quick search for that container I can see that container element but what I don't see is inline Styles I just see classes on here and so what reflex will do for you is it will actually create new classes for you as you can see on the right hand side here you can see the styles that have been rendered which was that padding that 10 m pretty cool so what this means is that each component itself we can start a a signing different styles to it if we want to now you may or may not do this on a regular basis that's not really the point here the point is to experiment to figure out where these different components are this can also help you better understand any given components element so like the nav bar for example let's jump into the na bar I'm going to go ahead and add in an ID here and I'll go ahead and say my main nav just like that notice I have a few elements that are already in in here as well I can now grab my main nav do that same search in the element itself and I can see here's my main nav what do you know it's inside of my base container which has this other div in here and then I've got my main nav and all that so it's pretty cool it actually allows me to start seeing what's going on what's being rendered and how I can start experimenting a lot more with it now going forward I'm going to give you a lot of these ele I'm actually going to just talk about it but understanding how these components are rendered is actually I think really important so in the case of our desktop only we've got this R stack here so if I come down to the very bottom I see justify between align items Center what if I actually add in something else in here as an ID and I'll go ahead and say my navbar hstack desktop something like that that helps describe this component I got desktop only htec maybe you don't know what htec does yet I don't think you do if this is where we've started but the idea being we actually copy this again and then I could go back into my browser and do a quick search again in the code just like that and now I can see that hstack which is inside of the Navar of course of course it's inside that's how it works right that's how each component is being written in Python we have a function here that's taken in an argument that also has a function here that's taken in another argument that's also taken in another argument right it just keeps on being layered in and so we can see the result of that by the divs that are being created nested divs all of these things are starting to Nest inside of it because of how all of these components are being rendered and again you will learn these things by actually just putting an ID in there looking for that ID and seeing all of the different styles that might be Associated to it right and so you can get rid of different things or uncheck them to see what's being what's happening based off the arguments that are coming through and naturally if you go into the docs and you wanted to search justify for example you do a quick search for justify you will see a bunch of different docs for this hey what do you know components layout alignment we can go ahead and just look at that and do well we've got justify in here these are different Arguments for the alignment and if we do a quick search for justify we will probably see see other attributes for this so you'll just be able to copy and paste it and just make it work real quick and so that is my strategy for how I decide what I'm going to do with any given element now again there's a lot of defaults that just work really really well we can already see that with our current content this default actually already works really well let me just refresh in here we can see that this already works well but we want to change it a little bit I do want to modify it I only wanted to show you this is a stry on how you can start experimenting more with the various layouts going forward I'm just going to give you exactly what needs to happen in order for us to achieve a certain result but I definitely encourage you to go through the documentation and just copy and paste and experiment with things as you see fit now let's go ahead and actually solve this Navar as we said we were going to jumping into our base page UI element here we've got rx. container with an IDE that's already Associated to it of course if it's confusing at all just get rid of that color mode button and we just have one ID in here so I'll go ahead and save that I'm going to copy this ID and I want to make sure that reflex is running of course and then I'll go ahead and jump into my browser we'll inspect the element we'll do a quick search with command F orrf and find that container element there it is right there and we see that it is a div and that it is containing all sorts of things in here now what we want to look at is instead of a container we can use something called a fragment well this renders nada nothing it doesn't render any div span it doesn't render anything out as we can see by saving it and obviously things change in here but if I were to search for that base container again that ID it's no longer there so yeah not every component is necessarily going to render something the fragment is a way to ensure that it does not render anything and basically says well you're not going to be able to put styles on here right so if I put in padding of 10m once again you're not going to see anything cuz it Doesn't render anything it doesn't render a div as soon as I change this to something different oh I should probably make sure that I have a comma in there as well U but again even with a comma it still doesn't render anything so as soon as I change it to a different element even if it was like text this is probably not a good idea because that probably will fail let's change it to something like container again we put it back as container there is that that padding once again and so what I don't want to use is the actual container the reason being is once it was a fragment we noticed something very important about the Navar the Navar looks great it actually is rendered correctly the thing that does not look great is our main content area here that child element that we've been passing through but even the button still in a good spot the actual logo with built with reflex also still in a good spot so of course we want to change it so the main content area here reflects well what the nav bar reflects as in these items are lined up right now this is just touching the edge of the document I want them to be lined up so how do we go about doing this well the way I'm going to do it is by copying from the nav bar quite literally if I go into the nav bar I see that it says rxbox okay cool I'm going to grab rxbox and I'm going to put it around the child element just like this and we'll go ahead and put the the in parenthesis I'll tab this in here so it's a little bit easier to see there's my element now I'm going to go ahead and grab this as being my base child element or we'll just call this my child element or my content area element something like that then I'm going to go ahead and copy this of course we will inspect the element now and I'll do a quick search and we'll see where that is and there's that element and it says RT box but it's not necessarily changing something related to the nav bar that's of course because well I didn't actually copy all of the nav bar going back into the nav bar all I did was grab the component that's being used in the nav bar if I were to scroll to the very bottom where all of the arguments are being added well now I can go ahead and actually add in some of these arguments I'll just copy all of them because again I want to copy the na bar so I'll go ahead and come in here we'll copy all of them with the exception of that idid um I don't need these comments probably so I'll get rid of those but I'll go ahead and save this and then we'll go ahead and take a look what do you know it looks well identical to the Navar now even the background all sorts of things related to it are identical to the nav bar which is great but the thing is I probably don't want the background color so I'll go ahead and get rid of that I will leave that one out I'll leave the background color to being you know based off of light mode or dark mode in other words black or white basically that's what I want next up what I want is probably this width I probably don't necessarily need to have it but I will leave it in there but I want to align my content a little bit different in other words on my homepage I want this to change maybe everywhere maybe not so if you're familiar with CSS you might do something like text align equaling to Center and we can save that and we can take a look at what happens nothing the reason it wasn't aign has to do with the fact each component can have its own Styles you can change them as you see fit now a lot of those components you will need to experiment on with where you might want it to end up working so if we actually take a look at our code here what I want to do is I want to take a look at the child element now the way I'm going to do that is of course where it's being rendered which is inside of full stack Python and in this index page here our base page has the child element in here now just as a reminder we're going to go ahead and just change just to being my child equals to that H stack element and then I'll go ahead and pass it in to this base page like that next I'm going to do that experimenting with the ID and I'll call this my child and just save it as is and then I'll go ahead and do a quick search on that page inspecting the element here and doing a quick search in here and I've got my child and so what we've gotten here is we've got a bunch of classes that are in here by default one of them is this align items Flex start if I were to uncheck that element here what we get is the actual text being align in the center I also have the actual form input changed quite a bit but the idea being as soon as I were to refresh it goes back to what it was if I inspect the element and grab that child element again and then just comment out the Align items it does change things right in line there so that means that then I can see that this element this actual component is handling why it's being aligned in the way that it is so that means then I would come into my full stack python I would look up this element itself look up this element to make the changes that I want this is where I might try to do something like text align being Center as well so we'll change that we'll refresh in here we'll see what happens what but you know it actually aligns the text in the center but the actual input is now quite funky so what I want to change as well is something called align so I'll go ahead and just do a line equals to Center as well we save that and this might change things a little bit for us as well the input is back to the same size it was everything's aligned in the center now so this actually gives me the ability to modify things for this component may or may not have effect on the parent component so the parent component itself we probably don't want to do text the line being Center as we'll see in just a little bit but the idea being now I have this single component on here now why is it that this these arguments worked for the child element yes of course we are experimenting here with how it might work but there also is the docs that will tell us this so if we go into the library the library of components here we can see that there are ones for layout inside a layout we have stuff called stack so the stack has different layout components that we can use v stack is for vertical direction hstack is for horizontal Direction stack is used for either one so this actually will change what we end up doing so if we actually look back into our child element here we see that it is vstack or vertical stack so we can scroll down to Vertical stack what do you know that looks a lot like the content that we had and then in here we can scroll down a bit and we can see different references or different properties to Any Given stack component whether it's hstack or vstack we can come in here we can see that Al line there is the option to change things based off of a bunch of different stuff in here and so we can use something like stretch in here so if I did Stretch on my alignment save that and go back into my project what ends up happening is hey that element comes back what if I were to take away text Center if I take away text Center what ends up happening is it brings everything back but then it stretches the entire component itself the text is no longer centered but things that are related to the stretching will be adjusted as well so in this case it happens to be the input that gets stretched out and then of course we can actually see this also by looking at the my child element itself right so it's all stretched out and if I were to get a line item stretch let's do a line item start and we can see that hey that actually has an effect as well so there are a lot of different ways on how we can think about what we do with our child elements or any element on there as soon as we change it to Center the way it actually handles this component is also just a little bit different and it does of course have effect on all of the other components as well so we're going to want to continue to experiment with this and I'll continue to show you but the idea being that whenever you run up against something that's not working as you intend you want to go to the base element itself and figure out what's going on when I say the base element I mean maybe you start with the absolute parent which in this case is rxbox that's what we did we started with the absolute parent did some experimenting in here then we go to the next level which would be the child element which of course was the vstc we also might want to go to what either other element which in this case the input itself maybe we want to change that also and in which case you would come into form into input and you can see a lot of the arguments that would come in here as well so scrolling down to the API reference we've got all sorts of arguments that are coming in here that you can really play around with as well now some of the arguments are also just general component arguments that you can continue to play around with as well so for instance like the Align one you might want to put in the Align in here as well as Center and just see if that does anything or start or whatever um the point is that this experimenting will continuously happen and I encourage you to continue to do it but now that we've got some of the fundamental layout let's actually start building out new pages and have some navigation itself now we're going to go ahead and create a brand new page it's really easy to do first and foremost we will actually copy the index component so go and copy that paste underneath it and we'll go ahead and say about page obviously the child elements in here can be the same or different I'm going to change the label to being about us I'll keep that size at nine I'll go ahead and do the text in here and say something cool about us I'll get rid of these inputs and comments and just leave it like that get rid of this comment as well and there is a simple page that we're going to use now how we actually route it how we actually can access it is by going down into app and just copying add Page Changing this to about page and then declaring the route we want it accessible from so in our case we'll just have it at the route of about so now jumping into our project here if we go to slash about and hit enter we now see our about us page very very simple but of course this is not what I want to do what this is going to start doing is getting this full stack python module really really full it's going to have too much stuff and it's going to be harder to maintain just like we did with the UI element itself so what we want to do instead is we're going to go ahead and create Pages SL init.py so an entire module for about and then I'll go ahead and do about to Pi and well now all I need to do is cut this out bring it into A.P and then do a few Imports the first one being import reflex as RX the second one being our base page so from dot dot ui. Bas import base page and there we go next up what I want to do is inside of my pages here I'm going to go ahead and import That Base page from about or rather the about page from the about module and then we'll go ahead and do our all method here and we're going to go ahead and put in about page p in here as a string now the reason I'll I do this is going to be obvious in just a moment but the first thing is back into my f stack python module I'm going to go ahead and import this about page so one of the ways we could do it is say something like from pages. about we can import that about page and that actually solves that problem but what I actually want to do is I want to say from dot right underneath the UI I'll go ahead and do from do import Pages get rid of this import here and now I can just use the entire Pages module like this and so now if I add new ones on there which I will eventually I'll be able to actually route things that way so it's going to be a lot easier so for example if I were to create a pricing page this is what I would do is say pricing and then slash pricing and then I'll go ahead and duplicate about to just being pricing the about page to being pricing page this is going to be pricing and then R pricing or something like that there it is then in my init method here to make sure that I can import it from the pages module I'm going to go ahead and import it from here so there we go and so now we've got two new pages in here and a location that we can actually access them at about and pricing not surprising we have about and pricing right here naturally we would want to fill these things out quite a bit more but of course the big problem that we have now is really the routing how do I actually click on a link and go where I need to go so let's take a look at how we can solve that now we need to actually handle navigation so if I click on a link or a button that should navigate the actual page should reflect that so the way we're going to do this is by jumping into our index page here right above or below this text I'll go ahead and do rx. well link and we'll give it some sort of text let's go ahead and say go to about page and then we'll go href equals to about and that's it that's as simple as it gets that will then allow me to have this link here and I can click on it and it'll take me where I need to go now of course if we need a button well you may have already seen this but the button itself you actually use that in place of the text so then you would just put the text there and now it's an actual button instead of just a link like like that now the reason for this has to do with HTML itself an HTML element of button doesn't actually go anywhere that will never go anywhere so something like slab never goes anywhere so what rxlink does is it actually allows for that to go somewhere so if I inspect the element here for that button we see that it is still a button but right above it it puts an anchor tag so we can actually navigate somewhere else which is pretty cool now we actually can already see this also in navp with this Navar link here it's doing the same idea the same thing but instead of a button it's just using text that's coming from this link so here's an example of a reusable component that we in theory could have made so what we do do here is we scroll down to rx. hstack and we can see all of the possible links the homepage should obviously go to home about to about pricing to pricing and then contact to contact right so once we save that we go back into into our project here we can actually now navigate around to the various pages of course our contact page doesn't exist yet but overall the other ones do and so even the actual nav bar the image itself right here we can go ahead and do rx. link put that in here as well and just go ahead and add in the href bean to the homepage and just tabbing this in a little bit and this one as well and then the heading as well maybe we also want the heading to be a link so we go ahead and put that in as a link as well and then we can kind of play around with these different elements as we see fit just like that okay so now I can actually click on various points in here and I can do stuff I can actually move around to my pages great and of course if I click on reflex it goes back now the problem is what we see here is of course it is now a link it's not just that texted like it was so that might not be what we want the other problem is if I break this down and open up the navigation here and click on this about it does not navigate for me so back into the code what we could do what we would Inuit it is to go down into Mobile and tablet we would scroll down and we would see the menu items the context menu items to me the logical thing to do would be to say oh I'm going to go ahead and do rx. Link in here and I'll just go ahead and move this home item here and just do href equals to that and then I can repeat this process in theory going forward so if we save that and we refresh see that it compiles now it's saying hey the component drop down menu item can only be one of these but it got next link instead and so what happens here of course if we were to look into the documents do a quick search for dropdown and we will actually be able to see the drop down menu here and then of course we can navigate into the different items what we see in here is there is is this context menu for items and heck there's even shortcut keys that we can use in here that are built in but what we notice is the actual menu itself does not have a link it's not actually written there and if we were to scroll down to the very bottom where the menu item is right here we can see that there is no property for Link in here so the logic in here might be okay let's cut out this menu item like that I'll get rid of this link here and instead of it being like that I'll just go ahead and change this to maybe the same thing as our Navar link before or just put rx. Link in here of home and then href being to the homepage right and this also in theory would work so if I were to go back into the project let's go ahead and break it down into what it was click on this and now I see that it is linked there but if I click on the side of it it doesn't actually navigate if I were to click on the actual text then it would probably navigate let's actually navigate here here and then let's try that again breaking this down click on home I click on that text it works if I go to C check out our docs again and click on the side it won't navigate so of course those are two problems we still need to solve right here on the brand and also in this context menu so since we're going to solve it in the context menu I'm going to change this to just being home still and we'll come back to it in the next part on how we can do additional kind of navigation this right here is an anchor tag so it's like what you you'd be expecting in a normal HTML element so ahre equals right and that's what's happening inside of that link where it comes to something else we need to handle a different kind of methodology which will be corresponding to events let's take a look now we're going to go ahead and use event handlers for redirecting our users to any pages on our site this is very straightforward forward but the idea being that we are no longer going to use RX link but rather a onclick event instead so the way we're going to do this is by get rid of all of these old ones I'll get rid of that and we'll do rx. button and I'll go ahead and say about us so naturally with this button if we were to go click it it would not take us anywhere right so we can see this by jumping in to our homage here and clicking on this button it does absolutely nothing now one of the things we could do is add this click event on click and set state.id click and now at the very least it would actually have a few print statements in our terminal assuming I did it at the right time there we go so another thing I can do is just simply say something like rx. redirect and redirect them where I want them to go rx. redirect and click on about us sure enough I can redirect pretty cool so I can also use these things to together so back into our did click here I'll return rx. redirect and this time I'll go ahead and do about- us and then I'll go ahead and come back into my click event here and do state.id click we'll go ahead and save that and let everything refresh now if I click on about us it takes me to a 4 or4 page page could not be found so this right here actually highlights one of the challenges to doing programmatic redirecting is the fact that maybe you are using a route that just simply does not exist so if we scroll down a bit of course the route is this right here and so we might want to think about how we're going to solve that for all of the different routes going forward so one of the nice things is for any given page we can actually comment this out and we can go into that page and do a decorator rx. page and actually put the route directly in here so about- us or something along those lines and of course what would end up happening then is that page would work but then now other parts of my navigation might start to break now it might not break right away but it should break after you actually clear everything out the about page the old one the old navigation should be completely gone at some point and in this case it is so what we want to do of course is solve that problem make sure that that's working correctly I will keep it back at about so it still works at this point but now we see a new approach of actually routing our Pages we also see a way to to programmatically Route our Pages as well now when it comes to buttons themselves since we have the ability to just do rx. link this is what you should do pretty much all of the time right you just use the button in there and then href being about or wherever it is that you need them to be linked to that is what you should always be doing one of the big reasons for this has to do with the fact that now I can copy the link address that's on that particular button uh which the programmatic approach the onclick approach won't necessarily give you that href itself that's pretty interesting but now of course we need to solve a couple of things one is all of the routes themselves for our various pages and then also maybe a general State event that I can reuse in other places like in our dropdown Navar let's take a look at how to do that right now so one of the reasons I showed you this redirect with the incorrect path has to do with the fact how easy it is to accidentally use the wrong value here now this could be true in a link this could be true in how you route it here or if you were to route in the page directly no matter what it can be true it can be really easy to accidentally use the wrong route and so of course that can have catastrophic effects on your entire application what if you decide that you want it to be about us and then you go into your local development here you click on about it's still navigating to about and it's still rendering that's kind of cool but if of course if you were to refresh your project here let's go ahead and recompile everything all of the cach is cleared out and now if I refresh onto this about page what I will get is a 404 page and so that false confidence is now gone but I have a bro a bunch of broken links and stuff like that so when it comes to our primary routes here what we want to do is we want to set some constant values for them those constant values can change but then we can use them throughout our application so the way I'm want to do this is jump into fullstack python here we're going to go ahead and do navigation slash and then init.py and then inside of here we're going to go ahead and create routes stpy and so all I want to do is create my home path or really the Home Route right and then copy this several times or however many paths I'm going to end up using so the About Us Route the contact us route the pricing page route or just simply pricing route and so on right so whichever ones you might want to use in here is what you'll do now and so you'll want to use double quotes probably but then you just add in all of the different paths that you actually want to use so these are them right here so now that I've got that I'm going to go into my init method here and do from do import routes this is so that I can use routes in a way that I've kind of already seen with Pages let's go ahead and import navigation and let's go in our init method let's make sure that routes is inside of all here like that okay so inside of my navigation Now everywhere I want to use the about page route I just do navigation. routes. about page route right and so there we go and I can use that again inside of my pricing route come in here and this is going to be my you know pricing route oops let's go ahead and get rid of that and just change this to my pricing route and so naturally what I can do then is use that same concept anywhere I need to use some sort of routing in here and so that way I can change it inside of routes here any given time and everything else will adjust accordingly so of course this also means that my Navar needs to use these things as well so going back into my navbar I'm going to go ahead and grab that same element so from dot dot import navigation now that I've got that I can come into my different Navar links here so navigation routes about us route and then navigation routes pricing route and then navigation route contact us and then of course my homepage here navigation route and Home Route so literally anywhere I need to use any of those paths I can update it as such right so the Home Route is going to be used a lot now the Home Route is probably one we could get away with not using just use the slash but using all of these different routes in this way really help lend towards what we need to do next which is create events specifically for this menu right here and that's actually definitely something we'll want to do but at this point I now have reusable routes and I just want to make sure that any href in here is using those reusable routes that are now defined as constants throughout my project it's pretty simple but the next part is just creating a another type of navigation state so that I can reuse that when I'm not hardcoding links throughout now that we have these constants here for our different URL pads and we understand the concept of using our X redirect in conjunction with a state class we're going to go ahead and create a state class specifically for navigating now this is for various elements on our web app that may or may not have a link value so whether it's a button or in this case we've got our drop- down menu with this context here that requires us to handle it a little bit different than a link as you may recall if you do rx. link here it's going to run an error so if it was something in here as RX x. link and try to link that to something it just simply doesn't work it will quite literally say hey you can't use this component so of course we need something different that something different can absolutely be onclick and then rx. redirect to where we want to redirect it like in our case it could be redirected to home and this is totally fine but it brings up that same problem whereas if I do change the routes at all what's going to end up happening so instead of doing that what I'm going to do is I'm going to create a state navigation so we go ahead and do state. piy here and we're going to go ahead and import reflex as RX and then I'm going to create a class called nav State and this is going to be rx. State and then we're going to just define various methods that we want to handle so for example to home which we'll take in self it's going to return rx. redirect and it's going to take us home while that home is coming from these different routes in here so what I'm going to do then inside of this state element we'll just do from dot import routes and this is going to be redirecting routes. the Home Route and so now if I were to build this out more with my other routes that I have I can it's fairly straightforward so then to about us routes. about us route to pricing and then you know pricing route and of course you can fill it out with all of the other routes that you might want in our case we just have the contact one that's the only other route that's in here so we'll go ahead and leave it in as to contact like that and contact us route great so now with this nav state in mind we're going to go into our init method here I'm going to go ahead and do just from. State we're going to import the nav State and then I'll go ahead and make sure that that is in all as well so now into our navbar I'm going to go ahead and import navigation in there looks like I already have navigation for some of our other routes here the links themselves those are going to be fine we're not going to actually change those ones all of the ones that have links we will keep as is now what we'll do inside of the context menu for each onclick method here we're going to go ahead and use the nav state so I'm going to go ahead and enter this out I'll break this down a little bit so it's a little easier to see but of of course it's going to be navigation and then naav State and then what we want it to do which in our case will be uh to home okay and then we'll close it off and we want to test this out first I'm going to go ahead and just add in about as well so I can really test it out so two about us great so with that in mind let's go ahead and make sure there's no errors looks like there's not let's go ahead and take a look at our Navar now I'm going to break this down open up the drop down here click on about sure enough it takes us to about click back on home and sure enough it takes us there as well so naturally we now have the ability to do these things so I'm going to go ahead and bring in you know pricing and contact so two pricing and then to contact which might not even be a page yet but we'll go ahead and test these things out now so pricing there we go contact not even a page yet so we probably should add that page real quick but we have all of the navigation working and it's based off of this state element here so yeah that's actually pretty nice now when it comes to doing something like this redirect I recommend doing it in a state element altogether so that you are shortcutting what needs to happen inside of there now absolutely you can do rx. redirect and then use these routes just like we did in the links themselves it's really up to you on how you go about doing that I think having this State method is really nice because then anywhere else I need to do this redirect I totally can and it's going to work just fine so in other words when I have let's say a login page and after they log in I want them to be redirected to the homepage I can just now use this navigation state or if they go to a page they're not supposed to I can have a timeout that eventually sends them back home as well so those are other more advanced features that we can implement but before we do that I'm going to go ahead and create a contact page as well so I'm going to duplicate about to just simply contact and then we'll call this our contact page and contact us and then I'll go ahead and go into my init method here so from. contact import our contact page and just implement it like I would so one of the things that we could do though is instead of bringing it directly into here like this we you can actually go back into our contact page and just use that route right in line so in here we'll do from dot dot import navigation and then the route itself will be right on the page which will be navigation. routes. contact us route and we can save it like that and that should actually give us that contact route now so there it is contact us and we can break this down we can navigate where we need to go great so now that we have some of these fundamental pages I want to actually Implement a contact form so we'll start out with the form itself and then we'll have to do something with it as then store it somewhere let's take a look at how we handle forms right now now we're going to update our contact page to actually have a form on it so the way this is going to work is we're going to jump into the components library in reflex and actually look over at forms and we can see there is a basic form here this is close to what we want but not quite there but at the very least it will give us some of the foundation that we'll use and need for this particular form data so that's actually what we want to take a look at right now is this form example so the first thing that I want to do is inside of my contact page I'm going to go ahead and declare my contact state right and this is going to be rx. State and this will just be our state variable for our contact form which then also has the form data in here which we can set to being an empty dictionary now notice there is the actual data type that's in here as well this of course enhances the code makes it a little bit more reusable but the idea being that we have our form data in here and then the next method inside of that is we need the handle submit method which we'll take a look at in just a moment I also want to print out what that form data looks like okay so next up what we're going to do is we're going to put the form itself inside of this child element here which is going to replace this so to do this I'm actually going to go ahead and say my form and then do rx. form and this is where we'll actually Implement everything related to our form and that's just going to take place of this rx. text here just like that this just allows me to really hone in on the form element itself so it's not getting you know lost inside of the stack element that's here so with this in mind we can actually see in the example there already is a rx. form that example I'm going to go ahead and copy and paste in here and we can see a number of things related to it there is another vstack or vertical stack in here which is going to stack everything on top of each other and then we can see everything that's coming in here including an hstack and then a submit button and then we have this form State as in handle submit which of course is not a form state but now a contact state is what we called it great so what we've got here is the ability to just really change how our form's going to end up looking right now we've got these placeholders of first name last name I'm going to leave those in there and then I'm going to get rid of this H stack I actually probably don't need that one because if you look at the example here we've got a switch and a checkbox both things you know maybe I want in maybe not but in our case I'm just going to go ahead and stick with something more like rx. text area and of course what this is going to allow me to do is actually bring in an input itself so what I want to give this is a name of Simply message and then I'll go ahead and put in a placeholder with you know your message like that now I usually put the name first that's just out of my own preference I like knowing the input name because it has implications on the form data itself where everything after that doesn't necessarily have any implications on the data you may or may not save into a database now in this case I just have some basic data so let's go ahead and take a look at the contact page now and all we're going to do is let's refresh it looks like our server is down for some reason I'm going to go ahead and bring it back up go back into our contact page here and what we should see is the actual form element itself so it's off to the side we definitely need to change that uh but for now I'm going to leave it as is and I'll just go and say just ADM and hello world and hit submit notice that it is cleared out and in our print statement we've got that data so the reason it's being cleared out is because of this input right here this argument for reset on subit we could change to be false you might not want it to reset so we come in here and oh it refreshed there and then once again we can come in and hit submit now it doesn't refresh or reset the form itself so let's go ahead and change it back to being true and then the other thing is if I hit submit here it actually does submit empty forms so naturally that's not what we want I'm going to go ahe and say require being true on the first name and then the message also be required now you could swap this out for different kinds of inputs as well like if you wanted to have an email address so let's say for instance we did rx. input and now we'll go ahead and say email this time we'll go ahead and G give it a actual type in here of email so the argument this of course will then correspond to the email input which is going to be something like input type being email where the default is input type being text which of course you could also declare as well just to make it more verbose as to what is happening on any given input right and so we use the text area input as well there's a lot of different ones there's password inputs there's all sorts of things like that and so now if we refresh in here we've got our email let's go ahead and add in a placeholder here as well placeholder and your email save that refresh in here and so what we'll see of course is your email I hit submit it's going to force me to put in my name and then if I hit submit again it'll force me to put in my message and then therefore it does submit with all of that data great so that's a really good start so it's nice that we can render out our form and we can even see the data that's being submitted but of course the problem now is it doesn't look at all what we want a form to look like in the sense that it's off to the left here I want it right underneath the title of contact us if I were to break it down it looks a little bit better on mobile but it's still not great so let's go ahead and solve that now now there's two ways on how we're going to go ahead and solve this one is by using common props that is style and layout props that you can use for CSS all of these things are potential use cases that we can have to improve the styling but what I really want to look at is just simply the width in addition to the width we're going to take a look at responsive elements and specifically the desktop only and you know mobile and tablet elements that we saw in our navbar so let's go ahead and get started here the first thing I'm going to do is I'm going to jump into my inputs and I'm just going to go ahead and add in wi and we're going to set it equal to 100% okay so it's going to take 100% into the Container element it has so let's go ahead and bring that in and what we see on desktop now it is well closer to what we want it to look like on mobile this is maybe exactly how we want it to look on mobile but of course on tablet still a little too wide and then if we go any further than that this is still quite a form so let's go ahead and change this a little bit more going back into my child element where I'm actually rendering out my form I want to use the rx. desktop only and I'm going to go ahead and render out my form in here and so with desktop only of course what that means is it's only going to show up on the desktop the actual styling already changed it already looks a little bit different which is interesting but if I were to break this down as soon as I get past or towards the tablet size the form disappears appears so that's actually a good sign because then I can actually come in here and instead of just doing desktop only I can do mobile and tablet save that refresh and of course what we'll end up seeing is if I break it down I can see that the form stays the whole time and it certainly looks a lot better than it did but we can still improve this a little bit more the way I'm going to do that is by using a box on desktop only so if I do rx. boox here and put our form into the box elemented itself we can see that it probably won't make that much of a change if any at all and so what we can do with the box is now I can actually Place Another width element in here and we can start off with 100% and see what happens there so in this case what happens is basically nothing so the reason for that has to do with it where that box element lies so we can go ahead and say ID and say my form box and just take a look at that in our browser so once again I'll go ahe and inspect the element and we'll just take a look at my form box let's go a and do a quick search for it and there's that box element right there so the width says 100% but it's not actually 100% of the entire page here so the way we can make it 100% of the entire page is by using the viewport attribute which is w and then you you could do it 100% of the height or you could do it 100% of the width with W so 100 100w VW brings us out to 100% of the viewport width and that is not what we want either but it is nice to see that we can do that and So within the desktop maybe we wanted 50% of the vport WID and if I do that now it actually is looking a lot closer to what I might want now it still might be too wide and we can adjust that as we see fit but the idea here is now we have the basis for the styling once again I only use the width element in here along with break points and of course we created this box so I'll go ahead and use the same element in here again with that box and now on mobile and tablet I want to change it a little bit I no longer need the ID in here because I know exactly what I'm doing but the idea being on mobile and tablet I probably want it to be a little bit wider so I'll go ahead and say 85 view width and now on tablet it's probably going to be a little bit wider than it was on desktop but as soon as I get down to you know mobile it start to look pretty good so once again you can play around with the viewpoints itself uh or the you know the responsive break points we could do tablet only as well and maybe this is more like 75 and then mobile only is the one that's you know 85 or 95 and and again you just play around with it as you see fit and we can break it down and really just kind of see what works for us but the thing is there's one other aspect I want to add in and that is I want the first name and last name to be on the same line so the way I'm going to do this is by using rx. hstack hstack stands for horizontal stack so I'm going to go ahead and cut this out and paste it around the inputs themselves so I'll go ahead and tab these inputs in so they are inside of that hstack element and I can break it down so I can see that as is now if I look at it I see that it's going first name last name inside of just one piece of this element so the hstack is not going 100% so let's go ahead and do our width of 100% on the HTE element itself and see what happens there so if I were to refresh that now it's at 100% again and it is actually working all across the board now I think even on mobile this probably looks pretty good but if I were to add in anything else into this deack let's say for instance I wanted uh one more input in this stack here that might break these things down quite a bit or maybe too much that might be too many elements on mobile where on desktop is probably fine so again it's about playing around with it until it works well for you in your use case worst case scenario you just make a form for each breakpoint so for a form for desktop a form for tablet a form for mobile with a lot of the same inputs and then you can just reorganize how it all works out and then of course you will handle that data as you see fit as well So speaking of handling that data what I want to do is I want to actually render the data that's being submitted just so we can see what that looks like after it is actually submitted so we can kind of start handling it and going towards storing it into our actual database as well what we want to do now is conditionally render out a message after the form has been submitted so if I submit the form I want a messag just to show up here saying thank you now the way this is done is built into reflex so I'm going to scroll down into my child element here right underneath this heading I'm going to do rx. and then we're going to go ahead and say true and I'll go ahead and say submitted and then the default value will be default or something along those lines so we'll save that and I'll refresh in here and what we'll see of course is it says submitted that of course CU I said true if I change it to false it's going to go and say well false default the default value so this is how we can do conditional rendering of all sorts of things now do keep in mind if I do something like rx. button here what we might see is a challenge or an error with the rendering here I get both arguments must be props in other words if you are going to pass in a string here you need to pass in a string here if you're going to pass in a component here you need to pass in a component here so I can do something like like RX text just like that so that is an important distinction because rx. condition this.on you can use on all sorts of things you can use it on the base page you can use it on the child element you can use it on the form you can do all sorts of things in there but the real question is how do we actually toggle between a true and false value here well it actually comes down to our state so I'm going to update this a little bit and I'm going to change this from the form State here I want to go ahead and make sure that that typo is fixed and the forb data should be in that context state next I'm going to go ahead and do dat submit this is going to be of type Boolean and well the default value should be false probably so I'm going to go ahead and change this to being self doid submit and the value being true so after the submits this is a toggle basically as to what happens then in my condition here I can use that state value of did submit and now I can actually toggle between those two values so if I were to save this and let's make sure it's called Contact State sure enough it is default button is showing up there right of course I don't want that button there we will get rid of it but I'm now going to go ahead and put in my message and there it goes it says submitted fantastic so of course if I do have an element in here I can also just have nothing in here I can leave this as just blank save that and what we get of course is the element being rendered with nothing so I'm going to go ahead and pass it in and run that now it's submitted great so what I also want to do then is actually change the text that's coming through in this text right here so what I'm going to do is instead of using text I'm going to use the context State itself so one of the things I could do is the form data so I can do context State and then form data and then we can do two string just like that and if we open up the terminal we get an error here so in this case we actually do need to have have a backup or a fallback value so I'm just going to go ahead and put a string here this renders out as a string so I'm just putting a string and there we go so now that we've got that I'm going to go ahead and take a look at it in our page and I'll go ahead and submit my form data with some gibberish in here let's go ahead and hit submit and there we go so it's now showing that data as a string now I actually probably won't ever render out a form like this ever but it's getting to what I actually want to do which is saying something more like uh thank you in there but more like thank you you know first name whatever that value is going to be and so as soon as I start to make this a little complicated I want to go back into the state and make that into a variable so we'll go ahead and do rx. varar and we're going to define a new variable in here as simply thank you and it's going to take in self and it's going to return something related to this so I'll go ahead and say thank you exclamation mark to start next up what I want to do is grab that form data the way we do that is we're going to go ahead and say first name equals to self. form data. git first name naturally we know we can do this dogit because it's a dictionary and it's being set as a dictionary all across the board it is a dictionary or we can go ahead and set it equal to an empty string in which case I can now use this string substitution that you would with python otherwise and we can bring it in just like that now this variable is what I can use for my thank you message inside of here so we can do our contact state. thank you and we can even put it as our fallback as well so we're going to go ahead and save that and we can see as soon as I do that I see the thank you message in there with an extra space in here which I don't want to have we'll adjust for that in just a moment and I'll go ahead and say Justin add in my message and there we go cool so that gives me that ability now this thank you here maybe we want to change it just a little bit and basically say thank you with a you know plus here and then I can just do dot strip and that means that if the first name is empty it's going to strip this down and then add a parenthesis at the end in which case our thank you now looks correct of course the actual condition itself I actually don't want this to show up on the second half but in the case that you may make the first aim optional which in my case I have it as required but if you were to turn this as false then you still want that thank you message to show up and be formatted correctly and that's how we do it so one of the downsides of this though is if I were to let's fill this out and let me just refresh everything let's save it this thank you should go away assuming that everything's running correctly looks like I have it not set so let's go back to that condition oh yes I did not put a fall back value there we let's go ahead and set it like it tells us next up we're going to go ahead and put in Justin and then some gibberish here thank you Justin I'm going to navigate to the homepage and oh I forgot to contact them about something else it still says thank you Justin so there's a couple different ways of how we can think about clearing this out the way I'm going to do it is by actually having some time in between the submission and when I want to clear it out in other words when it is submitted I actually want to eventually sleep it and then have it Go did submit being false eventually so how do we actually go about doing that this is also known as a timeout method um or you know in the case of JavaScript if you're familiar with that process set timeout so that's kind of what I want to see here right now now we're going to implement a timeout method or basically we want to change the did submit status on our form after a certain amount of time like we discussed in the last part but the idea here or the intuition would be to import time and they do something like this where you come in and do time. sleep and sleep like two seconds or something along those lines assuming that our project's still running no errors actually happened I can come into my contact and come in here and hit submit hm it didn't seem to work in fact did submit didn't even work anymore it actually made it false so unfortunately this is not how it works what we need to do is instead we need to turn this into an asynchronous function and then use built-in asynchronous features to python which is async iio then instead of using time sleep we use await and async iio sleep now if we were to run this and do it again we get the same result so what we actually want to do is we want to change it a little bit more than this and that is we want to return back a yield as soon as we do yield all of these things will be updated the state will be refreshed and then we can actually go ahead and run yield once again after submit ends up happening or that sleep function ends up happening so we can do something like this and then just pass it in it says thank you after a couple seconds it goes away so that is the approach to timeout it's not the same thing as a countdown so let's actually take a look at doing a countdown if we wanted to as far as a timer is concerned now we're going to take a look at how we can do a countdown now this isn't that practical for a contact page but since we just did this timeout method I want to show you how to do a countdown now it's fairly straightforward first off in our state any sort of reflex State here we're going to go ahead and say time left and it will be an integer of however much time you want to countdown I'm just going to go ahead and say 5 seconds so with this in mind I'm going to go ahead and give it a label as well so right underneath here I'll give it RX dovar and we're going to Define time left label and it's going to take in self and it's going to return it's going to be very similar to this right so we're going to come in here and instead of that we'll go ahead and do self. label and we'll go ahead and say I don't know time left and just simply seconds right and basically if the self. time left is well less than one then we're going to turn done or no time left something like that right so with this in mind I'll grab that label we'll go right underneath the heading here we'll do rx. text and then our contact state do our time left label and we'll leave it as is of course if I refresh on my contact us page we should see that it says 5 seconds so the next part of this is actually creating the logic to tick down the time and so I'm going to call this a asynchronous function again it has to be asynchronous we're going to call this our start timer and it should be like start countdown maybe but I'm going to just call it start timer and it's going to be self what we want to do is we will go ahead and say self. time left you know minus equals to 1 so basically every second we want it to have one less now in order for this to work we want to put it into a while loop so while self. time left is greater than zero um then we'll go ahead and update that as is okay so as long as it's greater than zero then we will continue this process so if it's at one then it's going to go and go through that process which once again we then want to do a wait and a syn iio Dos sleep and we want it to sleep 1 second and then we wanted to yield that result simple enough so the big question then is how do we actually start this timer well the RX page attribute here we can actually put in on load and run something related to a state in this case we can do contact state.st start timer now do keep in mind RX page can only have this if you wanted to you don't have to have the route in other words this same sort of features and functionality can work on other pages that just simply don't have um this argument in here in other words I can just leave that out and it will still work to some degree but I still need this route because that's where my contact page is so now if I were to refresh on here it now shows me it's ticking away to a number number of seconds obviously you could do the reverse of this you could do all sorts of things in terms of how you do the timing itself so if you were to want to start ticking up you could change it a little bit differently than this and now you could say something like less than I don't know 100 seconds then you could do plus equals and obviously I started at probably 10 seconds but now it's going to go ahead and count up so you can really just decide which way you want to go in terms of your countdown timer but I just wanted to show you that as a practical way to use timing inside of reflex within the python of it all and of course async iio with reflex is how this is even possible if you don't use async IO it probably won't work as cleanly as this now you can do other things in async iio as well you can do long running tasks that happen in async iio but that's outside the context of what we really need to do here instead what we want to start doing is moving towards actually saving this data to our database now we're going to go ahead and create a database for our reflex project now we're actually going to be using the built-in database called SQL light but the idea here is we want to be able to collect data from our forms and actually store it into a SQL database the reason we're using SQL has to do with the fact that it can handle a lot of scale so we'll talk about that more in just a moment but in the me time I'm going to jump into my docs I'm going to click on learn here in reflex and then we're going to scroll down to database go to overview and here is stuff about our SQL database what we'll be end up doing so the first thing to point out is reflex uses SQL model now the reason this is important is because if you ever need to make modifications to how you actually Define your models SQL model will probably be the first place you go the next place you'll go is SQL Alchemy which is also what SQL model uses and it also uses something called pantic now the reason I'm bring these things up as reference for those of you who are a little bit more advanced for those of you who aren't as advanced or don't know SQL don't worry we don't have to learn SQL we can just use Python that is why SQL model has become so popular is because of how it actually handles what we Define for our database tables and how we can insert data as we'll see going forward so the idea here then is we're going to go into our configuration notice we've got this connecting item here and I can see that there's this database URL argument this is actually the default so if you don't set it it will default to this but I will mention that you can also use others as well so in rxc config.py we're going to open it up there it is it's not actually in there it's not defaulted to anything so I'm going to go ahead and add DB URL to SQL light yes you can use postgres you can use MySQL I think Mar DB is in there as well and there is support for all kinds of other databases in general now what we are using is called an OM or an object relational mapper and we are going to have basically a python class be responsible for how our database table is designed so if we actually take a look at pages and contact what we're going to be designing is actually not a whole lot different than this state element here at least these two lines right here and this sense that what we could do is we can come in here and say class contact and I'll call this my contract entry model and we'll just do rx. model and then I'll go ahead and say pass for just a moment I will say this model at the very end is not necessarily something you will have to put in there the only reason I'm doing model is because I have contact State here I'm just basically trying to keep it keep the actual parent model or the parent class as part of the name which is completely optional for both of these things but it helps me decide where these things might end up being or end up living or at the very least I can just take a quick glance and know hey this is a state class this is a model class that's really it because of how we actually Define our models so in some cases you might go ahead and say your entry model you want to have a column called name and that's it maybe that's the only column that you want to have and so what this would translate into a database well let's actually take a look at a spreadsheet to kind of get an idea as to what I'm designing here so if we go into a spreadsheet and we call it my database this is basically like what we first did which was basically set our database URL which is really just reflex. DB so we could basically call this reflex. DB right so we are basically using some Liberties here to describe how databases work next up we want to define a table the table itself will be like the sheet and in this case we called it our contact entry model now that may or may not be what the table name ends up being that's not really the point the point is we have a database that has a bunch of tables each table can be defined as wec fit just like each sheet can be then we can start defining various columns so the first one I did was name but again I actually want to get the data from my contact us form so maybe name isn't exactly great so we've got a name here but if I scroll down to my form what I actually have is first name and last name so it probably be better that I use first name and then last name right underneath and of course I'm just declaring it as a string type and that's it that's all I need to Define to then have basically a database table with you know first name and we don't need to Define Str Str here but we can do last name and so on right so that's kind of the idea here is as you add more column definitions inside of your model you will add basically new columns in your database so when we do email and message it's like email and message great so what we want to do then is we want to translate an entry from the form into a line in the database so like Justus Mitchell High whatever.com and this is my message right and so you can think of it like that every time you put a new entry in it's going to be a row in your database of course databases are more robust for a lot of data than spreadsheets are spreadsheets have their advantages as is but what I wanted to show you here was more of the structure just to get a mental model as to what's going on when we're trying to store this data for those of you who are a little bit more Advanced you might understand this already but the idea here is we now have this model okay so with this in mind we've got a database defined our first model defined I'm going to go ahead and run the reflex and then DB in it to initialize the connection with that database and run various things from olymic olymic is a way to track all of our models and their migrations we'll talk about that more in just a moment but now that I've got that we're going to go ahead and run reflex DB Mak migrations and then we'll go ahead and run reflex DB migrate okay so the idea here is we only need to run in it one time when we create new models or make changes to them we're going to run make migrations and migrate I will talk about make migrations and migrate in the next part in more detail but for now we're going to go ahead and take a look in the Olympic folder here and what we want to see is in script.py if there's anything going on as of now there's nothing in here there's nothing actually valid as far as the actual database tables there's no database tables yet is what I'm saying this becomes very obvious because as soon as we do table equals to True save that and then run make migrations what we'll see in make migrations it actually generates a new file for us and then when we run migrate it will actually make those changes in the database so what make migrations does is it actually creates these little file reference points for when we want to make changes to our database and so what we're seeing in here is literally changes to our database and then when we run migrate it actually creates those changes it actually runs those changes for us notice the table name contract contact entry model that is coming from the class name itself notice that there's a field called first name what do you know it actually gives us a data type in here granted we didn't Define a data type or anything it just inferred it for us because of SQL model which is great so Olympic is a really nice way to do this but the thing is what I don't want to actually have on my repo is I actually don't want this Olympic coming through what you will want on your projects is you will want this to come through because you will want to keep track of those changes when you don't want to keep track of them like me I'm using this just as reference then I go ahead and remove it we also have stuff about Olympic as far as the init file there's a lot of different configurations you can have but notice that SQL Alchemy is written and used throughout which is what Olympic is all about so I'm also going to go ahead and put this into my get ignore as well so go ahead and add both of those things which of course are optional for you okay so now that we've done our first migration and we have our first database table it's time to actually put an entry to actually take some data and store it in the database table using reflexes sessions now what we did right here was we defined a schema for a database table that means just the structure of the database table and the data types that go into it there's a lot of things that are being inferred here because we just didn't Define this database model in a really robust way because we didn't need to this is actually very simple data that we're going to be grabbing it's not that complex but the thing is if we wanted to do the same simple model in pure SQL Alchemy it's a lot more complex these are still fairly simple models certainly more advanced than the one that we have but this is how much boiler plate you'll have to write for just one single model again these are more robust but it still is very very similar so the nice thing about using the SQL model is it is still able to do a lot of the things that SQL Alchemy does but it does it in a way that's modern python SQL Alchemy has been around for a long time SQL model is a lot newer and has gained a lot of traction for the reason of being able to define a model this way this is probably as easy as it gets so the idea here then is we want to now use this model now if you're familiar with sqle Alchemy this the the way you use it is slightly different but notice that I didn't have to do any additional configuration the only thing I really added in was my database URL which could be a connection string to my SQL or postgres but the idea is all I defined here was the database URL and the model I didn't have to do anything else and now I can start actually using this database itself so let's take a look at how this is done so in our submit method here this is actually where I'm going to want to submit the data so the way this is going to work is I'm actually going to submit it inside of the handle submit button we're going to use something called with rx. session as session so basically every time you want to use a database session you do this then you're going to go ahead and create a new instance of our database so I'm going to go ahead and call it DB entry equals to the model itself and so what can we pass in here to initialize this model well of course we can do first name equals to Justin we can do last name equals to Mitchell and we can keep going throughout with all of the different fields that this database entry model might need or we could just use this form data in here and quite literally just unpack it as you would with python uh you know dictionaries in general once again it's a dictionary I can just unpack it like that so this creates an instance of this model but it does not put it into the database yet instead what we need to do is we need to use the session and then add this data into the database and then when we're all done with that we can do session and then do commit now what's happening in this session is we could add additional entries in here if we wanted to this is not something I'm doing but it allows me to bulk add a bunch of different things not just one that's why we do hey we're preparing to store this at the database boom store this in the database that's what's happening there so that's it now what we're going to do of course is this is where we would then yield out did submit in there and just to make sure that that portion is working so a couple things that I don't want anymore is this start timer I don't need that anymore I'm just going to go ahead and comment it out for now and probably delete it eventually onload we also don't need anymore and then if we scroll down a bit I also do not want the label any longer either for that one because we really just want to see the thank you message that's coming through so back into our project here assuming everything's running just fine I'm going to go ahead and say Justin and then write in some gibberish and then thank you Justin it works still just fine with all of that same data I didn't have any errors in here um it did print out that dictionary still which may be something you want to have happen maybe not but the idea is it's now in there now before I say this is all said and done I want to actually take this one step further and make a change to the form data itself so what I'm going to do here is I'm going to say data equals to form data. copy and now what I want to do is say 4 KV or right actually not data copy but rather just an empty dictionary here but we will do 4kv in form data to items so KV of course is the key and value and we'll go ahead and say if if V equals to an empty string or V is none V is none then we'll go ahead and just hit continue otherwise we'll go ahead and do data k equals to V we'll go ahead and save that this is going to be the data we use now okay no errors next up we'll go ahead and put our name in some gibberish message hit submit oo now we get an error and it's saying that we've got a notnull constraint failed on last name when it tried to insert this data in other words the database is saying hey you need to put something in here when you go into the data like when you want to insert it into the database itself up until this point the something we were putting in there was just an empty string as soon as I did this iteration here I actually checked for empty strings and said hey I don't want data that has empty strings so if we look at that data of course it's going to be quite a bit different it's just going to have most likely two values in here so I'm going to go ahead and submit that once again I get an error so I'll scroll above that error and we see that our data is just these two keys first name and message that is only the data that I submitted so of course what we need to think about is now is this entry model enough do we need to make it a little a little bit more you know verbose or robust than this to allow for empty fields in the actual database itself so before we actually do that I will say as far as handling form data it's important that we continue down the line of hey what can we do with this data can we validate this data further can we tell the user if something's incorrect or wrong that is something else that we would want to think about in the long run to make sure that this data is is good enough to go into the database itself because once we actually do this session portion we don't want to run into any errors like this now granted I could probably put it into a tri block and show something related to the error itself but before I do that I'm just going to go ahead and refine my model a little bit to account for null data or empty data that's just not there now we're going to go ahead and change our model Fe field by simply adding a default value or allow it to be nullable so there's actually two different ways of how we can allow it to be nullable first off we can grab the field that we want to be nullable and we can put a pipe in here and just say none and then we can set the default value equal to none so whatever you put equals and none that will be that default value now there's another way to make it knowable and that is by grabbing inside of uh we'll go ahead and do from SQL model we'll import field here and so I can grab field and set that equal to nullable being true as well so or n not null is true but null of all being true and so these two things basically correspond to the exact thing so we're going to go ahead and run our various migrations for this so whenever you change something to RX model whether that's adding one or changing one of the fields what you then run is reflex DB make migrations so the nice thing about this is it's actually preparing what we want to do and of course in Olympic we will see what's going to happen in this upgrade or this change here it shows us that we have alter column last name notice that it says it's changing it existing type is already in there and then we've got alterate colum like the results are the same the field names are different but the results the same in other words this is the same as just saying this and so this is probably what you'll want to end up with if I run to make migrations now more than likely we won't have any changes happen but we will see that we need to update our database so after you make migrations then you go ahead and run migrate to make sure that all of those things have been changed if I were to run make migrations again I shouldn't see any changes come through since those fields are essentially the same so go ahead and comment that out just for a moment next up what I want to do is actually test out the you know contact page to see if it if it fails now so I'll go ahead and give my name in here and I'll go ahead and put in a message hit submit now it says thank you and we're good to go so the actual data in there is narrowed down to the required fields and our actual form is also narrowed down in the same way great so there is one more thing that I want to add to this and that is a timestamp let's take a look at how to do that right now now when it comes to a lot of database table it's very often that you'll have a field to keep track of when it was entered the actual date and time that it's entered into the database sometimes you'll have a field for when it was updated as well right now what we want to look at is the inserted field the actual time stamp as to when it was created so to make this happen we'll go ahead and do from date time we're going to import date time and also time zone and then I'm going to go into my entry model here and I'm going to declare my timestamp as a datetime instance I also actually might do something like created at the way you name this field is going to be up to you but you want to make sure that it is verbose enough to understand exactly what it means in this case created at seems to be an automated field and that's what we're doing so the next thing is I want to set that equal to a SQL model field once again and then I need to add in a few new parameters here that actually combine SQL Alchemy the SQL model as well as pantic the first one is going to be our default Factory so this is coming from pantic and it allows us to have a callable a function that will give us our default so that default is going to be the git UTC Now call and this is going to return a datetime instance so we'll go ahead and return date time. now passing in time zone. UTC Okay so basically the default is going to get that function just like that so from here what we want to do is we also want to update the SQL Alchemy type to make sure that our database is updated as well so to do this I'm going to go ahead and import SQL Alchemy just like this and we'll use various data types that SQL Alchemy has for Fields now if you're not familiar with this but SQL has different data types for their different fields or different columns so if the column has a certain data type we can actually filter in a Range so for like created at we could filter it by a start date and an end date which is actually really nice but that's on the database side just so you are aware it is very much possible so the actual type of field that we use is actually important so to actually declare the type that we're going to use we can put in _ type as in SQL Alchemy type equals to SQL Alchemy do dat time and then we can pass in time zone being true here okay so very very simple way to declare a SQL Alchemy field I realize that this is multi-layered and for those of you who aren't familiar with this process this might seem like a lot but it is actually fairly straightforward and what we're doing here is not something you'll do very often more often than not you'll have stuff like this this is a little bit more of an advanced field itself so the idea is after the SQL Alchemy type we can also do SQL alchy column and keyword ARs and then in here we can put in the server default which is just SQL Alchemy do funk. now and that's that's it so that's the SQL Alchemy keyword ARs and then the next one nullable being false we do want do we do not want this to be null whatsoever okay so with this in mind let's go ahead and run our migrations because of course we created a change to our model so I'll go ahead and run the reflex DB make migrations just to prepare those changes naturally we can go into olymic and take a look at the changes that are coming through and we see that we've got this altered table created at with all of those things I just added next up we'll go ahead and do reflex and DB migrate and we'll go ahead and hit enter and this of course will create that for us and it will also get give us the default so the default Factory all of the items that were already in the database will go based off of this function right here so it would have been right now for everything that's already in the database but everything going forward will be based off of that timestamp whatever that server is that time stamp for that default in there too great so now that we've got this let's actually take a look at these entries themselves we want to retrieve them from the database because all we've been doing is adding to the database but before I do that I also want to mention if we look at this contact. it's getting rather large so maybe we want to decouple things first then take a look at the listed model items themselves let's go ahead and do that now we're going to go ahead and start decoupling our contact. py page the way I'm going to do this is by creating a new module in here I'm going to call this one contact slash and then we'll use in .p once again as we've seen before and then in here I'm going to start with state. pi so inside a contact. piy I'll just go all the way down to State and then bring all of that cut it out or copy it rather and bring it into state. inside of contact and then I'll get rid of some of the comments that are in here uh like that okay so doing this means that I can get rid of some of the Imports that are on here the next part would be our model model so next to that I'll do model. high and then I'll go ahead and grab that model itself so I'm going to go ahead and copy a bunch of things here paste it into model then back into State I'll go ahead and get rid of the model related items which means that I'll probably need to get rid of a number of imports in here as well but then add a new one which of course will be from model import our contact entry model now the important part here is contact state is going to handle everything related to the model in relation to the page itself so going back into contact up high I'm now going to go ahead and import the new state element that I created so I'm going to get rid of this old one and then we'll go ahead and get rid of the comments as well and then now I'll go ahead and do uh from dot dot import contact right and so contact itself back into my it file I'll now do from. state we're going to import our contact State and then I'll go ahead and just put it into all here and it's going to be equal to that and contact State great so now wherever I need to use contact State I will just do that directly from the contact module so in the contact page here we're going to go ahead and take a look at all of the places where my contact State exists so here's contact state so contact state do there we go so that's going to just replace those values that are not currently in there okay great so that means then I can actually remove the content model too I don't think I have that anywhere else on this page looks like I don't so let's go ahead and get rid of that and then that means my UTC now I can get rid of as well and some of these other Imports in here also great so still have our base page of contact inside of P for now uh but overall what I've got is at least something closer to what I want so now that I've got this I'm going to go ahead and take a look at what I might need to do in terms of reflex so we'll do reflex DB make migrations I made changes to where my database table actually exists so it's certainly possible that I will need to remake those migrations now at this time since I did make some of these changes I would probably want to delete Olympic and actually just go from there because realistically when I'm creating a module like this I would actually create it as its own self-contained module to start not backwards like this the reason we're backwards in this case is because we were working up to it that's really the point here so the next module I'll actually want to create is the for module itself so inside a contact I'll go ahead and do form. piy and that one I'll go ahead and bring in so to do that I will just grab from the form up copy it bring into form. piy and of course this is no longer a page anymore now it's just our contact form just like that and instead of declaring the variable I'll just go ahead and return the form itself so no need to declare the variable in this case I now do not need to import the entire contact module because I'm inside of there instead what I can do is just do from then. State import the contact State and then that being how we handle all of that great so there's our form now these other import I no longer need into my init file here I'll go ahead and bring that in with from form import our contact form and of course that's an element here and I actually have the context State written incorrectly this should be a string on both of these so we're going to go and save that now into contact. I still have contact in here I do have my form but I no longer need it like that I can keep it as a variable if I wanted to and just do contact do contact form and then just initialize it like that this might be a simple way to ensure that the form is actually coming through but realistically I would actually probably want to have it in the locations it is make sure you actually do call the function so that the actual component is being created and returned that way reflex knows about it now that this is in place let's go ahead and take a look make sure that reflex is running we'll go into our contact page and all we're looking for here is errors in this case no errors happened which means that it probably went into the database we definitely still need to update this of course but of course the logic now would be hey why don't we just bring in the contact page into the contact module as well and so I want to do that I'm going to go ahead and do page up high and we'll bring it in so I realized we just did this stuff and we just changed everything we did all these crazy Imports in here and the only reason I am now moving it over is because this is actually how I would design a module like this but we had a work our way up to it we added each layer and component as it was necessary but realistically as we'll see very soon we will start the module like this in this format so it's a lot easier to manage in the long run but now that we've got that I'm going to go ahead and do a few things here so we'll do from for or do import our form and our state both things we will use I'm going to go ahead and replace our contact dot with state DOT where it makes sense and then contact Dot with form dot where it makes sense and it looks like it's just those elements there and I'll go ahead and save that I'll remove this import here I still need the navigation and that base page so now what I'm going to do is inside of pages here I'm going to go ahead and get rid of this import of this contact page and I'll quite literally comment out my old contact page we'll save everything up and of course it recompiles and now we get a 404 the contact page is no longer found now why is this well there's actually a few different reasons for this and the main one is the fact that this module is not being imported anywhere other than itself so what I actually want to do now is we'll go ahead and do from. page we will go ahead and import our contact page and then I'll go ahead and bring that in now and so with this in mind our state and our model and all that sort of stuff probably didn't work either so if we tried to run migrations or make changes on our model there's a good chance that those things didn't work as well so now what I'm going to do is go back into my page I'm going to get rid of this route on here I'm not going to actually declare the route on here or the RX page on here at all instead what I'll do is I go back into full stack python I'm going to bring in contact once again and we'll come back down here and I'll go ahead and add this as a page now it's going to be contact and then the contact page and of course the route being our contact us route and now it's in a new location and it's actually being imported into the entire project so we should be able to see it now once again it's back and if I make some stuff here there it goes and if I did some migration changes some model changes we'll just go ahead and do that really quickly in here uh just for some arbitrary field and for now that arbitrary field I'll just go ahead and say user ID and we'll go ahead and just put an integer or none and the default being none I made some changes to the models so let's go ahead and make sure that those changes can be reflected with reflex make migrations and then hopefully what we'll see is that migrations happen looks like it did inside of Olympic we can go in and take a look at the migration file itself which is this right here we can navigate into that user ID column and sure enough it is in there it's actually going to be ran so we'll go ahead and run reflex DB and migrate there we go and so that should actually make that database table now that we've got a little bit more of a narrow item for our Conta module we are now establishing something that we could reuse at least this methodology that we can reuse across other kinds of data types this entire module here this entire contact module is really about the contact entry model all of it is about this model the state how we actually manage or insert data into the model all coming from the state the page how we render out the form then that turns into that model that ends up being that database model as well it's not like these static Pages these are static pages that up until now basically did nothing right so contact did do something for a while which we no longer want anymore but these pages are now just simply static pages and we could also think about them a little bit differently in the future uh but for now we've got just that and so what we want to do from here on out is build off of the idea of a database model so we can actually retrieve data update data delete data it's now time to actually retrieve data from the database we've been inserting data quite a bit but let's go ahead and retrieve it now so we're going to do this inside of a state class so inside of contact State this is where we'll end up doing it this time left stuff we could probably get rid of I don't think we have it anywhere else of course if I save it I don't have any errors related to it so we're good to go there next up underneath handle submit we will go ahead and Define a new function and I'm going to call this list entries and it's going to take in self and what we want to do here is say with rx. session as session we want to get our entries back from here so we can do entries equal to session. execute and what we want to do is we want to select all of our entries so the select command will come from SQL model we're going to import select here so we are going to go ahead and call execute and then the select on the model itself so the contact entry model in this case then we'll go ahead and do all this will actually give me all of those entries back and so in my state what I want to do is set those entries like this so naturally I'm going to go ahead and declare the contact State I want to have empty entries in here and so to declare this as a data type we'll go ahead and do from typing we're going to import the list class here and it's going to be a list with the value of the contact entry model but the default will be an empty list so that's how we actually can list things out and then assign them just like this great so this function here we need to be able to call it as soon as our page loads we'll see that in just a moment so the idea here is we'll go into page up high and now I'm going to go ahead and to find a new page this page is going to be our contact entries list page and once again it's going to be an RX component and then we want to return something here in our case I'm going to go ahead and return the base page like we've seen before and in this case I'll also go ahead and grab the vstack with the heading itself just so that we have those things in there and then all of the other items for that vstack as we might need in terms of styling it out and there we go so there's our B stack and our base page just like that so with this in mind we now have this contract entries list we'll call it page and then I'll go ahead and grab the init method here we will go ahead and add it into the init method just like that next up what I want to do is obviously route this so since I'm going to be doing a new route I want to go into routes here I'm going to copy the contact us route and I'll call this the contact entries route and just do contact SL entries just like that great so now I've got the page the routing all of that all I need to do is of course have the state working back into the full stack python here I'm going to go ahead and copy this and paste right below once again with contact we can now do our contact entries list page and then our routes we can do our contact entries route great so assuming that everything's running still I will go into here and try entries and actually spell it correctly and there's our contact us great so that's a good sign so back into our page here we're going to change this from contact us to just simply contact entries and I'll change this to something like five this time I will not justify this at the center I just want it to be uh you know basically up there great so we can change the alignment we can do all sorts of things in here but now I actually want to see the contexts that are in here so the way this is done before we mentioned RX page and then onload but now we actually will will not use RX page onload in line instead we'll do it on the full stack python so right in here is where we will call that onload itself so we're going to go ahead and come in here and say onload and this is going to be equal to that State method so we need to make sure that we actually have the ability to grab that contact state so contact Dot and well we do so we can do context State here and then list entries so when it's loaded up it's going to call that function for us and so that will actually bring it in here it's hard to tell if it actually went through so what I want to do is in my State method here I'll just go ahead and print out my entries and see what happened with that print statement and so we'll come back in here and hopefully what we'll end up seeing is a print statement with some values that are stored in my database and there you go we've got created that message all of that stuff in there pretty good so that is actually printing those things out but how do we actually render it on our page this will bring in another element that's actually really cool first off we're going to define a new component and I'm going to call this by contact entry list item and what it will take in here is a contact element which will come from the model so let's go ahead and do model here and it's going to be simply model do contact entry model and so that's the data type of course then I can return back rxbox and we can bring in our model however we see fit in our case I'll just go ahead and do rx. text remember contact we can do Dot and since we are using this data type here using dot will show us all of the different fields that are available to us in my case I'm going to just go ahead and grab the first name here and then we'll do contact and maybe the message itself so message great so that should give us that text in there and then if we wanted to we could add in some padding here as 1 M or something along those lines just to make sure that these entry items are separated out okay so this is for one single item but how do I actually iterate through those items as in for item in list print I something along those lines now when it comes to rendering on our front end we can't do something like this we got to do something a little bit differently and the way we do that is called rx. for each and so inside of for each this is where I can put my list element here and then I have my callback function that will render out whatever that four each is so to make this really simple I'll just go ahead and do a four each and call back and I'll just go ahead and say like you know text here and then I'll just render rx. boox and rx. text of that text and now there here's my call back I'll put in here and I'll go and say ABC ABC and CDE or something like that that is how we end up doing four each and so what we've got in that page now is it's actually iterating through that list in there so we just have a call back function for that I'm going to go ahead and comment this out as well as this one just as reference for you in this case I'm going to go ahead and do rx4 each and the 4 each in this one is going to be based off of the iterable that we have already available to us from the state so we're going to go ahead and do state DOT the context state. entries that is an an iterable that we just created Now by default it's not going to have any entries right so when it first gets loaded up it's going to have nothing which is fine if we have nothing we have nothing what we do though is we have that onload page that will actually add those entries in for US based off of that data type as well and so back into here this should actually have some values in there and then of course we've got our entry item call back here which will then render those things out for me and if I were to save this what I should see is everything related to those items in there and of course we've got a little bit of an issue so I'll go ahead and change this to rx. let's say heading and do contact and first name like that and then I'll go ahead and just put the text below there like that and so I can at least see maybe a little bit different of a look as far as the contact and the message and of course we can go ahead and try this and I'll go ahead and give a another example and just put some more gibberish there and then go into entries oops not entires but entries and there's that other example great so that is how we can list these things out now we we want to make this more robust in the very near term when we recreate a lot of these same Concepts but for a different data type the actual different model altogether but overall that is how we can list out entries we can actually go through and just search all of them now this is a form of database querying right here and of course we can improve that as well or change it to query based off of things that we really want to um and there's a lot of examples of that in the documentation for the various SQL lookups like the SQL model and SQL Alchemy do have a lot of examples of that including reflex also has examples of that as well in the documentation but that's where we're going to leave it as far as the contexts are concerned with one exception these contact entries we probably don't want anyone to see them so we'll probably have to come back to change how this is accessed if it's even possible to access it for any one user but that's something we'll look at in the future now we're going to go ahead and create a brand new feature starting with the data model so instead of starting with the pages and working up to the data model we will start with the data model and then work up to the pages now the reason I think this is a good way to go about creating new features is because then you can think about exactly what you want to store first and then build features around that to ensure that that happens so first and foremost we're going to go into our project here and I'm going to create the blog module and we'll call it init.py and then I'll go ahead and create the very first one which is of course model.py and there we go so we'll go ahead and import reflex as RX and then I'll create my blog post model and it's going to be rx. model and we'll go ahead and say table being true now do keep in mind usually what I would actually call this is something more like blog post or just post itself but I'm leaving the model in there to make sure that it's distinguished from my other features and so it's really easy to see what's going on with every part of this application so once I have the blog model itself we have to think about the fields that we're going to want for this now of course I want a title field and a Content field itself right and if you think about other kinds of models let's say for instance you wanted to do an email model this is basically the same thing but it would be a subject and content and maybe something like HTML content or something along those lines so you can think of this blog post model as a general model itself or a general data type that you can then reuse in other places so to make it truly General we need to add in a a few other fields eventually we're going to go ahead and add in the user field itself so what user owns this blog post or is creating this blog post that's one thing that we want to do for sure sure but that's a long-term one the other ones are going to be something like created at updated at and then maybe publish date and maybe publish time so those things are what we're going to add in what I'm going to do right now is created at and updated at because we've already done it before in our contact model so if we go down to our contact model we've got our created ad here so that's what I'm going to end up using but before I actually build that out I want to make sure that my git UTC now is reusable so going back into the root of my project here I'm going to go ahead and create utils and then init.py inside of here I'll go ahead and do timing. py and then I'll just go ahead and grab this datetime object here into timing and something along those lines like that and then in my utils here I'll just do from do import timing and then all being timing great so back into my contact model now I'll also go ahead and do the from. import utils or rather from dot dot or like that and we will go ahead and update utils to timing. getet UTC now so we're using that instead of our get UTC Now function right here and then we'll go ahead and jump into our blog model and do that same thing I'm going to go ahead and copy that created at because it's fairly straightforward and hopefully you have an idea as to what to do with this one so with this in mind we're going to go ahead and bring in our uh date and time so from date time we'll go ahead and import date time and we'll also import SQL Alchemy I don't think I need to import time zone it looks like I don't so import SQL Alchemy and then from SQL model we'll go ahead and import the field and there we go so we got our created at and so now we can duplicate this to being our updated at field so we'll change it from created at to just simply update at and the idea here is that when the database table this Row in particular changes we want this field to change as well to that time and the way we do that is by doing on update and then we use the same SQL Alchemy function right here so that it will update this field whenever this rad changes that's actually fairly straightforward but now that we've got that we've got the Baseline model that we want let's go ahead and run our migration so we'll go ahead and do reflex DB make migrations we'll hit enter and something to note is well did it actually create the migrations something I did off video was I actually deleted my olymic stuff as well as my database and my initializing and I just wanted to start from scratch and so I actually can see what's happening here the only migration I have at this this point is my contact entry model I don't have any other migrations in here this of course is because reflex doesn't actually know about this blog module and therefore we'll not find model.py in there sure we import something and we also import reflex but we need to make sure that our main project here knows about it so the way we're going to do that for now is going to import our model and we'll go ahead and put it in here as well as inside of all and then we'll just paste it in here like that simple enough then in fullstack Python our Imports here I'm going to reorganize them a little bit I'll put contact first and then I'll go ahead and also bring in blog granted I'm not using it yet but this will at least allow my reflex project to know about this blog module and that would be true for other models as well you the reflex project needs to know about it it's not going to look inside of just random modules to find those things so now when I run reflex DB make migrations it actually goes ahead and runs those migrations and then if I do reflex DB and migrate I get that migration as well great so now that we've got this what I want to do is I'm going to start the process of everything I'm going to leave the publish date and publish time for later because they are going to need some specific use cases and some uniqueness to them as well as the user we have to implement off later to actually have our user which we will as well let's go ahead and start building out the rest of the blog post model related to crud create retrieve update and Destroy let's take a look now that we have our blog post data model let's go ahead and create our blog post state so inside of our blog here we're going to go ahead and create state. and then we'll go ahead and import reflex as RX and then we'll do from. model import our blog post model and then we'll go ahead and create our blog post state of course it's going to be rx. State and and it's capital state there we go and so what we want to do here is we want to declare a couple things related to this the first one we'll go ahead and just get our posts now we've already seen this one before but I want to go ahead and import you know from typing we're going to import optional and list so post themselves we're going to go ahead and put it in as list of the blog post model and we'll set it equal to an empty list we saw this already next we'll go ahead and do a detail view as in just simply post which is going to be an optional post itself which I'll set to being none okay so to start out we're going to do the git portion of crud that is retrieving items in here so the first one is going to be something like load posts and it's going to just take in self and we don't necessarily need to return anything but I'll leave that in for now as just simply pass next up we're going to go ahead and do get post and we will do pass as well so to start out we'll do load post this is going to be by far the easiest one that we'll need to set up because we've already seen it so that also means that I need to import a few other things related to SQL model so the first thing is we're going to do from SQL model we're going to import the uh select function so that we can come in here and do with rx. session as session we're going to go ahead and do our actual post themselves so we'll go ahead and say result equals to the session. execute and then we'll put underneath here the select and the blog post model okay so something we need to think about in terms of this results here is we might need to change it to based off of what's actually published so to start out I'll just do all posts and we'll think about it later as to publish posts um and so the result here course will then just be self up posts and that's equal to that result and then that's it okay so naturally what we can do then is take this same sort of concept in here and then grab the session and now it's going to be our results in here this is going to be a little bit different because we need to grab the post ID whatever that post ID ends up being now this presents a problem with our current knowledge of reflex so I'm going to go ahead and keep the G post out for now and we'll come back to it the first thing I'll Implement is our load posts and we'll do that in a page next then we'll do our detail view after that now we're going to create a list view or the list page for our blog posts now we've already seen a list page before with our contact entries so I'm actually going to go ahead and copy all of this stuff and we'll modify it as we go forward so inside of the blog here I'll go ahead and do list. py and we'll go ahead and paste this in here and just change things as necessary to our blog posts right so we got our blog post list item here which I'll reuse down here and then we want to go ahead and change this from contact to just simply post which will be our blog post model and then we'll go ahead and do our heading being something like post and title and I probably don't need anything else I don't need the content yes because this is just listing things out so I can click on it and take a look at more things next up of course is going to be our actual blog post list page so we'll change this to blog post and list page and we'll just do this as blog posts okay and then the state item itself well that's going to be instead of entries it will be our blog post State and then our posts themselves great simple enough not a whole lot different than what we've seen I'll get rid of this form here and now what I want to do is bring in my list page so to do this I'll go into the blog itself and we'll do from. list import the blog post list page and then we'll go ahead and bring that in as an argument there back into fullstack python I can now implement this blog import here and will come down right above contact I'll go ahead and do my blog. list blog post page naturally I need to update my routes so I need to make sure that I have something for this so once again right above contact us I'll go ahead and do my blog posts route and I'll just call this simply blog there we go and so back into fullstack python we will change that to this right here great so with this in mind let's go ahead and make sure our project is running looks like it is let's take a look at it and let's just navigate over to our blog here and of course I don't actually have any blogs yet but the actual route is showing up now of course the next thing that we did Skip in here was related to to our state so we also want to go ahead and add in on load to handle our blog do well blog post state which I don't currently have imported in the module itself so let's go ahead and bring it in so from. State we'll go ahead and import that state there and then we'll go ahead and bring that in here now we'll go back into our full stack python module here we've got our state and then we'll go ahead and do the load posts call here just like we did with the list entries and so now that we've got that I probably still won't have any entries because I haven't created any of them I don't have that field up yet but before I actually do create them something we need to understand or think about is how we're going to link to them so in the case of our heading here what I want to do is I'm going to do our blog post detail link right something along those lines which will also take in the post as argument and then we also might have a child element in here as well which will be of type rx. component and then we want to return the link itself so rx. link right and inside of that link we will go ahead and put our child the href itself will be based off of the post so the post ID is going to be post. ID don't worry I'll explain this ID thing soon enough then the post detail URL is going to be equal to well we've got our navigation. routes Dot and our blog post route which is the root route so this is going to be our root path is really going to be this right here and so that root path we will then use some string substitution in here for that root path put a slash there and then put our post ID at the very end and so this is going to be what our href is naturally if there is no post ID then we would say something like basically if post is none then we'll just return rx. fragment of the child basically returning that child element and then we can also say the same idea if the post ID is none then we'll do that same concept there great so then now with this in mind I'm going to go ahead and bring in this link here and I will go ahead and do my link so the first part is of course the child element that's going to be rendered around or inside of this link and then I also want to pass in the post argument itself so naturally we'll have to see what this ends up looking like there's still going to be some tests for this uh but of course what this also means is that we need to learn how to do the routing here now before I actually do that routing I actually want to create these post objects so I'll go ahead and create the form and the create view first so very similar to like what we did our contact page in here but before we go away I do want to update my navigation one more time and that's inside of my UI here I'm going to go ahead and add in another navbar item for our blog and this of course is going to be navigations routes and our blog post route save that and we should see it up here now and I should be able to navigate into that blog great next step of course is taking that same concept once again is we now need to add in our blog navigation here as well and so it's going to be blog and then nav State and it's going to be to blog and we of course need to bring you that in as well so we're going to go ahead and grab our navigation State and let's go ahead and copy the two contact and go right above that and then to blog and then our blog posts route and let's save it and we'll go back into our main project here we'll click on blog looks like it navigates to us and then I'll go ahead and try the same thing oh looks like my navig failed so let's go ahead and take a look at our state this looks fine so let's go ahead and look into our terminal and sure enough I got no Json serializer found of posts so what this is telling me is there's something related to SQL Alchemy and general and so what I think it is is related to the state element itself H yes in load posts this should Beall that is one thing that I missed on here after you do that select you do do all now it refreshes so let's go ahead and try that again navigating to different pages there we go if I break it down and go into the blog it takes me back okay great so now that those things are all situated let's go ahead and start our create process I actually want to load the posts before I see the detail of them let's take a look so far all we've been doing is static URL routes we now need to see how to do a dynamic route now the dynamic route itself of course is going to be related to any given blog as it stands right now when I go to link one of these blogs the ID shows up in the URL but I have no way to really handle it now what you could do is you could hardcode every single one as in you could come into your pages here and you could do something like you know the blog page here and you would do something like SL blog and one and then do it again and do blog and 2 so this is kind of the method we've been doing is we've been designing the actual URL what should be rendered there but of course that's not what we want to have happen instead we want it to be dynamic it's really easy to make it Dynamic you just change this into a bracket and then you can pass in whatever argument you want so in my case I'm going to go ahead and just call this my blog ID so we can see what that ends up looking like now in order for us to actually see this I'm going to go ahead and render out a static page of some kind in this case I'll just go ahead and copy the about page and I'm going to bring it into my blog here and I'm going to just call this my detail page and of course we'll just rename this to being our blog post detail page I'll leave everything else out but the one thing I will change is this about us I'll go ahead and say blog post detail something like that so with this in mind I'll go ahead and grab this we'll bring it into our init method here from detail we'll import that in and then we'll go ahead and put it here and then of course we'll go back into our full SE python here and then in our ad page method here we'll go ahead and bring in our post detail page so if we save that now and I go into my blog posts I can now click on one of these and it says blog post detail and now it's actually showing up but it's also showing up for IDs that simply do not exist in the database yet so if I go to this one this is not a valid post at all so we'll have to adjust for that or account for that but before we do what I want to see is I actually want to see what's happening in terms of the blog post itself like how do I actually access something related to this blog post well the way we're going to do that is by going into our state object here I'm going to go ahead and create a new variable I'll go ahead and do rx. varar and we're going to define the blog post ID and it's going to take in self and for now I'll just go ahead and return one but what I want to do is I want to print out self. router. page. prams as in the URL router for each page what are the actual parameters that are coming through in here so in order for this to work we're going to go into our detail page and we'll go ahead and do from. ort State and then I'll go ahead and come into my heading here right after it I'll go ahead and do rx. text and we'll just go ahead and put in state. blogpost model and then our blog post ID I think that's what we called it yeah blog post ID and this is not our model but rather our state and there we go so that's going to be our ID now so let's go aad and take a look and if we save this detail page with commas we should be able to see the actual ID that's coming through from this argument here or is it let's change it to something different of course it didn't actually change but if we look at our print statement we now have some arguments that we can actually use inside of there so in our state then we can actually return back our pam.get blog ID or none right so basically if it's not in there it could be something like that we can also put a fallback like this where it's an empty string value and then once I do that it updates to that ID now that's not the only parameter we could have in here we could also put something called query parameters and say something like ABC equals to 1 2 3 hit enter there and we also see those as being parameters as well so both of these actually end up working the question of course is what if we actually put in blog ID 1 two 3 in here what ends up happening is it actually ends up defaulting to the URL router as we can see right there so that's actually really important because we definitely want it to do default to that URL router but both of those parameters can be really useful for looking things up I'm not going to go into too much detail on the other one the query parameters router but it is nice to know that it exists so once I do have this blog post ID here now I can start thinking of well on my detail page how do I actually render out that blog post well it comes back to the state itself we have load posts well what about our detail post so we can now go ahead and say get post detail or something along those lines where we are now selecting that blog post model and what we can do is we can actually put in here a another condition right next to the select where we do where and we grab the argument that we want to pass in which is our blog post model. ID and we set that equal to well this variable right here so we can do self. variable and then instead of all we do one or none and this result then will be our actual post and this should say one or not one or one but one or none um and then we'll put that result in here just like that so realistically the ID will pretty much never equal to an empty string so that should probably be none and of course we could also check in here and say something along the lines if the actual item is equal to that then self. poost is none and then we can just go ahead and return this okay so the idea here now is grabbing this blog post detail when we render out this page so just like we've seen before we can now now do that on load method again and we just do our article state so it's going to be just like our list view here but instead of load posts it's going to be G detail or get post detail the other thing would be maybe get one post or something along those lines and so what we'll see in here is of course now I can actually grab the post element itself so instead of this here I can just go ahead and do state blog poost State and then title or rather post. tile and we can go ahead and save that and what we can refresh in here 12222 does not actually have a blog post title if we look at the blog post itself it does come back in here it does so naturally I want to change the way this is rendered I'm going to get rid of this justify Center here the textt itself we're going to go ahead and grab the post title cont or the post content so we'll do post and then content here and then we now no longer need to put the ID there at all and we can save this and I'll get rid of this child element here as well and so now what we should get is the actual blog post itself which is kind of hard to tell because I didn't put much content into these blog posts but we can now route to Any Given detail which also means we can start the process of you know editing the detail as well which is going to be very similar to what we have here but just using a form in a slightly different way so that's actually pretty cool now that we've got this let's go ahead and start that editing process right now now we're going to go ahead and implement the methodology to actually insert a blog post into our database now it's going to start with creating a session variable or session object just like this so we're go ahead instead of load posts we'll go ahead and do add post and this should take in something like form data okay and of course that's going to be a dictionary itself so we'll put that in as well next up of course instead of being results we'll go ahead and say post equals to well the blog post model and unpacking the form data as we've seen before this post eventually will be equal to this one right here so once we to make that actually happened we just go ahead and do session. add that post as we've seen before then this is just preparing the database for it once we do session. commit it will actually have it in and then we can also do session. refresh of that object to make sure that it is correct and it's from the database and it should have something like post. ID once we do that refresh great so this is the blog post state that we want to use but now of course in order for this ad post to even work we're going to go ahead and create another state element in here and I'm going to go ahead and copy this one and I'm going to call it something different this is now going to be our blog post form state or I'll just call this the blog form state so it doesn't get too confused with the blog post State itself now what is it that I'm actually trying to do in here well that is just simply having our form data which is going to be a dictionary itself and it's going to be empty and then we want to handle the submit method whatever that ends up being of that form data and we'll just go ahead and do self. form data equals to form data okay so this is fine for handling submit data but the thing is I actually want to handle this ad post method in here as well so what I can do then is I can actually implement this State method to inherit from the blog post State method so that I can then do self. add poost and just doing our form data just like that and so that's a simple and easy way to extend our blog post States so that we can reuse it in other forms in here I'm I going to change this actually to blog add form state or add post form state or something along those lines to make it as verbose as possible for the actual form we're going to end up using so the next thing is actually grabbing a form that we can use which is coming from contact I'll copy this entire module bring it into my blog here and I'm going to just change it to actually forms instead of just form so this of course is going to now be our uh you know blog post ad for we'll start there and a lot of the inputs are going to be the same the first one is going to be our title input which will change the placeholder to title I do not need a last name input at all I will keep this hstack in here just to see how it gets rendered out mostly next up I'm going to get rid of the email itself then we'll come in with our text area here this is going to be content and then our message here we also might want to add in a height element here being something a little bit different let's go ahead and say 50 VH or 50 vertical height whatever the vertical height ends up being and that will be our text area let's see if that ends up working of course the onsubmit is no longer contact State now I'm going to just go ahead and import State Al together and then down here we will go ahead and do state DOT and this is going to be our blog add post model form State and then we're going to go ahead and do handle submit just like that okay so simple enough the state element is in there it should be able to actually add that data in here and of course we can verify that inside of our ad post method here we can go ahead and say print adding and then you know print out what that post blog model is going to be so we can just verify that that's ends up working so with this in mind I'm going to go back into my contact again and bring in the page element in here I'm going to call this addp and I'll get rid of some of the other elements in here that we don't need and I'll just go ahead and do our contact page and this will be our blog post ad page which of course has this child element this is now going to be our new you know blog post something like that we are not going to have the condition state in here which I'll explain soon enough but then we'll go ahead and make sure our form is in here justify Center I'm going to get rid of that a line Center I will keep but I'm going to get rid of justify Center as well as that and then I'll do my minimum height being let's say 95 vertical height um or rather viewport height next of of course is the form element itself now I'm going to just go ahead and change this to being simply my form and doing form Dot and then whatever my for or rather it should be forms so in here forms Dot and then the blog post add form there we go and of course we want to initialize it so I'm going to go ahead and replace some of these elements in here and we will now see a form element coming through okay so the next things is do we need any of these other Imports I don't think we do so I'm going to go ahead and get rid of this and that okay so now we've got our blog post ad page let's go ahead and bring it into our init method here so we'll go ahead and do from. add we'll import that blog post ad page put it into all then we'll go back into our fullsack python app here and I should already have blog imported and then right underneath our list page here I'll go ahead and bring in my blog post ad page and then our route what is it that we want our route to be should we put it in our navigation route we'll talk about that in just a second I'll get rid of this onload method the ad doesn't need to to be there whatsoever so there's a bunch of different ways and how we can think about this ad route is it going to be reused a lot I think it actually might be at least a few times so I will actually put the route in here if it's only going to be used one time then perhaps we just go ahead and do something like blog ad but since it's going to be probably used multiple times I will change the navigation so that we can uh reuse it wherever we need to I'll go ahead and grab this blog post right here and now I'll go ahead and do blog ad post route or something like that or maybe post add route and then I'll go ahead and add add to the end of this okay so with this in mind I'll go back into my ad page and save that since I am putting it into routes here I'm also going to go ahead and put it inside of my nav State and then we'll go ahead and do blog to blog ad oops let's get rid of that and two blog add and then I'll also actually duplicate this to being something like two blog create and just returning self. to blog ad and then we'll go ahead and do blog post ad route there we go and so now I have two different methods that will actually go into that blog post route and then in my actual blog post elements here the list item I'm going to go ahead and add that one in for a particular particular button so we'll go back right here into maybe underneath the heading we'll go ahead and do rx. button and we'll go ahead and do new post and of course with a button like this we'll do rx. link and we'll bring in the href being equal to No Surprise href being navigation. routes. blogpost add route and just making sure navigation is in there sure enough it is and there we go so let's go ahead and make sure o let's put a comma here and let's go ahead and make sure that our reflex project is running it sure is now I've got this button for new post now I have a way to write a new blog post and we can say hello world this is my new post exclamation mark hit submit nothing seems to happen let's go into our blog here and there it is the post actually does show up and when we go to print it out we've got this notice it says adding I equaling To None now I did mention that I will come back to the IDS because of that blog post link that we have up here right so we do have a post ID going back into add again or rather the state element to add it I want to go ahead and say print adding and then underneath the refresh call I'll go ahead and say added and then we'll take a look at that one right there and so going back into our new post another new one with some message hit submit what we've gotten here is another new one and now it has other data in here and what do you know ID equaling to two so by default SQL databases will create an ID for us especially when we create something like a model using an omm so sort of a hidden field that's in here is called ID it's an integer and it's called a also known as a primary key which means that it is going to be a unique value for this entire field now going back and thinking about our actual um spreadsheet that we had each row had a row number that's kind of the general idea here is every time you insert a new item a new ID is going to be issued for that item and it happens in a specific order which is why I wanted to show you before you add it to the database and commit it then after you add it and commit it it will actually have that data so since I did refresh this I am able to set the state element with that post value whatever it might end up being now this is going to come into play after we do all of this I actually want to handle some sort of method for a redirect but before I can do a redirect so we will add in a redirect here before I actually do that I need my actual detail page working so I can actually see the individual post let's take a look at how we can do that right now now we're going to start the process of editing being a database entry so whatever is in the database we want to be able to look it up and then edit it in a form now before we actually do the lookup portion of this I just want to show you how to edit with a form itself so what we're going to do then is I'm going to jump into the blog and we're going to go ahead and create a edit page in here and I'm going to do everything inside of this edit page so we'll go ahead and import reflex as RX and I will actually grab the original ad form because we're going to use essentially this to some degree when we go and edit it in the first place but for now I'm going to go ahead and just do this add form here and I'll get rid of this on submit for what it currently is to changing something like edit example and state so we'll go ahead and create a edit example State and it's going to be rx. State and then we're going to go ahead and Define handle submit and it's going to take in self and form data and then we'll just go ahead and print out that form form data okay so I'm going to go ahead and copy this and use the you know handle submit down here so nothing about this is new most likely so let's go ahead and implement this as a page and I'll just call this blog post edit form or sample form something like that and I will go ahead and grab Addy and copy a lot of these things in here bring it over into edit. just so we have all the form stuff correct or at least related correctly in terms of how it will end up up working I'll go ahead and do this uncomment out this import for just a moment because we're going to use this form as our default form now okay so we're going to call this edit blog post just like that there we go and so the idea here of course is to then add this into I'll just call this my blog post edit page for now we'll do this import into our main module here so we're go and import it here and then we're going to go ahead and bring it into our main configuration for our various pages on fullstack python module so we go ahead and copy the detail page here for now and I'll go ahead and just add in sledit because that's what it will be going forward and then it's going to be our blog post edit page okay so we don't need to really worry about the edit the post detail stuff just yet so what I will do though is I'll go to a blog post and then just go into sledit okay so this should render out this form here so what we want to do is we want to pre prefill so what we want to do is we actually want to fill each one of these forms with data default data so the way I'm going to do that is going directly into the example state that we have here and I'm going to go ahead and say title is a string and it's equal to hello world and then content is a string and equal to this is my blog post okay so we're going to grab this example State and then we're going to update each input so the first one we're going to go ahead and do do our default value of the State value. Tile and then we're going to go ahead and do the text area we're going to go ahead and just say value equals to the example state. content okay and so whenever we declare something like value we also need to do something like on change where then we can actually set the new value itself so in this case I'll just go ahead and do handle content change and then I'll go ahead and Implement handle content change here and of course it's going to be that value so we'll just do self. content equals to that value and so now with this in mind we'll go ahead and take a look at our example blog post page and let's go ahead and make sure that everything's saved up and we'll refresh this page assuming that we have no errors here at this point we hopefully don't let's go ahead and just restart that server and see if that solves those errors there's probably something cached with the error itself and so now we've got this in here okay so when I have it as the handle change I can actually type something in here and hit submit and naturally nothing really happens but it does say that gibberish data that's in here as soon as I get rid of this on change method here I will see that well let's go ahead and refresh on this page I actually won't get that data so if it's refreshed I can't even type it won't even let me type in there so I need to actually change it back to onchange now one of the things you can't do in a text area you can't set a default value that just doesn't work so as soon as we save it it will actually change to being an empty message it just doesn't work on the text area and that's it so what we do instead is we need to actually handle the value itself now something else that's kind of cool is we can actually infer that there is a set whatever the arguments are up here value as well so down in the on change I should be able to just call set content just like that and then we'll go ahead and refresh in here again and now I can go ahead and change this as is and I actually don't even need to implement that method now the actual text input the one that we saw before that default value works just fine and we can see that by submitting that data so the said content method is something that is actually really nice it's just a convenience method that's built into to the state itself so with this in mind I can now think about how I want to design my editing because realistically I just need to grab the blog post detail this actual these values and put them inside of the form itself and then once they are in the form they'll be all rendered out and so that's something we will do very soon now the other thing about this reset on submit this actually doesn't make sense anymore because we already have values that are being set for these inputs so even though if it tries to reset it it's just going to go ahead and add those original values back anyway or whatever I change them to according to the state but of course if I refresh this page right now it doesn't actually store this data it doesn't save it anywhere so naturally we need to update that but the important part here is the fact that we on a text area we declare a value once we declare a value we need to implement a change value or an onchange Handler the same would be true with this up here is we'd have to do value and then on change and then actually listen for those Chang es which we can do by setting that you know set title here as well so any sort of input works that way text area in this case does not have a default value you actually have to set the value and then listen for those changes the input can have a default value or you can set the value directly and also listen for those changes so that's just a slight thing that we need to understand about text areas themselves now that we've got this in place let's actually go ahead and use real data and edit that real data and then save save that real data now the reason that we actually did this example of using preset data is of course so we can replace it with real data from our database so the way I want to do this is by jumping into state.pay and I'm going to go ahead and copy the blog ad post form State into being something new which is going to be of course our blog edit post form or we'll just go ahead and call it our blog edit form State and so in here what I want to do of course is my content and this is going to be a string value itself which I will set it equal to maybe an empty string now when I do something like this it automatically makes me think oh in the original blog post date this is actually where I should set that content value and that's where I'm going to do it so I'm going to come back up here and we'll do our post and instead of post I'll just go ahead and say post content and this is going to be a data type string or none and I'll set it equal to none to start out or what might be better is really just setting it equal to an empty string here so we're going to call it post content mostly because it's the detail content so that means when I actually go to get that detail value I'm going to go ahead and set it as post content equals to result. content or whatever the post value is which of course we could also just do self. post. content both of those things will be the same and so now I've got this in here and I'm just going to go ahead and leave it in as a empty item so that I know that I can use that content at some point now before we actually handle the submit method we will go ahead and print out this form data uh because this will be the state we'll use now now inside of my edit. I'm going to go ahead and do from dot State we're going to import the class itself directly now the reason for this is so that my edit form will adjust as well so I'm going to get rid of this example edit State and we're going to go ahead and use our blog edit Post State here and the first thing I want to do is set the actual blog State and post then I'll go ahead and set my post content to being the blog post State and post content remember the blog edit form state is coming from the blog post state so it can actually use all of the same elements that are in here it's just inferring things a little bit differently when it comes to handling submit just like we did with the ad post itself and the reason of course for this is so that we can use those methods as well as the content that's coming from that state so we're extending it quite a bit okay so that gives us these items in here so naturally what I can do then is title being post. title or something along those lines and so now inside of my form here I can just set the default value being title and then I can use the blog post State set title that should be inferred and that should work just fine or I could just stick with default title there's no NE it's not necessary for me to actually have the onchange method in here if I really just don't need it in the case of the post content though I definitely do need it so I will bring that one in down here and we will then set it just like that and then we'll handle our submit method here there is one more input that I want to bring in though and that is going to be on the roots of my form here I'll do rx. input and this input itself will be related to the post as well and so this is going to be hidden and I'm going to give this the name of Simply something like post ID with the value of post. ID right and so the reason for this has to do with how we're going to end up updating this input itself and let's make sure we've got all of our commas in here and there we go so now I should have all of the data as needed inside of the form itself which is now being rendered in that page so since I have this form in here I'm actually going to go ahead and bring it into my form so we go Ahad and cut this out and go into forms now and I'm going to bring it below my ADD State form here just like this and then I'll go ahead and cop cut this up here and I'll actually change my input a little bit for my ad so that the only state values are coming through as classes themselves and we will put those around a parenthesis like that and then this is the ad post form State I'll use instead of state DOT which is really just one element I believe and so there now it clarifies that a little bit and this of course is now not a sample form but rather the actual form and so back into edit. py I will go ahead and do from forms we'll just import it now as forms Dot and then we've got that form I don't think I have anything else in here related to the actual edit page itself but I definitely could one of those things that I could add is the actual State element itself the actual edit form State and we might as well so I'm going to go ahead and bring that in back into the uh edit. piy we'll go ahead and bring in and we'll do from. state we're going to import the blog edit form State and the reason for this has to do with grabbing our post and then we're going to go ahead and do something like that and now I can use that as my heading in here Al together so I'll go ahead and do edit and then just simply the post. tile or maybe something like editing with a little space there of that post. tile and now let's go ahead and see and make sure that everything's running with reflex run and hopefully our edit page will now have all of that stuff pre-filled and almost ready to go uh but of course we've got something in here and so we've got no attributes set content oh yes so we made one slight error so we've got our post content here that is the attribute itself going back into the state itself we did post content so back into the form the handle change method needs to be set post content right just like the actual value itself and so once we do that that should I think solve that problem so let's go and reflex run again and it looks like it did once again it's inferred that you can actually set it there is that Setter on there and so we go back into this edit page now and if everything's looking right we now see our data now there's this input in here this little box that's showing up we'll fix that in a second but now I've got this this is my new post if I hit submit here I think I should still have that print statement and there is that new data so here is my updates or something along those lines we hit submit and there is that data great so it's actually showing me exactly what I want to have happen in terms of the submit method itself for that edit now the input here is just being rendered out so all I'm going to do is do rx. box and put this around here and we will just wrap it around so that I can do display being none so it's actually truly hidden as far as the input is concerned how things are being rendered out for General inputs doesn't necessarily hide that by default so with it being HED it's now gone and that of course is going to be that post ID in there as we saw in our print statement uh just a little bit ago it actually showed us the post ID now this has to come back to our state. so in here when we want to actually update this so we've got our handle form here I now have a post ID in here that I can get or quite literally pop from this element here so when we submit it we're going to go ahead and pop it out and that is going to now be what we are going to handle so we've got our post ID and then our updated data and that's going to be equal to that new form ID and so we can actually go ahead and do Post ID and updated data we save that let's go ahead and submit it again assuming that's our only print statement we go and submit it at the very bottom we now have an ID with some updated data great so now what we can do is we can actually edit this post so down next to add post we're going to go ahead and copy this right here this time I'm going to go ahead and do edit post so edit post needs to take into effect the actual uh you know post model itself so we need to actually use something like the lookup for the detail and so what we're going to do is we're going to grab this Result One or none thing here we're going to bring it down into our edit post and we're going to paste this in here so once again it's post ID which should be an integer and then we'll go ahead and say updated data which is that right there so first off we need to grab our result which will be our actual post itself so we can just call this post and then I'm going to go ahead and comment these out for just a moment and basically we want to see if the blog post model. ID is equal to the post ID that's being passed into this edit post then we're going to go ahead and if it's not basically we'll go ahead and oops let's go ahead and get rid of that if it's not then we'll go ahead and say if post is none then we'll just go ahead and return which it could be if if for some reason it was deleted before we went to go edit this next what we're going to do is we're going to go ahead and grab for key value in updated data. items we're going to go ahead and do a set attribute on the post the key value items so this is the same concept as doing post. tile equals to the updated data. g. tile something along those lines that is the point once we actually have that then we will go ahead and do our session. add of this post now the important part is it is adding this to the session and then we're going to do session. commit and the thing is this post has an ID in it so we are looking up the value based off of this ID we are going to have a value back which will also have that same ID in there then we update any of the values we need to then we actually commit those changes and that's pretty much it and then we can do session. refresh of the post and then we can redirect if we wanted to so I'm going to go ahead and leave it as is for now and then we'll we'll go ahead and leave this out like that I no longer need some of these other comments but now we should be able to actually edit the post we could call it like save edits maybe so I have it as self. add poost this could be edit post or save post edits right just to make it very verbose there we go and now let's go ahead and give this a shot so inside of our edit page I'm going to go ahead and say hello world this is my new post and do something ridiculous like that hit save I get an error here so let's go ahead and see what the error is in our reflex docs here and I got this missing positional argument here that's actually a good sign because that means that in my uh State element here I actually made a mistake which was all I did was submit the form when I should have submitted both of these things right here and just like that now that we save it we should be able to actually do those updates once again so I'll go ahead and clear out the cache by restarting reflex once again and then we will go ahead and refresh on this page and here we go and so now I'll go ahead and once again edit this page with the spacing and all that hit submit and sure enough nothing seems to happen so let's go into our blog and take a look at that hello world there and there is our post coming through now it's not formatted very well because of the space being gone but the actual post has been updated which is pretty great so now of course we need to update the detail page a little bit more we want to add some formatting and we want to add an edit button based off of a condition so yeah that's actually how we can edit different form values and of course there's a lot more to it in the form itself we could do a lot more inputs in here if we wanted to so we also want to add in a publish date input and so that's something that we will do as well let's take a look all right so now we're going to go ahead and update our detail page so that it has a conditional value for an edit link so that means that if we have a Boolean value something like can edit I'm going to go ahead and say true to start out then we're going to go ahead and create our edit link which will be rx. link and of course it'll say edit and then we'll go ahead and pass in the href being based off of the state itself so I'll go ahead and do uh you know something like SL blog and then the blog post State and we'll go ahead and take a look at the state what we want in here is our blog post ID so go ahead and grab that one and then do slash edit there we go and so that should give us our edit Link in here but of course we want it to only work if edit is possible so we'll go ahead and do edit link element equals to rx. condition and and the condition of course is whether or not it can edit and if it can edit we'll go ahead and render out that link if it can't we'll just do rx. fragment of an empty string remember whenever you're using this condition you need to be able to have basically the same data type coming through both of these things are components so it is the same data type and now we'll go ahead and right underneath this heading I'll go ahead and do the edit link itself and then we'll refresh in our server let's go ahead and make sure it's running with reflex run we should be able to see that button in here rendered out so we can actually go and navigate to that edit and there we go and if I were to toggle can edit to being false I should also be able to see that as well uh where it goes away great so we'll add those permissions soon enough but for now what I want to do is also test one thing and actually go to a page that doesn't exist I get an error this error is saying none type has attribute contents you may saw this that's because inside of date. piy what we've got here is we are trying to set the content even if the result for the lookup is none so basically we will go ahead and say that if the result is none then we're going to go ahead and do self. Post content being equal to an empty string and then I'll go ahead and return here otherwise it will go ahead and set that value uh as is and so I'll refresh in here now it doesn't run the error but of course if I go to a page that it actually works it will show it that so I'm going to go ahead and keep that condition being true just to make sure that I actually can edit it and eventually I will update how that condition works based off of State values but for now we're almost done the next thing is the actual detail page itself well we need to update our state here a little bit and so right now what it has is well the text is just kind of running a muuk right it's going crazy in here and so what's happening is it's actually not uh using the white space correctly so we're just going to go ahead and do the white space and add it in as pre wrap just like that and that should actually update it to being closer to the actual input text itself and we should be able to edit it and do all of the things that we might want to now the other thing is the actual button itself maybe you want to move this and so to move it we would do something like rx. hstack and so that the heading and the button are on the same you know horizontal plane so that's what hstack does and then I'll move it over here and then of course if I want to change the alignment I would then go ahead and just do something like align and we would say end let's go ahead and try align end and see what happens with that and there it goes it now goes on the bottom and that's a little bit closer to what I might want in terms of editing now you might want it to all edit right in line and not actually change the page that's something you could do for sure but I'm going to keep it with different URL routes like this and so if I do need to make any changes I totally can and then I would come in here and do something like that now after I edit it I actually do want to redirect to the page itself so let's go back in and see how we're going to go about doing that in the next part now we're going to implement a simple redirect so that it goes back to the blog post whenever we really need it to so inside of our state here I'm going to go to the very bottom and I'm going to define a method and we're going to call it to blog post and it's going to take in self if not self. blog or rather if not self. poost then we'll just return rx. redirect and this will just go into the blog otherwise we'll go ahead and return rx. redirect and then of course it's going to be a string substitution here of blog and s.p. and that's it so with this method in in mind we can now use it wherever we need to so in the case of our state elements here we'll then return our redirect of self. to blog post and then we'll do that as well in the edit method also great so there we go so the other part of this is to make sure that in our save method here we'll just go ahead and do self. poost equals to that post as well just to make sure that that's in there as well so now with that in mind let's go ahead and save it and let's rerun everything so let's go ahead and run our our reflex project here we will Refresh on on our edit page here in just a second and we'll go ahead and hit submit and what it should do is bring me back then if I go into blog I'll go ahead and do a new post and I'll say another great one and put in some message hit submit there it goes and now again I can go ahead and edit it to abc1 two3 and hit save now when it comes to adding a new one maybe that means that I want to actually go immediately to the edit page so let's go ahead and modify this a little bit and go ahead and say edit page being false and then we'll go ahead and just say if edit page then we'll go ahead and copy this and then go in into sledit save that now in the add method here we'll go ahead and just say edit page being true and we'll go ahead and save that now of course the next thing is this slash blog here so we have it in a few different places which of course is not what we want to do so in our edit page we've got it in our or rather our detail page we have it in our link right here so let's go ahead and start off by changing our state a little bit by doing from dot do import navigation and then we're going to go ahead and do our blog route and this is going to be our navigation. routes. blog post route we'll actually keep it in as just simply blog post route to just keep the naming the same then I'm going to go ahead and update my variable inside of my blog post state so we'll do RXV and we're going to go ahead and do blog URL or rather blog post URL which we'll take in self and then it's going to go ahead and return well basically if not selfpost then it's going to return the string of that value which of course doesn't have a trailing slash here of course if there is a blog post URL then we'll go ahead and bring that same thing in here and then we'll go ahead and use the selfpost doid and then we'll go ahead and use this same concept for the edit URL and I'll just go ahead and do edit down here and then we'll just put edit here okay so we also want to make sure that this blog post URL does not have a trailing slash so basically if blog post. ends with the trailing slash we'll just go ahead and make sure that it doesn't have one at least here so wherever we Define it before is totally fine but here when we're actually doing the different redirects we want to make sure that we do this correctly so now down in to our you know two blog post we will then update this as is so I'm going to go ahead and bring in the blog post route as that default then we'll go ahead and do our you know self. you know blog post edit URL and then uh we'll actually make sure that it's inside of a string as well so we'll go ahead and do that and then I'll go ahead and do the same thing down here which will just be our blog post URL there we go and so back into my detail here let's go ahead and try that same thing inside of this edit link actually let's make sure that everything else is working first so inside of edit here I'm going to go ahead and save that it goes back great and then I'll go ahead and do a new post and I'll say another one or whatever gibberish hit submit and there it goes now it's editing that and then of course if I submit it again it'll now bring me to that great so with this in mind I'm going to go ahead and update this href here to one of those URLs we will just go ahead and change it to being state DOT um still going to be our blog post post model and then we'll go ahead and do our um blog wait what did we call it our blog uh URL so blog post URL and this should be actually not blog post URL but blog post edit URL and it's looking like it's not saying that we have that one in here so let's go back up and just verify that we do and there we go so it does all right so let's go ahead and try this out now back into our detail page looks like we're getting the blog post model oh that's why this should be blog post State simple little string substitution there and so now with that in mind let's go ahead and run it again and now we should have a little bit more robust of these editing I think so if we refresh in here click on edit sure enough it works now one of the things that's important to note is I did string substitution here I did test it without doing string substitution and I actually get an error there so once I did that it went to an error so it expects a string so make sure that you are using string substitution if you ever run into something like that where it's like hey this isn't working so whenever you use RX thatv VAR just make sure that it is string substitution that's going through when you want to use that value wherever you need to including down here now the reason the blog post route doesn't need to be string substitution it's because it already is a constant of a string but the point here is to really just do a quick search for SL blog on our entire page and we should only see it well a couple of times and that is related to the different routes so the pages themselves these routes we probably should put into our main configuration routes but the only reason I'm not is because I actually want to keep and be able to see what's going on here feel free to change it as you see fit but now that we've got this we are ready for the next step which is going to be moving towards actually doing some Authentication but before we do that even I want to add in the publish date and time and then adjust things on how it gets rendered based off of those two values we are definitely at that point now we're going to start the process of allowing for our blog post to be published now eventually we'll have a publish date and time but we'll start out with just simply something like publish active with the type of Boolean and we'll set the default to being false now in my case what I did is I actually deleted all my migrations and I also wanted to delete the database the only reason for this is so that I can just start fresh basically from here with this new data table and then we'll go ahead and run our make migrations and then our reflex DB and migrate and of course I don't actually need to run make migrations or migrate after the init because a lot of those models were already brought out but the idea is now that I've got this publish Act here let's go ahead and take a look at the documentation for switch on reflex switch is going to be really nice cuz I can just toggle this setting so I really like switches for Boolean values and that's what I'm going to do I'm going to copy this entire element from the basic example for the switch if you just do a quick search for switch you should be able to find this component itself and then I'm going to go ahead and jump in to my form here and right underneath the content itself I'm going to go ahead and bring in that switch and we'll go ahead and do that bring it in we'll tag tab it over a little bit as well and I'm just going to go ahead and say publish active and the default is not going to necessarily be checked but we'll look at that in just a moment and then I will give it a name though and the name of course is going to be publish active great so what should the actual default be for this switch value um and let's go ahead and go back into our content we've got our Title Here as one of the values I can now do publish active as one of the values as well so publish active in here from the post directory um okay great so that's going to be our default value now and it's really just that simple I shouldn't have to change much in the way of the state itself because that is now a value for any given post so at this time I need to actually create a new post so I'll go ahead and do hello world as soon as I hit submit here uh with some new content I'm going to go ahead and see there's my publish active switch so I'll go ahead and save that and we get an error so the error is related to the actual data that comes through on a switch so the default is simply on so of course inside of our state then we might need to update it in here based off of what's going on here so we'll go ahead and give it the publish active and it's going to be our form data and I'm going to go ahead and do pop of publish active now what I want to do is I'm going to go ahead and set a default to being false then I'll go ahead and check if publish active is in that form data and then I'm going to go ahead and grab that pop value and I'm going to set it equal to odd and so now we've got a new value for our published data of publish active great so what we want to do is just check this form data so we'll go ahead and print it out save it and we'll come back in here let's do a refresh obviously the default is off let's turn it on I saved that now I didn't get any any errors or anything like that but publish active is now on and if I were to go to edit it it now says P active if I turn it off we can go ahead and see that it's off it's not even in there uh which means that we can go with this default value of just simply being off great so that's a really good sign now that we we have this publish active toggle I want to actually update my form just a little bit so with this switch in mind what I will do is go to the next part which would be related to this so I'm going to go ahead and do rx. condition and basically we're going to see if it's active itself so I'm going to go ahead and do publish active and we'll go ahead and come down in here if it is active then I'm going to do rx. boox and for now I'll just go and say rx. text and we'll do publish input or something along those lines so let's goe and save that and now we'll come back into our edit form and then I'll toggle this and this toggling doesn't actually show the publish active coming through so of course that's a little bit of an issue in terms of what I want to implement here so that brings me back to the state itself so let's go back into the state element the default State element and this case I'll go ahead and do Post publish active and the default here is going to be a Boolean and we'll go ahead and set it equal to false then of course when we actually go and get that post detail just like we did with content I'm going to go ahead and do self. publish active being related to self. poost and then of course it's not publish active it's just or not that whole string it's just that so with this in mind now I can actually go back into my Form This Is Now the default checked again when we actually come through that's what's going to happen so it's from the state element itself once again that's inheriting from the parent element then we can go ahead and do on change and this is going to be equal to uh the change value the default change value which is of course the element itself and then I can do set underscore what that element ends up being just like that so now if I go ahead and come back in here and this publish active I should actually be able to see um oh wait let's actually add in the state element here there we go and now I should be able to see the toggle coming through let's go ahead and take a look there we go so now that I've got that toggle this is where I can actually start putting in an additional section for actually publish date and time so that's what I'm going to do inside of this box here I'll go ahead and do rx. hstack we want it to be horizontal and then I'll go ahead and do rx. input and for now I'll go ahead and just put in a few defaults we will have to change this in a little bit but it's going to be two different inputs in here and it's actually really cool so what we can do is just bring in a date and then we can also bring in a time so both of these things are actually what I will end up wanting to have so I'll go ahead and do the name of publish date and then we'll go ahead and grab that same sort of idea with the name of publish time okay so that's will will give me the actual stack that I'm looking for in the terms of the hstack here I'm going to go ahead and give a couple widths of 100% just to make sure that that's all done on each input and each element in here and we'll tab them in as is just to make sure that it's formatted fairly nicely okay so back on my edit if I go into publish I now see that I've got these date time objects in here that I can then use so naturally back into my state element when I get the form data itself which will come in here we want to pop those data items first so once again I'll go ahead and grab the pop element here and this is going to be our publish date which will take in that same thing and then we'll go ahead and grab the publish time and then I'll go ahead and print out the publish date and the publish time so we go ahead and save that and actually once again just like in this this call right here I want to go ahead and make sure that I actually have those things in here so I'll go ahead and give it being none as default and then we'll go ahead and come through here repeating this again for publish time all across the board and there we go now I'll go ahead and print what those things are back into our form here I'll go ahead and let's make sure that everything's compiling sure enough it is I might have to refresh the cache a little bit here so I'll go ahead and rerun it and we'll go ahead and take a look at it in just a second and there it goes and so now we've see publish in here so if I if I change this to some date in here uh that's probably not a great date let's go ahead and get this to 2004 or something and we'll go ahead and do 101 a.m submit and what we'll see in our print statement is that value so we're definitely in a really good spot to start actually having datetime objects in here handling this is a little bit complicated so I want to make sure that we do it uh together and in its own section but the idea this is we can now publish these date and time objects like this doing this what I got to just to this point is so much easier and reflex than so many other things because you also have this drop down menu that kind of goes off the screen here but um I have the ability to just really easily add in the date and time itself uh super cool and so let's go ahead and actually implement this now now when it comes to the publish date I actually don't want it as two Fields I just want it as one one field very similar to updated at and created at but it's going to be slightly different in the fact that it won't Auto set and I'm going to go ahead and paste this in here and we're going to go ahead and do publish and I'll call this publish date even though it will also include a datetime object the default is going to just be simply none the datetime object is going to be the type we're going to have no keyword arguments in here and then we'll go ahead and allow it to be nullable I'll get rid of these objects in here or these comments rather and then we'll go ahead and run our reflex and DB make migrations and then our reflex DB and migrate okay so how do we go about doing this well the first thing is going back into our state element here so we can absolutely put this state element what we're about to do in a lot of different places I'm going to put it just in the blog edit form State and the things I'm putting are going to be related to the publish data itself so what we want to be able to do is we want to be able to change that publish data uh but it's going to be based off of whatever the default data is that's going to come through so inside of this state here I'm going to go ahead and import from date time we're going to import the date time object and we're going to go ahead and create a couple things related to our datetime object so we're going to start with the Baseline one first so I'll go ahead and do RX dovar and we're going to Define this as publish display date and it's going to take in self and it's going to return something simple I'm going to do 20 24 or 23 and then the month will be 12 and then I'll go ahead and do the date of one so this is going to be the format of year year year month month and day day that's the format that we want to use it on I think this will work internationally as well if it doesn't please please let me know but the idea being that we want to use this format right here so that back into my form what I can do is I can do my default value being equal to that so based off of the edit State itself and this is going to be our you know the state in here so the publish display State just like that okay so we're going to go ahead and save that let's go ahead and make sure that I can run this back and so what I might get is something related to the string itself so let's go back into our state here I want to just go ahead and make sure that this returns back as a string so that when I do aim to render it the actual typing check will go through just correctly okay so now inside of our date object here let's go into some blog post that we're going to edit we can now see that it is pre-filled with that data now I'm of course not going to do a hard string like this at all I don't necessarily want that um but at some point I will change it but before I change it I'm going to come down in here and now we're going to go ahead and do display and simply time so the time is going to be in hours minutes and seconds so for this one I'm just going to go ahead and grab from the datetime object itself so this right here I'll just go ahead and grab what the time is now instead of doing this RW string you definitely can still do a Rost string but I'm just going to go ahead and do now and we're going to do Str Str Str strf time and it's going to be percent H colon percent M colon percent s so that is the format that we're doing so we're doing the string format time and it's going to be this so with this am mind I'm going to come back into my form here and I'm going to go ahead and copy the first one here and we'll bring it in as the publish display typ so we're going to go and save that and now if I go back into my edit what I should be able to do is when I toggle this I should be able to see the time that it is and that is the current time for me so I can do that same thing of course with the date so basically taking the same idea here and instead of it being that we will come in and do this kind of format now that format itself is going to be percent y- percent lowercase m- percent lowercase D so capital Y just like that now of course if I were to take a look at my form itself we'll refresh in here and we can see that it is today's date and today's time and yours will probably look the exact same okay so that's based off of date time though um so what I don't want it to be is I don't want it to be based off of date time I want it to be based off of something different I want it to be based off of what's stored in the database before I get there I'm going to go ahead and actually set the publish date and time based off of what's coming through right here so that means that my Pub string or let's go ahead and call this my publish input string is going to be equal to the publish date that comes through with a little space here and the publish time that comes through and so what I want to do is my publish date is going to be none I'll set it equal to be none this is going to be my actual final publish date is what I'll call this one because the input has publish date on there so final publish date is going to need to be a datetime object based off of our model which is a datetime object so that's how what we need to store it as so that means I'm going to go ahead and do a try block here and we're going to go ahead and do try the publish date being equal to date time. STP time so this will format a string that comes through based off of well essentially the same thing which is going to be this right right here right space and then this right here why is there a space in there well the format that we are doing we are using that original publish date to that publish string and that's what's going to be the format or at least that would be what the final format is otherwise if there is an exception that is of course going to then mean our final publish date is just simply none and so now in our updated data I can go ahead and say publish date being equal to that final publish date okay great so this will allow us to set it based off of right now and pretty much or at least start with right now so I'll go ahead and refresh in here we've got our publish active um and then I'm going to go ahead and set this toggle is not doing the correct one we'll fix that in a second uh but the idea here is I want to set this equal to that we'll go ahead and save it and then on my detail view I just want to see what that publish time is so we'll go back into that detail and right underneath the uh title here we'll just do the text for that and we'll go ahead and do our post. publish date okay so granted we can always format that publish date but for now I really just want to see that it's coming through sure enough it is great so what if I actually changed it to something different we come in here to let's do uh 20 20 one or something like that save that and sure enough it is saving it it's saving it correctly okay great so we're we're getting close so next up what we want to do is we want to actually just see how we can use our own data so let's go back into our state here and we've got this published display state but of course this means that well maybe we just don't have a post at all so first off I'll go ahead and say if not self. poost then I'll go ahead and return that then we'll go ahead and say if not self. poost dopu date then I'll go ahead and return that but then if I do have a publish date then it will be self. poost dopu dat and it's going to be the exact same shift time shift F string time so basically the string F time of this and so that same concept is true for our our actual publish time so go and come back down here and we'll just update these two right here and get rid of this and just change the time right there there we go so now we've got our default publish time in here if I go to edit it now shows me what it is that I'm trying to edit fantastic now if I were to take off the publish active notice that when I refresh in here the publish active goes away so that's definitely something that we might need to update but for now I'm going to leave it as this and we've got you know March or whatever then I go to edit it again and there it is and if I were to create a new post I can say hi there some new gibberish post hit submit publish active is on which is probably not what it should be so we'll change that we'll change the date to sometime in the future and there we go so actually we need to make sure that our blog posts on the public page actually show up to be being uh the actual published ones ones that are actually ready to be seen so there's a lot of different things in terms of permissions that we can do there that we're just not going to cover in this one uh we will have some things related to users and lookups and stuff like that but the main reason that I have um these publish date is because I think something like a blog post or something that you want in the future is actually really important and a lot of web applications have it so seeing how to be able to actually set it in the forums and also in the state and all that is I think fairly important now we're going to take a look at how we can filter out a query like this to be based off of well whether or not a field is active or all of them are active or an actual date so we'll start with active because it's pretty easy so if we come in here we are just going to go ahead and do wear and inside of this wear CLA we'll use post model do uh publish active equaling to true and that's it so that will now load all of those posts based off of that value so let's go ahead and grab a post and make it inactive so I'm going to go ahead and save this one of course the detail is still there so I can take a look at that but if I go into the blog list it is now gone no surprise there if I were to go back into that active one edit it make it active again save it go into the blog what do you know it's back great very very simple you just add the wear the actual model itself the field and then what you want that field to be so we can actually chain together queries as well so if we put parentheses around this condition we can do an and statement and then we can actually use another condition inside of here so that condition in this case will be our publish date so I'll go ahead and do publish date now what can we do in terms of publish date well I can actually use the date time object object so I can actually come down in here and say something like date time. now we can say it's equal to or we could say that it is less than so it's in the past so it happened before right now that's kind of what that query is doing and so once again if we go into our blog post it looks like one of them went away but if I were to edit one of them and change it to being in sometime into the future we can actually go ahead and select let's say for instance uh we're going to change it to 2025 just like that hit submit now the detail view shows up if I go into the list view it no longer shows up great so it actually gives me the ability to make changes and query Things based off of where they actually exist in terms of publishing and it's really just that simple so this same wear we can actually add into our detail views as well so if we went into the git post detail here this wear we could also put in in here as as well so you can change these things together at any time so let's go ahead and just bring it in we'll try and chain it together I'm just copying and pasting it for just a moment and we'll chain it together like that where publish active just like that so we go a and save that and then if I go into a page that's not active so this first one I'll just go ahead and change it uh right now we'll change it to being inactive and sure enough if I go on this page I get nothing if I go back into edit and looks like it won't even let me edit it because of that publish query that I have in there so I'll go ahead and get rid of that that statement on there so I can actually edit it as well and once again we've got the data that I can come through and update and change so it's actually really nice that I'm able to query these things and I can do it as I see fit and then of course we can change our load posts here to something like let's say published only as an argument here then if it is published only we would say something like our lookup ARS are well these values right here inside of this parenthesis and we'll go ahead and do something like that so we can separate it out a little bit easier otherwise we'll go ahead and put our lookup ARS as just empty empty parentheses and then we'll unpack them inside of here for that wear Clause so we can have these chained together naturally these same lookup arcs we could reuse use in other places so maybe we create it as a little function that we could then reuse in those other places but the idea being if we change this to being false and we come in here we could then see um let's go ahead and make sure that our reflex is running we now see everything in there and so if we actually came back into our let's go into something like this we're going to grab it and grab the list in here we could then change some sort of feature in here to have a you know a published only so we would say something like uh let's say for instance published in here where it's all of the published articles in there and then you would want to toggle this somehow uh to being different than load posts which might just be another onload function that you create that will then use those specific look arcs that we just said um and that's something you could definitely consider doing the idea here is really to see that we can not only query things into our database tables but we can also query them based off of that datetime object that we created and implemented it's pretty cool but now that we've got this we need to start the process of using actual users so that it actually makes a lot more sense than where current stands because right now anybody can edit any of this stuff so let's go ah a and take a look at how to do it with users now we're going to go ahead and Implement users into our project by using the reflex local off package now to make this happen we're going to go ahead and do the installation so I do recommend going to the GitHub repo for it but the idea being bringing reflex local off into our requirements.txt and then running pip install d r requirements.txt to make sure that your requirements are all set up one thing I want to point out is I do not have any migrations or a database at this time I completely removed those things just so we can get this part up and running and so I'm going to go ahead and run the reflex DB in it and then we'll go ahead and run our reflex DB make migrations and then our reflex DB and migrate great and so what we'll see in the actual docs for the reflex local off is we will see something that looks maybe a little familiar and that is these pages right here so what we can do is we can actually use their default Pages for logging in and registering so let's go ahead and grab grab these and I'm going to go ahead and bring them into the root of my project right above my about page I'll bring them in here and of course these are now the reflex Lal uh pages okay and these are my pages great so we want to import this package in as well so right under reflex I'll go ahead and import this one in and now if we scroll down we can see the various routes are in there now of course we need to know where this login route is so I'll just go to the definition and we see login and register yes you can change these route if you want to and you can change them into the package itself and it actually handles everything else so reading through their code might be something you might want to do for your routes or the routes that we created in our project earlier but at this time I'm going to go ahead and use these routes in my project itself so even if we didn't look at the routes or we didn't see where they were I'm going to go ahead and come into my UI into my nav bar I'm going to go ahead and import the package again so once again it's the local off package so we'll import it this of course is now our login route and let's go ahead and make sure we import it like that into our actual login page we've got our button here for login and sign up so I'll go ahead and do rx. link around this button and of course it's going to be hre of that login itself so I'll go ahead and put it right around that button like that and there we go I'll tab in that button now and tab in the href there we go so this is obviously not the signup route but the uh that's the login route so we're going to go ahead and copy that one as well I'll just copy the entire thing and paste in here and this will be log in and this one will stay as sign up and we'll just change it to the register route or we could just call it register to kind of fit along with what's going on here and so with this in mind if I were to run my project now so let's go ahead and do that with reflex run we can now navigate to that area so the login page that comes in from reflex local off by default so it looks like we might need to run our migrations again because of reflex so let's go ahead and do that uh The Reflex L off we need to make those migrations and run them as well uh the reason they weren't there at the in the first place is because they didn't import the package yet but now that the package is imported we should be able to run it and have access to register and log in so before I actually do that process I will click on register and take a look this looks fine to me if I look and login this also looks fine to me but the problem is it's not actually using my base Navar so I probably want to change it a little bit which we will but before I do there is one other element that I want to make sure that I'm doing and that is our menu item in here we've got login and sign up so once again we need to update our nav state so let's go into navigation and we are going to go ahead and import our reflex local off in there we'll go ahead and do that and we'll call this you know something like to register and then something like maybe to log in and now we'll go ahead and do our you know reflex local off. routes. register route and then login route okay and here we go now we can go back into our nav and go into where those items were so they are in the menu items like this and I'll just go ahead and add in some click events to both of these and we'll go ahead and do login and sign up sign up I'll change to register just to fit along with everything else that we were doing and then this is going to be to register and then to log in great so now we've got a lot of the paths to be able to log in and register now all we need to do is modify the login and registrator page so that our Navar actually does show up there let's take a look now we're going to go ahead and update our login and register route so that they actually have our Navar on them you may or may not want this I definitely want this so the way I'm going to do it is by actually just grabbing this login page and taking a look at the definition so the definition itself is just rx. Center so there's a really good chance that I could probably just put a wrapper around this because it is a component so that's what we'll go ahead and try out inside of our project here we're going to go ahead and create off and then we'll do our init file and then I'll go ahead and create pages. so all I want to do is import the login page we'll start off with that one I'll grab this and and in our Pages here we're going to import reflex as RX and then I'll go ahead and bring in from Local off. Pages we'll go ahead and import our login page and now I'm going to Define my login page and it's going to be returning back an rx. component and then we want to return be the login page the original login page but of course the original login page wrapped with our own UI so from do ui. BAS we're going to go ahead and import our base page and so let's go ahead and bring our base page and put it around the login page just like that so now what we should be able to see is this base page being rendered let's go ahead and go into fullstack python here actually go into our init first and do from um we'll go ahead and just import from dot we'll import our pages and then we'll go ahead and do our all method in here and put in pages okay there we go then in fullstack Python we'll go ahead and bring in off here and we'll go ahead and do our first one which of course is that login page we'll keep everything else basically the same so let's go into that route and we've got it right here so off and we've got pages and now it's just going to be my login page we'll save that and let's make sure our project's still running and then we'll go navigate into our login page and sure enough there it is so this built with reflex we did have some things that we did by default on each one of our Pages here we put the you know entire page a little bit bigger so I'm going to go ahead and change it just slightly on my login page to better match maybe like my about page which has to do with you know our vstack in here we've got a bunch of things that are going on the main thing I want to bring in is just this minimum height so back into our login page here I'll just go ahead and add in that minimum height on that base page and let's see if that actually does anything now it might even cause an error so in this case it actually didn't do anything it didn't change this minimum height so that's a little bit of a problem so I'm going to go ahead and change it a little bit more then so that means I'm actually going to go ahead and grab all of this right here we're going to go ahead and copy that this is what I'm going to now bring into my base page here and we'll bring it in like that we'll tab it in now instead of the login page we'll just go ahead and grab the login State we'll go ahead and grab the login form and then we'll go ahead and grab in padding top whatever that element might end up being so now that we've got these Pages we want to go ahead and probably grab it from login so if you actually went through everything you would see that it's in login. py that's where I just copied that login page information and that's how I was able to bring this in so in rx. cter this is probably where I want to put in that minimum height let's go ahead and give it a shot I'll put in the minimum height in there make sure I put a comma at the end of it and then we'll take a look at our login page now we've got a minimum height going and it's looking maybe a little bit better I don't know if I need that padding top anymore so let's get go ahead and get rid of it and take a look and with that padding top gone this looks pretty good I'm okay with this great so we want to repeat this process again with my register page right so we're going to go ahead and call it basically the same thing as what we've got here which is now going into the register page which is in registration. we'll go ahead and copy all of that and once again we will not have the padding top but I'm going to go ahead and call this my uh registration or register page and bring in the center here get rid of that padding top bring in our minimum height here and put it right underneath the condition which I think that is there we go so we'll go ahead and put it right there and of course we need to bring in those items there I'll get rid of padding top now I'm going to go ahead and copy the Imports to a degree put registration below here and then we'll go ahead and grab in the state elements registration State and I'm guessing registration form and that looks like that's all we need great so now that we've got that back into our project here we're going to go ahead and just change it from the local off to my off basically which is already imported and we've got everything going and of course it's now called my register page great so that's how I'm going to go ahead and modify it and we go into the registration and now we've got our login and register fantastic so it's just going to be a username registration but the idea is if we go back into the documentation for this what we can see is other kind kinds of things that you might want to put in like an email form or something like that if you want to actually register with email then this would be a way that you could go about doing it and just go through their documentation on how that's done but before we can even do that we would need to actually have a email model in here we need to change this to allow for us to even have the email the user's email so let's go ahead and see how we can do foreign Keys now and how we might further customize these registration pages right now when it comes to registering users we might want to actually have additional information about that user so we could do it on this form right here we could do it later I'm going to go ahead and modify the registration form to have an email field and then we will have to store that somewhere so where we're going to store it is what we're going to do right now we're going to open up off here and we're going to go ahead and do model.py and I'm going to go ahead and bring in you know import reflex as RX and then we're going to go ahead and create the class of user info which takes in rx. model once again it's going to be table being true and then we want to declare a few things the first one is just going to be email St and that's it so we want this to be corresponding to our user model and eventually we'll have our blogs doing the same now the other thing about this user info is I actually might want to implement stuff related to the blog itself that is in the blog we have the blog post model we've got created at and updated at both of those things I'm actually going to go ahead and Implement in this model as well which means I need to bring in a bunch of defaults related to that so go ahead and copy and paste a bunch of stuff right now and so now I've got some user info about this and of course I want to bring in the utilities as well let's go and do that also and so there we go we have some default values that we're going to go ahead and Implement here but it before I do that I actually want to bring in the concept of a foreign key so what we want to do is we want to actually save the user ID which is an integer and it's going to be equal to a field and it's going to have a foreign key relationship to the local user. so what is the local user well if we go into our migrations we want to take a look at the different models that were created we've got our models right here if we go into the next migrations we will see the local off session and we will also see the local user and ID so what we're doing here is we are actually going to associate this user info to that table of local user and the ID right there which is the primary key that actually ends up being as we see the primary key constraint that is how we do our foreign Keys we actually make it so that this model this table is now related to that table with those IDs right there and so that's where we're going to leave this part and the next part we'll actually integrate these two things in here so let's go ahead and see if we can run our migrations so we'll do our reflex run or rather reflex DB make migrations all we want to see is make sure that this is actually going to create a new migrations table for us it did not so let's go into our init here and I'll go ahead and do from Models we're going to import our model which we called user info and then I'll go ahead and make sure that that is inside of this import statement now I'll go ahead and run make migrations here that creates that migration file for me so we'll go ahead and do run reflex DB migrate and of course if we look into that new migration table uh we should see that we've got our user info ID email and so on and then we we've got some foreign key constraints in here based off of the local user. ID and we've got a primary key in here as well so this is just about associating those data points we'll see this a lot more but for now now that they are associated we want to update our registration page so that it actually will store that data we need to put a new form in here and we need to actually create uh a way to store that data as well let's take a look at this point we are right here here we actually just created this customization for this user model granted I didn't keep all the fields and I added some of my own but the idea is we now have our own custom model that we can use going forward so if we scroll down a little bit we are now going to change our custom registration so the first thing is going to be this state variable here I'll go ahead and grab that and inside of O we'll go ahead and do state. piy and I'm going to go ahead and paste this in so I want to implement this as best as I can so the first thing is I don't need any of these components in here I do need the reflex local off because we have this registration state in here and so what we've got is this user info that user info is going to be our model class this is our user info so we're going to go ahead and use that one so we'll do from and. Models we're going to import the user info model next up we are going to go ahead and bring in the things that we need one of the things that we don't need is this created from IP address you totally could get that one I just left it out all I'm going to grab is the email and the user ID from the actual request itself as we will see here shortly um from the actual form data so now that we've got that state we'll scroll down a little bit we've got this user error in here which is actually pretty nice that there is this so I'm going to go ahead and copy that and I'll go ahead and create the forms.py now we're going to go ahead and paste this in naturally we need to bring in a few Imports here so from uh we'll import reflex as RX and and then we'll go ahead and import our reflex local off so there's our user you know registration error nothing we need to change but I do want to have it in case I want to change it later I'm going to now go ahead and copy the register form itself and then we'll come in here and paste it in so we've got this input 100w if we actually scroll up a bit we can see that I can actually grab that input 100w which is really just a customized input if we take a look at it we can see that it's RX input with all of the same normal values it just has a width of 100 so feel free to add this yourself or in this case they like making all these reusable components which is what I'm doing right here as well I'll stick with what they did uh just so you can learn from it as well the main thing here is this input of email we want to make sure that we put a type of email in here as well just to make sure that that's in there also great so now that we've got that let's go ahead and grab the minimum width um in this case I'll go ahead and import that one as well from their components I think that's where it's from and then we've got my register state in here but everything else about this form is just about what we need so I'm going to change this to being called my register form then I'm going to go ahead and import my state value so from State we'll go ahead and import the state value that we just created which was my register State and so this is the one we will now use and that's what's going to handle the submit and all of the registration for us as we'll see in just a moment ideally okay so the next part is we've got this register form into our Pages here I've got our page and hey what do you know we've got the register form right here so I'm going to go ahead and bring that one in so from forms we will go ahead and bring it in like that and I will go ahead and put this right below this one and we'll go ahead and now use my register form save it and let's go ahead and make sure our project is still running and we'll go into our registration form and then it is so the question of course is can I actually register so I'm going to go ahead and give myself a user I'll go ahead and do my email here this a real email and then I'll go ahead and do a whatever password at this point and I'll go ahead and sign up registration successful you could save it if you want in my case I will just so I can see if I can even log in and sure enough it logs me in or at least it seems like it logs me in obviously there's still things that I need to do but I didn't get a bunch of Errors so at this point of course we now need to implement things related to that login process but the point is when I go to login with maybe a different name I should see an error here or if I use the same name and I give some gibberish for the password I should see an error here so that's a really good sign next up if we want to actually try and log in with the same user I'll go ahead and do that with that same user name in here and with whatever password I'm going to go ahead and try and sign up and it says that this person's already user uh registered as a username uh which is really nice so great so now we have user logged in and we can just go ahead and refresh on our login here log in again and there we go so now all we need to do is start implementing things related to this user based off of this authentication it is actually really that simple it feels too simple it really is granted we talked about a lot of things to get here which is why I kind of sped through the registration form and didn't go through all of the things that you would need to do in here but overall this should look very familiar to you at this point now that we've got that let's actually start using the user session itself now we're going to go ahead and create our session State variable that we can reuse on any page that we need to to see whether or not the user is authenticated so it actually is building based off of reflexes local off the off state that it has so it's going to be just like this but it's going to allow us to just modify it a little bit more than what we've got here so the way we're going to do this is inside of off inside of the state valuable we're going to go ahead and bring this one in and so of course there's going to be a few things that we probably don't need to reimport uh but like local reflex local off we don't need to repport or reflex but the SQL model we will go ahead and bring that in because it's going to be related to grabing data from our user info model right and so what we have here is I'm going to call this my session State because I'm going to use it for other things related to my session what we see here is we've got the local off state which is actually going to be set based off of a number of things so just like we've SE before where it comes to inheriting from another state that's exactly what we're doing we're inheriting from the state which gives us the off token which is being stored in the local storage which this is being created when we actually create a brand new session and so we've got a bunch of things related to the session itself including logging out in here and that's something else we will definitely need to implement at some point but for right now what I want to do is I just want to grab this authenticated user info so I'm going to go ahead and create another method in here and we're going to call this on load and no surprise we are going to use this when we need to so basically we'll say if not self dot is authenticated when it comes to self it's going to be based off of this session the actual State itself we're going to go ahead and return reflex local off. login State and then do reder as in redirect and so if we take a look at that we can see that this will actually want us to be redirected to the login page as it needs to so it's just a quick way to make sure that that is happening when we go to a page that needs this information and needs a user logged in it will require them to log in otherwise what I'm going to do is just print out my self. authenticated user info now again this authentic indicated user info is coming from our model where it's coming from the actual user ID which is the actual field that we have as our foreign key that's going based off of our local user ID which is what this is doing right here so really we just want to test out this methodology we want to test that this session actually works when our user is logged in so how do we go about doing this of course well we can go ahead and create a page specifically for it so I'm going to go into this about and I'm just going to go ahead and call it protected in here and in this protected page I'll just go ahead and say protected you know page something along those lines just like that and we'll rename it as protected page and we'll go ahead and import this so from. protected we're going to import our protected page now and we'll go ahead and Export that as well and so we've got our full page here now on my ad Pages what we want to do is we've got our about page so right below that we're going to go ahead and do our protected and page and in this case I'll just go ahead and make a oneoff route because I won't really use this this is just really to test these things out so we'll go ahead and do protected page in here and so naturally what we want to do with this protected page is we want to bring in that onload method that we just created so onload is going to be related to our session so that session we want to also bring in as well so we'll go ahead and put it into off we're going to go ahead and do from. state we're going to go and import that session State and we'll go ahead and use that as an export as well and so we'll go ahead and grab this inside of protected we should already have the full page in here we already have off going through because we did that already we used it a little bit already so we'll go ahead and do onload off. session state. onload what do you know there is our onload method and so now when we go to that protected page we should be able to actually see the print statement I don't actually have to do anything on this protected page not yet at least we we just want to go ahead and make sure that we can see that print statement so I'll go back into my local project here that's still running we'll go into protected and we want to just see we get a 404 not uh not found error let's go ahead and just verify that we just called it protected no we called it protected page so let's go ahead and just call it protected and and there we go so with that in mind now we see that it says protected page and if we go into our print statement we've got none so it's certainly possible that our login failed so let's go ahead and log back in and then go into our protected page now and we'll go ahead and take a look and still none what's going on well if we go back into reflex local off we've got this reflex local oth login required decorator so let's go ahead and bring that into our protected page here now we'll go ahead and bring it in just like that and we'll go ahead and import it now we've got the required login let's go back into our protected page here and if we refresh in here now we're still getting none interesting so let's go ahead and see what it is that is going on with our call here so we've got self. user is authenticated let's go ahead and print this out and we'll go ahead and print it out just like that and we just want to see if the user is authenticated if it's going to say true there it does so what is happening is it's not actually finding any of the user info itself so what we need to do is we need to diagnose the issue here which might be related to our registration process so we've got our form inside of our form there's our register form it goes into our registration handle user email state so we're going to go ahead and come back in here and there is our user info and does commit it so it's certainly possible that maybe we have an issue with our new user ID so let's go ahead and print out that one now so we'll go ahead and do self. new user ID let's go ahead and create a brand new user this time I'll just do some random user here we'll go ahead and say no I'll go ahead and change these and ABC gmail.com not a real one and then a whatever password I'm going to go ahead and hit sign up and we got registration successful it says say -1 I have a feeling that this little bug is something that you won't see in the future but what I want to do is just modify this handle registration email so that it actually does work and it does create this email form what I did was delete the database alog together so that I could do this the way I'm going to do it is by grabbing the original handle registration and we'll open this up in the code itself so the original one is going to be right here we're going to go ahead and copy this entire function and we're just going to change the order of operations just a little bit I'll paste this in here and I'll go ahead and use instead of super we'll go ahead and just do self. handle registration which of course is this default here notice that the actual default value that's coming back from that is what we return at the end of this handle registration so I'm going to go ahead and actually just cut that out and paste it right here and that's pretty much what I want to handle next I'm going to go ahead and actually bring back the self-de new user ID which is going to be what this is right here and that's actually what we'll now use which should actually give us the new users ID that's coming through and it's still returning back that original result this of course is customizing the default values and I think it's a bug that will go away very very soon but it's actually a fairly straightforward process if you actually look at the register user method itself What's Happening Here is it does create everything like we've seen before in terms of a session and then it sets the state variable of that new user ID so all I did was is say okay that's going to set that if it's successful then we're going to go ahead and return whatever that is before I flush it out because this right here actually does flush out what that new user ID is for the next level and so that's what we just did here it's just a very simple change to make sure that I can actually create this user info because before it was just simply not being created so since I deleted the database I'm going to go ahead and register this user once again and I'll go ahead and do the same email in here and then I'll go ahead and do the same password I delete the checked password as well I'll go ahead and sign up now registration successful let's go ahead and sign in with that user let's go ahead and navigate over to that protected page and what we should see in our terminal is this print statement right here which now has the email in there the ID and everything going forward the next thing on this protected page I'm just going to go ahead and get this required login off of here and let's actually see what happens with this page itself if I refresh in here that data is still in there it's still showing up which is a really good sign but the thing is I just wanted to test a number of different things related to the bugs that were coming through and side of this protected page itself now that we've got this we have the proper user session and we have the extended data in there we should be able to go forward and start associating other pieces of data in our project let's take a look now we're going to go ahead and Implement a sidebar for logged in users so that the logged in user it feels a little bit more like a dashboard than the landing page element that we have so far now the way we're going to do this is by going into recipes on reflex and taking a look at the various sidebar elements you could use the basic one if you want I like having this bottom user profile where it already has a log out button for me and things about my user account and then all of that great so I'm going to go ahead and copy this and we will just copy all of that code here and I'm going to jump into my UI section and we'll go ahead and create sidebar. py and we're going to go ahead and paste this in here now notice that the function itself the component is called sidebar bottom profile and this has all elements related to the sidebar I'm going to rename this to Simply sidebar itself this is actually what the basic element is named as well so if you go into sidebar again and you take a look at the basic one you can see that it is called just simply sidebar so I'm going to call this one sidebar as well and then we'll go ahead and import reflex in here so we import reflex as RX now a couple of different ways on how we can think about doing this sidebar item in base. pi we could have a condition in here that's basically saying do we want the Navar or the sidebar so let's see what that condition does so if I did from you know sidebar importing the sidebar here and we'll just go ahead and change the nav bar to sidebar just right here on that base page if we were to refresh what we will see is of course this changing just slightly and there is the sidebar now of course it doesn't actually look correct so the actual main child element here for any given page is now pushed down quite a bit now there's a lot of different reasons for this but the point here is to make sure that I'm actually going to have another kind of Base page for when they're logged in so that we can really account for all of the changes the base page might need so I'll go ahead and get rid of this import here in just a moment but first I'm going to go ahead and duplicate b.y to just simply dashboard dopy so back into b.y I'll go ahead and comment out the import of the sidebar but in dashboard I'll go ahead and leave it and I'll get rid of the nav bar itself so we'll go ahead and change this to sidebar bar and we'll get rid of a few other things in here and I'll get rid of the Hide nav bar we don't need that on the dashboard especially but we probably don't need it at all in general and then I'll go ahead and just change this to the base dashboard page and there we go so the next part about this is now I can go into b.y and we'll just go ahead and do from you know dashboard we're going to import the sidebar here now before I go into in depth of how to actually have the logged in user we're going to go ahead and just render out this B base dashboard first so I'll go ahead and say is logged in and we'll just go ahead and say true and now I'm going to import or have the condition for the dashboard or the main base page the original main base page and so what that means is we'll go ahead and do our base page equaling to that then I'll come down here and return rx. condition and the condition we'll start out with is just simply is logged in and then if that's the condition we will turn return the base dashboard page if it's not the condition we will return just simply the base page great and so what I also want to do in here is I'm going to go ahead and get rid of this hide Navar element I don't want that any longer this is not how I would want to do this condition anyway I would want to do the condition based off of rx. condition okay so with this in mind we see that our base page in here is you know kind of in line with the fragment so what I want to do is not actually call it base page because it actually confuses with the function itself so I'm going to Define this as base you know layout component or something like that and then we'll go ahead and return back that fragment itself so go ahead and cut this out and we're going to go ahead and return back that and we'll also put in you know RX do uh component as the returning element which will take in child ARs and keyword ARS great so now we've got our basee layout component and that is now what we will go ahead and pass in here just like that now no surprise we need to make sure that we're passing in the child element on each one of these things so child and child along with any args and keyword ARS if for some reason we need to modify those in the future great so now we've got a base page that's going to really confine to whether or not a user is logged in so what this is going to all us to do is now to start to just focus on the dashboard to make it work as we want to so the first thing is of course is to move the content or the child element to be off to the side here so jumping into the dashboard what we have right now is we've got a child element that is alongside of the sidebar but we actually want it to be in line with it so the way we do this is by using rx. hstack we want a horizontal stack here for these two items and once we do that we will see the child element come over here and also we see now that it's working a little bit better but we've also got this built with reflex here so what you might be considering doing is like oh well I want to bring that logo in so I'm going to go ahead and grab the logo let's go ahead and tab this over here this logo of course is kind of a standin for what the footer could be but if we do rx. logo here I can see that if as soon as I bring that in and if it is inside of this H stack it gets moved over here so we don't want it inside of that HTE instead we want it inside of this box right here with our child element itself which I'm going to go ahead and put right under here and we'll go and save that and now we can see that it is going or it should render up right below the child element itself but for some reason it is not wanting to show up in here just yet so let's go ahead and make sure that everything's running and there it is okay great so the next thing is we've got this button here we might need to change that's located but before I do I want to make sure my sidebar actually goes to the bottom of the page now the way we do this is by jumping into sidebar. it's not going to be in the sideart item as we see it's rx. link here it's not going to be in side items at all because as we see they're all those links so it's going to be in the sidebar itself now my intuition is going to be inside of rx. boox but what we notice is there's rx. desktop only and then rx. mobile and tablet so I want to actually see what it looks like with just the tablet so if I break it down I can see that this already has a full page that actually looks really good so I probably don't need to change that eventually I'll need to change the links of course but I just need to change the dashbo only one so I'm going to go ahead and open that inside of here we've got our v stack in here and so really what I'm looking for is simply the height of this thing and so if I scroll down a bit I see that there is a height in here and I also see that there is one that's commented out for a 100% so go ahead and take a look at that as soon as I change it to 100% what ends up happening is well it actually gets smaller so of course I don't actually want to use 100% I want to use 100% of the viewport height or VH as soon as we do that what we should see is it taking up the entire page but of course now I've got this icon in here that's still showing up right that's not great we want to get rid of that too so back into my dashboard here this RX button color mode here we're going to have to adjust I'm going to go ahead and comment it out for now save it as is and now we're getting a lot closer to what our actual final sidebar is going to look like so dashboard of course is going to go where it should which is basically to the homepage let's go ahead and fix some of these links now so I'll go ahead and do from you know do UI or rather dot do navigation we'll just go ahead and actually import navigation and so we'll come down in here and just verify our navigation routes see we've got routes imported right there so back into our sidebar here we'll go ahead and do our navigation routes we'll start out with just our first sidebar items here so we go ahead and do navigation do routes and then dot well this is going to be our home route of course that's going to be the dashboard the next one is going to be our blog right so we'll go ahead and grab that blog here and blog post route and with this in mind I'll go ahead and get rid of these right here and I'll go ahead and grab the sidebar item and we'll go ahead and do you know create post and blog post ad route we save that and now we've got some things in here related to our navigation looking pretty good the settings here are probably going to get rid of but what I want to see here is if I break it down are those Navar elements still in there and sure enough they are great so we have a sidebar in place with basically what a dashboard would end up being now naturally we still need a log out method we are not going to do settings here cuz a lot of things you're learning you'll be able to build your own settings if you like one of the things you might want to change is maybe the icons in here we'll take a look at that as well but I also want to have that toggle between dark mode and light mode but what we got here is a pretty solid start for a dashboard now naturally this is based off of the fact that we are just saying is logged in being true if we chck CH it to being false we should see that original page and that should still look basically identical to the way it did so naturally we need to implement that as well let's take a look at how we might do that so let's go ahead and make sure that our base dashboard page is showing up with logged in being true just turn that condition on so you've got this right here and so one of the important parts about this sidebar is the fact that each button element in here is actually a link so they they all navigate to a different page that's what they do by default but how it's being rendered is what we want to emulate by using a button because that's what we want now it's not a link but rather a button so one of the ways we could test this out is by going into the sidebar itself and just grabbing inside of anywhere inside of desktop only I'm going to just navigate down and I'm going to change this sideb item from settings I'll go ahead and just do rx. button and I'll just go ahead and say something like toggle dark mode just to start out and if I were to save that what we'll see is a button that actually gets rendered out but this of course is not looks like any of these other links here I want it to actually look like all of the other links in here uh instead of an actual button so how do we actually go about doing this well the way I'm going to do it is by actually copying this sidebar item here I'll copy the entire thing and we're going to change this to being something different and I'll just call this my sidebar like dark mode toggle item just sticking with the same naming convention in terms of item instead of saying button and so I'm going to go ahead and copy this and now of course if I were to change that button that I did with this dark mode here to basically say dark mode toggle I could do that or I could just leave a default of dark mode tole toggle in there and get rid of a lot of these arguments in here that I just simply don't need anymore so the text is now just going to be dark mode to toggle the icon we'll go ahead and just set it as moon for the moment and then I'll go ahead and get rid of this href in here just like that so now if we were to save it The Styling should look closer to what we had with all these buttons but of course I can now select this text here which is not what I want the other ones you know if you try to select it it doesn't quite work because it's a link so what we want to use instead of rx. Link we'll go ahead and do our X doop button now with a lot of these same exact elements in here so if we were to change it now at the very least it's going to start looking correc is but not quite so button not the right one instead what I want to do is rx. boox and I want to treat this box as a button so we go and do asore button now what this is doing then is it's basically saying hey this box make it a button element but do not use the default styling for buttons across the board that's all it's saying that's all I'm doing here is using a new button basically instead of the default buttons that come in with reflex and so now our toggle is looking a lot better but one of the things that's missing of course is this sort of like standard state do I want it to be black like that when I'm not hovered over it and so this is why recipes are really good to review is because you've got this style element in here that has underscore hover this is actually what's responsible for that background and that color and so if I were to comment out that background save it let it actually refresh a little a little bit what we will see is when we go over this dark mode button here the background goes away I can still select things so that's maybe not what I want but I'm going to go ahead and get rid of this background here and we'll go ahead and save it and now what we should see is the dark mode toggle okay great so that's back so this is actually showing me how I can do hovers classes in here there's all kinds of things you might consider doing but the main thing is I can see that there's this color element that I can now use on the default Style which is not necessary for the link but it is necessary for what we've got here so now I've got a toggle dark mode button here that is almost there the next thing is really is going to be the hover adding one more element in here and that is going to be the cursor and we really just want it to be a pointer itself this is straight up CSS that's coming through and so if we save it now and it should Now show us the pointer method in here making sure that we save everything and once we actually do hover over it now it shows us this and so all this little pointer finger really does is so that the user can know that this is a clickable element so now we need to just handle that click event so the way we do this is by jumping into our sidebar element here and of course doing something like onclick and then doing some sort of on click event handler and the Handler we're going to use is actually the built-in toggle color mode from reflex so we're going to go and do reflex. style we're going to go ahead and import the toggle color mode and so I can actually use this as my click event handler and we can just call it just like that save it make sure that everything is working here and we'll refresh and now I should be able to toggle that dark mode itself great so one of the things that's cool about this is it is toggling the dark mode but what it's not doing is it's not actually toggling the text itself so we might want to actually you know change this to being just slightly different so when I'm in light mode maybe I wanted to say turn on dark mode or something like that so the way we can do this is by using a another Handler in here and I can actually bring in let's start with the icon itself we'll go ahead and do RX dot color mode condition and then I'll go ahead and do light mode and dark mode so we can say light equaling to the Moon dark equaling to the Moon as well so the actual icons themselves if you were to do a quick search for Icon inside of the reflex docs you'll see the icon ability and you'll also see the implementation that is based off of lucid icons and you can search something like sun and you'll see all the various icons that are in here and so we've got our sun so that's the one I'm going to use for dark mode okay and so this condition here can take in components like this or we can use it for text itself so inside of the text we can come in here and say the light mode we would probably want to change it to being dark mode so turn dark mode on and then the dark mode we might want it to say something like turn light mode on something like that do a refresh in here now we should see turn dark mode on turn light mode on something like that all right so next we need this is logged in condition to actually work so the way we're going to do this is first off we're going to bring in the off state that we've created for our session which we just called our session state which of course is inheriting from the local off State package so I'm going to go ahead and bring this in now the way I'm going to do this is in base up high we'll go ahead and do from do off. state we're going to import this state element here and then we'll just go ahead and change is logged in to just simply session state. isauthenticated so this is actually coming in from the actual State element itself which we could verify by going into that class and just scrolling down we see that is authenticated in here it's a cached variable and it is a Boolean value very very straightforward another thing you can notice is if you scroll down you see there's a do logout method now this is going to come into play here in just a moment but for now now that I've got this session State here I try to save it and I get this circular import part thing or basically you can't import this and stuff like that so there's actually a little bit of an issue with the importing directly to the session State now you could try to import directly from off and what this might do is a circular import but basically we've got an issue with the importing this importing really comes down to the pages themselves so when it comes to these different pages here we have the base page right here for our login page and our register page so in other words this is actually importing a lot of the same stuff so we need to change our off package a little bit the way we're going to do this is by getting getting rid of the import from the off package for pages and I'm also probably going to get rid of the session State import as well that is part of the reason I actually did the absolute import here so naturally if I get rid of these Imports here this actually presents a new problem that we need to solve as well and that is coming back into our main module here this import for o no longer works so the first thing I'm going to do is from o. Pages we're now going to go ahead and import our various Pages our login page and our register page I'm also going to go ahead and do um from. a.state import our session State at this point these things haven't been used a whole lot yet especially the pages for login and lo and register so I'm going to go ahead and get rid of that import there and just do that and then the actual session variable the session State variable if we do a search on the entire application itself we see it's only really used three times so the import statement which if I get rid of it's no longer in there it's inside of fullstack off which we just got that import going in and then in base where we just imported it it is now working just fine so that should actually solve so that should actually solve that circular import error right there okay so with this in mind I now want to go ahead and take a look at my project of course now what's going to happen here is depending on if you're actually logged in or not you will see this dashboard here and so we of course need a way to actually log out this user and so the way we're going to do that is by creating a new argument on our state here this one is going to say I'm going to call this perform log out now in my case what I will first try is the super class or rather instead of the super class we'll just do self. doo logout which is going to be from our local state off and then we're going to do our rx. redirect and I'll just go ahead and do a slash for now we'll fix that in just a second but the idea is we want a button for performing redirect so what I'll go ahead and do is I'll grab my session State here here we will now go into our sidebar and what we want is the logout page or the logout component here so go ahead and find it which is this right here it's a side sidebar item which is not what we want instead I'm going to go ahead and copy the dark mode toggle and now make this sidebar logout item so very similar to what we saw before but not quite the same we only need one icon now so I'm going to go ahead and get rid of the color mode version the text we only need one text and that's going to be simply log out now it's important to note we actually don't need a condition for log in we don't need it to toggle between log in or log out depending on their session because they're only going to see the sidebar if they're logged in so that's another part of this that I think is important everything else is almost the same except for this onclick method here now I'm going to go ahead and import that so from do off. state we're going to import the session state and then I'll go ahead and do my session state DOT and perform log out okay so that's going to be our onclick event it will call this method of perform log out so let's go ahead and give this a shot we'll save it out and now I'm going to go ahead and click log out and so I got to implement the button itself let's go ahead and grab this and bring it down into our actual sidebar there we go notice the icon con is log dash out we'll take a look at that in just a second but with this a mind I'm going to go ahead and make sure that these are also in my mobile version if they weren't already in which case they are not as I see there so bringing in those in and changing the icon to just simply log-out which once again we could go into lucid and find that one as well uh but now if I refresh in here I've got my you know my sidebars in here it's looking good if I click log out it actually logs me out it takes me there and so one of the things we could think about when it comes to log out is maybe we don't want to just automatically log it out right so if I click on this yeah it's great that it logs the user out but what's not great is the fact that what if you accidentally click on it for that reason I want to go ahead and create one more page so going back into off into Pages I'm going to go ahead and essentially copy well let's actually copy our index page because it already has a button for us so I'll go ahead and go back into my index page I'll go ahead and copy this out and now let's bring that up into our off Pages here and this one is going to be my logout page or like a logout confirmation page the label says are you sure you want to log out or something along those lines I'll change the size to seven the text is well we'll go ahead and remove those things I'll just now do rx. button and say yes please log out and then maybe above that I'll go ahead and do rx. Button as well say no um something like that and then we'll go ahead and do our color scheme for no to be something like gray there's a lot of different color schemes we'll talk about more colors in just a little bit but for now I'll have this RX button here so the first thing is we want to actually just change this to being a link so RX button link and the href going where I need to go which in this case we'll go ahead and grab that state element itself for our navigation so from do dot import navigation and we'll grab our homepage for example or maybe our login page so uh in this case it's going to be going to our homepage so navigation routes homepage so basically going back now of course there's other things that we could potentially do for going backwards but I'm just going to go ahead and say no like that next of course our button here is going to be an onclick method and you probably already know what that onclick will be based off of what we just did with our sidebar so inside of the sidebar or actually inside of off here we're going to go ahead and do our from. state import our session State and we'll go ahead and use that element now so on click is going to be session States perform log out just like we just did now that we've got that we've got my login page here we'll go back into our navigation I'm going to go ahead and copy something in here and we'll put it right after the contact route and I'm going to call this my logout route and it's going to be SL logout and since we've got this log out route we'll go into our navigation and we'll put it in here as well so I'm going to go and copy this to login right underneath that to being to log out and naturally it's going to come from our routes. logout route just like some of our other ones great so now that we've got that let's go back into our sidebar and bring in our nav State now so we've got navigation already imported on here so all I'm going to do is change my onclick state to just being simply navigation. naav State and then to log out there we go now I can get rid of that session State variable once again and let's take a look at now if I click on to log out it should take me to the logout route sure enough it does the route's not implemented yet which we will do right now just changing the text a little bit so back into our main configuration or main module main full stack module here in my off page we're going to go ahead and do my logout page now and so going back into our different routes here underneath our log out and login route we'll go ahead and do our routes Dot and this should be our navigation routes so we'll do this one right here so routes do routes and this should be logout oops we got this right here so let's go ahead and change this now to log out route and simply log out and it's going to be my log out page which is the import we need to bring in and a we go so next now with this 404 page being refresh it should Now give me back to Simply that original log out page itself uh assuming that we've got something in here oh yeah so we've got an invalid color scheme I used gray with an E it should be gray with an A and we'll try that again there we go solved and now if we go into our log out page we should see are you sure you want to log out we hit no it takes us home great we go to log out we say yes log out and now it logs out okay simple enough so now we have a way to log into register and to log out and we see our conditional you know dashboard here so if the users logged in this is what they see now a big part of the reason that we need a difference is mostly so that when a user is logged in they have a different experience and more importantly when they actually edit things that different experience shows up as well and so when I do create a new post or something like that it needs to be Associated to my actual user so that's really the next step now we want to update this little section here with our actual user info so instead of my account I'll put our username and then instead of the you know default email here we'll actually use our user email so the way we're going to do this is fairly straightforward first off going into the sidebar itself what we want to do is navigate into the sidebar component which of course is this right here and then we just want to navigate down to where this h is where the icon of user and my account and all that other stuff in there so I'm actually going to grab all of the things from the hstack which looks like it's at this line right here so I'm going to go ahead and grab that and we'll cut it out and I'm just going to call this my sidebar user item and I will initialize it now the idea of course is after I do name it that I want to bring it in here as sidebar user item and then it's going to be rx. component and then I'll go ahead and paste out what I just cut and tab it back a little bit so it's a little bit easier to manage now as soon as I do this I also want to do it on my mobile version so I'll scroll all the way down to where the same stuff is with the mobile version and it is the same hstack I believe all of the information about it is the same so we'll go ahead and save that and then we will take a look at our rendered out version which nothing should have changed all across the board so of course now naturally we do want something to change and that's going to be fairly straightforward if you want to get anything related to the user we use the session State variable and specifically the authenticated user info and so what's going to happen in here is it's either going to return an instance of the user info class or none reminding you what the user info class is is that model in the database which only has these fields right here for now and so what we got is back in the state here this is going to return none this right here is going to have either a result which will either be the actual you know instance of the user info or it's going to return none as well and so realistically I just want to see if result is none then we'll go ahead and return none otherwise we're going to go ahead and print out that result the only reason to have this block here is to see the actual result itself okay so with this in mind we're going to go back into iside bar to where this user is and so what I want to do here is I want to grab that session variable so we'll go ahead and do from dot do off. state will import session state with this in mind I can go ahead and say off user info equals to the session state. authenticated user info and so that's going to actually show me exactly what I want now the idea here is this could be none so what I want to do then is rx. condition I'm only going to show this information if it's not none right and so the condition itself will be using the user info so we'll put the condition there then we will actually show out that info otherwise if there's nothing in there we'll just do rx. fragment and put that empty great so with this in mind that means that it's not none and then we can do something like this where we go into the user's email and we can just bring in something related to the off user info and we can do something like email now keep in mind this off user info is quite literally a user info instance so the way you could think of it is actually something more like user info object and then we could use that instead just to keep in mind that it is an instance of the class itself or at least it would be if it's actually available and you know that lookup when it's authenticated actually does yield some sort of result which should happen based off of everything we've done so far okay so with this in mind now we can actually take a look and my page has already Reloaded with that user info in there and it's all cached so this lookup right here is not going to continuously happen it's going to happen based off of the default cache setup itself or the session itself so when we log out that cach gets cleared out when we log in it gets updated okay so now that we've got that we can actually even see the print statement here and there is all of that users Fields not surprisingly all of those fields come directly from the user info model itself because that's that's what's stored in the database but there's one more thing that we might want to have in here which is what is the user itself the actual logged in user from that package itself so the package is from reflex local off. user importing that local user once again we used that for key already so what I can do here is I can actually declare a user and I can put it up to that instance or none and this is going to be equal to well from SQL model we can bring in something called a relationship we will see this again but I can bring in the relationship and by default it's going to go based off of that user ID right there but right now we've got the ability to actually now associate this object or whatever uh let's go back into this object is we can now associate them together with what's stored in the forign key value in other words this will give me the user the local user instance essentially based off of the ID that's stored here so we can see this even easier when we actually take a look at the authenticated user info all I want to do here is I actually want to refresh my page here I want to ensure that this cache is updated so I might have to log out to make sure that it's updated as well but the idea being that when I make some changes to the models I might need to refresh my cache and so I'm going to go ahead and log out and we will log out and then we will log in again okay so now if I look at that print statement this is what I've got I actually don't see the user data yet but if I change this to print. user I might actually end up seeing the stored user data and so when we look at it we refresh in here there is that stored user data it's quite literally showing up now as that instance so what this means then is going back into our sidebar I can go ahead and say something like user object and that's going to be well related to this right here but really what I want is my username via user object or something like that and for this I'll do rx. condition and that of course is going to take in the user info. user and then I'll go ahead and grab that user info. user. username otherwise I'll say my account let's see what this ends up doing this should bring back strings in here but what I could do then is change my text here is save it as is and we'll go ahead and do that and let's take a look and we still get my account okay so let's go ahead and just say this is a count just to make sure that everything's been cleared out and this actually did change based off of this new variable that we created and sure enough there it is it's showing us account count now What's Happening Here could be explained by the user method right here so first off what I want to do is I'm going to go ahead and add in and info so this is adding two conditions in here and that's how you do it with the Amper Stam in there so these two conditions are now piped together you could also say a pipe there if you wanted to do an or one but we'll just stick with and what I want to do is I want to go back into my state variable here where I printed out the user directly as soon as I do that and I refresh on my page here what I actually end up seeing is the user themselves so a big part of this is actually grabbing the result user so user object is equal to result. user and so what this should do is actually grab a database entry for that particular user that will actually do that lookup for you uh it's still inside of the session variable itself and as soon as you actually use that dot notation then you will get the actual refreshed version that will include that username itself so that is certainly one way on how you could do it in terms of updating the sidebar data now we could also use something a little bit different than this which is just simply our authenticated user because remember we've got self. authenticated user. right here so we probably don't necessarily need to grab that user object itself but instead let's comment that out and once again using session State we could go ahead and do something here and just do condition session state do you know is authenticated which it should be but we'll go ahead and do that and then it's just simply session state. authenticated user info or authenticated user and then username and we can sa that and that should actually give us the username for the authenticated user as well so there's a a few different ways on how you can approach getting that user data this one right here is much more about the relationship which at this point we probably don't necessarily need to have it on here but I wanted to show you both ways on how you can go about doing it because this will become important later and so what we see here is really just a query that gets related data for this particular user which we'll use more of and then in here we actually get that same information from the authenticated user itself the only difference is this right here is actually cached where this right here is not so what we want to do then is I'm going to go ahead and cache that in my state as well and we'll go ahead and grab the rx. cachar and what I want to do is say authenticated user username or we'll just go ahead and say authenticated username and turn takes in self and it returns Str Str a string or none and then once again we'll go ahead and grab this otherwise we'll go ahead and return self. authenticated user. username just like that and it should be actually username there we go so back into our sidebar once again just making this even better we are going to now cache that variable itself and there we go so now it's all cached out and so we should actually see the actual username and of course if we were to log out and then log back in we would see that cached value coming through at least in theory we would so let's take a look and sure enough there it is so off the video I went ahead and updated my sidebar here with a few new items as well as the actual icons that I've changed so I can navigate through my application a little bit closer to what I want it to look like so inside of the contact for example this is the same exact form it just now actually has a link to it in the sidebar with the icon from the Lucid icons themselves so if you did you know something like mail you can see the different ones in there and that's what I ended up using for these now the point of this one is to actually associate our user data so when we come into the contact model we see that we've got a user ID in here that is a field now the reason for that was to help associate this user data now this is not a strong Association this is just a reference to the user ID to the actual end user that we'll end up using so this is not the same thing as what we did before with our user info where we actually used a foreign key more on this in a little bit but for now what we want to do is just actually insert our user ID when the user actually submits a form the logged in user this of course is not the same thing as if they went into contact and filled this out but we need to adjust for both cases so if they are actually logged in we want to make sure that when they do contact us it Associates their ID in the long run we probably want to have a forign key in here but for right now we just want to see how we can update this field based off of a user that's logged in so there's a lot of different ways in how we can think about doing this one of the ways would be to go into the page that's actually rendering this stuff out so our contact page here we have the form element so we can actually pass in something like our user ID and let's just go ahead and say one this user ID I could then pass in as an argument to the form Constructor and of course if I were to go that method I would need to handle that Constructor that ID in here and then handle it in the form we'll actually see how to handle it in the form in just a moment but the thing is what we're doing here I can I don't necessarily need to do it this way now the way we would get this user ID would be to go from do off and then State we would import our session State here and then this user ID would be session State something like you know authenticated user. ID so that's one way how we can actually grab the user's ID but the thing is as soon as you see this session State inside of a component we can see that oh I can use this inside of another component I don't need to carry it down I can just pass the state variable around in other words I would get rid of these arguments here inside of the page itself and I would actually move this variable into the form itself so it's actually going to be in here instead of passing it down there's no reason to pass it down in this case and so once we do that we can actually add it in as one of the inputs itself so let's go ahead and do this method first and then we'll take a look at another method in just a moment so we'll do from. off. state we're going to go and import the session State and so with this session State what I actually want to do is something similar to our user info so let's go back into the state itself and we've got our authenticated user name which will return either the username or none I actually want to do that exact same thing with the user ID and so now what I'm going to do is say something like my user ID and it's just that simple and then in this case I'll go ahead and return back instead of the username just the ID now realistically what I would end up doing is something like instead of authenticated username I would probably say my username as well just so that the logged in user stuff you don't have to write it authenticated you could just say m that's my own personal preference but this is very verbose this is not as verbose but in this case I'm going to go ahead and leave it in as this so now back into the form that is the value we'll end up using for the user user ID so what this means then is inside of my form I can actually use a new input here so I'm going to go ahead and right above the vstc I'll go ahead and do rx. input this input is going to have a type of hidden right and so the hidden input itself will have a name of user ID now the reason we're using the name of user ID comes down to the model itself right here so that's the reason we're using that same name if it was a different name so like say for instance the contact user ID was the name this would be the name in the model as well or rather the model here just to keep that in mind on how you name these things I'll explain why in just a second as well next up we'll go ahead and put our value being equal to well our session user ID just like that so I don't need it up here necessarily uh but there we go so there's my hidden input now this will work when the user's logged in but it won't necessarily work when they're not logged in so let's go aead and see what it looks like when they are logged in now if I go into to my application I see that there is a field here this is the hied input field if we inspect the element here we can actually see the form and then the value itself is showing me my contact user ID so I need to update that but it gives me a value of one so it's literally going off of my user ID that I am passing in there which is great and if I were to log out and take a look at this same thing it's going to look very similar but of course it's going to be without a value inside of there so if we look in there now we can see that there's an empty value in here so it's not actually set which is fine but we actually don't need to render the field out at all if the user ID is not set so we'll go ahead and just do first off rx. condition and the condition itself is going to be this right here and then we want to bring in the input and then if it's not the input is or if my user ID is none then we'll go ahead and do rx. fragment and put it in as an empty string so we can save that and now on the not logged in one it's no longer there and then of course on the actual logged in one it is going to be well still that weird box so what we want to do is just add in something where rx. boox and I'm going to just go ahead and bring this around here I really just don't want that input to show up at all so I'll go ahead and just do display being none we save that and that should remove the box from even showing up in this case it's not actually working that way so let's go ahead and save it again there we go so now it refreshed and now that box is no longer there although the element for the input is still there and so if we look into the input itself for it we we can probably find it in here there's our form there's that empty box and then there's that input itself for user ID great so now we know that the form has this data already showing up so in the contact State here we can actually take a look at that data on the handle submit we'll just go ahead and print out the contact data for that data being submitted and then I'll go ahead and just run this real quick with a message hit submit naturally there's my user ID with some gibberish in there and then if we look at the contact history I did update it where it does have a user ID so if we look at the page itself when we list everything out I just added U you know this element right here seeing if the contact has a user ID will show it otherwise it'll show a fragment basically the same thing we just did with our form element uh but of course it's showing up on the contact page itself great so that's really nice and it actually does work okay here so I'll go ahead and say Justin again and I'll just give my message just to verify that it is a new message that's coming through in here and there it is right there great so this is nice that I can actually implement it in this form condition right here but just like our page where we didn't want to implement it here it was not necessary to implement it here can we implement it in the state like can I just do it in this handle submit so this logic is sound for sure so what we want to do then is import that state variable here bring it in and we'll do something like this now I will go ahead and take it out of the form itself so I'm going to go ahead and comment out this condition here just leave it out Al together so back into the state element here inside of this data I'll go ahead and do data and our user ID and then we'll set it equal to session State my user ID now we'll take a look at what happens here this to me is another layer of the logic that would happen that you might consider doing we go into contact and I'll say my new one and then something else hit submit and it says thank you my new one if we look at our contact data though it gives me this computed variable with well basically not the user ID so unfortunately we can't do this this is not how we can use or reuse a state object itself but what we can do is we can actually take that state value and I can use it as my default state for this contact State using this allows me to do something like this instead and just say self.y user ID and basically we would say if self. my user ID is not none then we'll go ahead and set that state value this allows me to inherit from the original session state which then allows me to set that data based off of it and so now now we'll go ahead and do it again and I'll go ahead and say my uh working state with some value in here hit submit we go into contact history we go to the bottom my working State and there it is there's my user ID so now we have two different ways on how we can approach doing this one is directly in the form itself which makes a lot of sense for a lot of things the other one being in the actual contact State the state variable that we end up using to handle the form itself so that is the way that I would do this one is actually bringing in our session state for our contact date and then updating it right in line you don't need to do it in the form if you don't need to do it in the form but every once in a while you might want to have session variables inside of the form itself which is why you would want to go this way so for example if you want it to actually show up in here let's say in your contact instead of you know contact usest showing first name and last name you could have those values pre-filled using this method right here obviously I did it with my user id but you don't necessarily have to have all of these values in here in fact you could even hide them Al together if the user is in there and just require the message and then they actually enter the message but the data that comes through would be the same as before the actual user's name and all of that which is also pretty cool so now that we've got this in mind this is a way that we can associate this data but it's not a hard Association it's not a for and key relationship so what we want to do is actually modify our different models including of course our blog model to actually handle the data where it's more corresponding to each other and there's a lot more relations involved very similar to like what we did with our user info here let's take a look at how we do that now we're going to do some quick housekeeping with our code here if we go to inspect the element and we look in the console we will see a bunch of console errors and it says invalid prop ID Supply to react fragment now if you're not aware reflex actually gets turned into reactjs in the front end but of course we're just writing python it just gets turned into it for us it makes it really really simple but this warning this error here is something we want to address so react. fragment is the same thing as rx. fragment so if we look for RX fragment inside of here we will see a bunch of different places we use the fragment so if we look in each one we just want to make sure that there's either a child element or multiple child elements or just a string no other arguments are necessary so on each fragment so far they look pretty good then eventually what I get to is the base layout component which has a fragment but also a couple arguments here so we don't need those arguments all of the other ones are components these arguments we do not need so we'll get rid of them those are called properties inside of reactjs but the idea is we've got these RX fragments we will go ahead and comment out just like that once we do that the console log should clear of the most things in here and so of course you could always look at the border radius one as well and if we do look for Border we can see that there's a bunch of different border radius settings in here so in the nav we see it as a image that's directly on there but then in the sidebar we see it that it's style that you assign to it so I think using the style is probably the way to go I'll let you do that in this case I'm going to go ahead and go back to it what it is that we're trying to work on which is going into full stack Python and seeing why we actually need relations with users why we need our models to be related now on one hand we have a model that's not actually related in the sense that it's not database related there's no foreign key available but it is related in the sense that we have a reference we have an a field that actually exists for our user IDs so what we want to see now is how we can really leverage the relation itself and really what it comes down to is state.pay we have this lookup for the user info the actually related user info we actually already saw the related user info come through when we did stuff like this right so this actually did something that's interesting that we'll take a look at right now now for this to work what I want to do is I actually want to go into fullstack python into my index page here and I just want to show you how that info ends up working so we're going to go ahead and do from you know off. State we're going to go and import oh we already have our session state in here so we don't need to import it again so go ahead and use this session State now in our index here once again we want to remember that it's like my user object is session state DOT well what is it it's the authenticated user info that is one object the other one is just simply the authenticated user so that's what we'll start out with is our authenticated user and I want to just render out that value so I'll go ahead and do rx. text and I'll grab that user object and put it into this text element here let it refresh and what we'll end up seeing is well something interesting this is now saying objects are not valid as a react child once again this is showing us that reflex gets turned into react on the front end but what we also see is that it says objects with keys what does this actually mean well what it means is that the actual object itself the actual my user object cannot be rendered out it can't actually be rendered out in this way now if we wanted to see the entire dictionary itself we can do something like two string and that will actually turn it into a string value so it's no longer a dictionary and then it'll actually render out so we can actually see that same value but of course as soon as it is a string value we can no longer do do notation like username in here like like this instead what we would do is we would get rid of this two string and just use username directly and that allows us to do this sort of field data in here that we might want to show up just like that so this is nice this is again our authenticated user itself but the thing is I want to get my authenticated users info as in I want to get this data right here they are related kind of but what I want is just simply user info here so the way we go about doing this of course was back to our state value where when we did authenticate with this user we actually grabed that result and set it into the cache we grabb the user info directly so the way we do it everywhere else is we actually just use the user info we use authenticated user info and then we go are going to go ahead and do two string here and we will be able to see that user info and of course what it's going to render out is the email all of that other stuff I even have the user ID in there because it is associated through a foreign key but we have only some of the user data so the next question would be oh well I want to take the same data and use my user info. user to stream the reason I'm saying user is because if we look at the model itself we can see that there is this relationship here for the user in fact in our state value we also saw that with result. user so I'm gonna go ahead and save this I'm not going to change anything other than this right here we'll go ahead and take a look and if I look at the data now what I will see is absolutely nothing but if I make a small change to the state that is if I actually do call result. user right in line before I actually return back the result what I will end up seeing is well the actual data itself the reason for this is because it's doing a database lookup right here we're actually using our session we're doing a database lookup for for the main user data the user info data that's all we're doing that's the only lookup we're doing as soon as we call result. user this does another lookup in our database based off of what our model says which says that user is a relationship now if I changed it to something like my user obj like my user object I would then have to go back into my state change this to my user object and then back into my component and change this to my user object once I make all of those changes that data will still come out once again and so that also means that I can do you know something like username in here and now I can see my user info and also the related data to my user info in here like our username now of course A lot of these things could be moved back to the state like we saw we did some of these elements in the state itself based off of just the user themselves but what we want to do is we want to do something very similar where we can actually query the users blog information or their contact information but we want to do it in either direction that means we want reverse relationships as well so what do I mean by reverse relationships well inside of our user info we did a my user object this gave me the reverse relationship to that local user to that related user so it actually gave me the reverse relationship the forward relationship as it stands right now is is coming back to our session this is going hey my logged in user my actual authenticated user which is an instance of the local user object this is actually how I get that forward relationship this is how I get the reverse relationship now I realized this might be a little complicated so what we want to do is we want to actually see how to do this with other models as well other models that have that two-way relationship this one does not have a two-way relationship exactly because there's no back populates argument in here cuz I can't actually change this local user itself so I want to change this back to being a user and I want to use that everywhere I had before just to make sure that it's working but I just want to remind you that this is a database lookup it's an additional one as a result of this and so yes it's actually getting the exact same user that is doing the original wear clause in here but the idea being if we don't have that database lookup that data is not readily available inside of this authenticated user State information but it's also that data is now Associated to the entry itself this is not possible with our contact so if we go into contact here there's no foreign key relationship so no matter what if I put a user in here and did the exact same things as I did with this it would not actually find that user because there's no foreign key available to it it it would there is a way to actually still find it though it's just not going to be as clean or as easy as this so what we want to do is we want to make this cleaner and easier and once again if this is complicated at all it starts to get a lot more clear when you actually do these reverse relationships based off of how you look things up and of course we could talk for hours and hours and hours on how to design this stuff inside of databases so we don't want to get too deep in the r whole itself we just want to understand the foreign key relationship and how these things are actually tied together because it actually adds a lot of robust capabilities on the database side once again that's not going to be discussed in too much detail here other than the fact that we'll be able to Leverage What the database does really well when it comes to finding related data and so let's take a look at how to update all of our different models so we can have more robust relationships and foreign keys with them now we're going to go ahead and build out a new models module that will have all of our different models that we need to have foreign key relationships with so basically we're going to be building off of user info instead of the local user mostly because of this relationship field right here which we'll look at in just a moment as well but the idea being that everything's going to funnel through user info instead of the local user so now what I'm going to do is I'm going to go ahead and copy this models. and I'm going to paste it into the root here right next to full stack Python and then just change the import just like that okay so once I do that I'm going to go ahead and get rid of my old user info Al together this old models all together it's completely gone now because it's going to be used a little bit different so State dopy now is no longer from just dot models it's going to be dot do models and it's going to go based off of that and wherever else I might need it I will do that I think it's probably just the state info itself next up just the same with our blog I'm going to go ahead and grab our blog model I probably don't need to repport everything uh but I'll go ahead and grab the blog post model here we'll cut it out and we'll bring it into right below our new model we'll save it in here looks like I've got everything necessary in there so I'll go ahead and get rid of that as well there we go next up we're going to go ahead and BR bring in our contact model in there as well same thing I don't think I'll need extra stuff in in here but of course if I do I will import them okay great so there we go so now I've got all these Imports and these models changed quite a bit so naturally what I'll need to do is I'll need to update where these Imports are um and I think it's probably mostly just in the state itself and that's pretty much it so from model do models do models and so on naturally once you do something like this you are going to have some big changes that need to happen on the database side right so we've got can't find off do models so here's this off one I'll go ahead and get rid of that we'll save that as well contact probably might have it as well looks like it doesn't uh and then we've got fullsack python. blog so let's go ahead and take a look at that there's our model import there as well also don't need that anymore so we'll go ahead and save it and hopefully that solves everything for us let's go ahead and try to reflex run again and there we go so can't import model from the init file on blog which might have something to do with my cash here so I'll get rid of that in a couple of places because this is definitely a major change and I realize it's sort of late in the game it feels late in the game that we're doing this but the reason we're doing this has everything to do with the relationships that we need to bring in and so we've got our blog model here I'm going to go ahead and import it now so from do do models import the blog post model okay so we need that model type there it's probably on the detail as well let's take a look if it's in here looks like it's not okay great just in the list itself because of the detail link and the detail list item that makes sense okay let's see if it's running now and now we've got on contact something with the init model as well it looks like it's trying to do it we've got contact state looks like maybe the cach here so I'll get rid of that cache as well let's run that again and it's still showing us that circular import so perhaps we have something in here on one of these Pages that's causing that get rid of the Imports that we no longer need this one right here is causing that so I'll do our from dot do model import our contact entry model there we go and do we need it anywhere else looks like we're okay let's go ahead and run that again and there we go so now it's actually compiling and so one of the first things I would want to try here is I didn't actually change anything about the database models themselves so let's go ahead and try you know our reflex run or rather DB make migrations and then we'll go ahead and attempt to run our migrate command here and so far it actually didn't make any changes to the database itself my next test would then be to jump into my actual project and see if everything's still working correctly and so if we log in here we've got our username and password sure enough everything seems to be working okay as far as lookups as far as submitting data as far as actually getting our contact entries our blog post if we had any I'll go ahead and just create a new one hello world I did delete a database at some point so that's probably why that's not showing up there that is and we see Hello World in there and just like that okay great so now we have a new location for our models the reason for this has to do with how we do and Define these different relationships so our user info model is just simply user this one does not have a reverse relationship in other words the local user instance cannot grab user info like the user info instance can grab that local user so keeping this in mind we want to have access to both models now there's probably a way to augment the local user model itself which is probably fine but the thing is I don't want to touch it I'm using that third party package for things Beyond just the model itself and we extended it on purpose and that's what we're doing right now is to make sure that we do have extra data for our user that extra data is now going to come in the form of the this blog post model right here so instead of using user ID I'm going to go ahead and do user info ID and this of course is going to be an integer it's going to be a field the default will be none and then the foreign key itself will be based off of our userinfo doid right so it's going to be based off of this model right here of course if you changed it to something different you would need to update that as well to the lowercase version of the class and the field of ID it has to be an ID it has to be to the primary key as a reminder ID is a primary key that's actually in there by default but it's just hidden from when you design it this is true for every single model so being building out foreign Keys is possible with that mind so now here's the big reason as to why we're doing this and that comes back to the user info instance itself we want to set it in here and as an optional value of the user info class and then it's going to be a relationship with something called back populates and since it's a blog post I'll go ahead and call this posts and so I'm going to bring in optional from typing so we go and do from typing import optional okay so now we have the ability to do the user info one way so from the blog post instance we can grab the user info but what I can also do is come up to now my user info and have a reverse relationship so we can do posts and now I'm going to go ahead and declare the list value from typing which will be a list of the blog post model quite literally this name right here in strings so that it knows it's on the actual module that we're in here with and then this time it's going to go ahead and do our relationship and now we want to go ahead and say back populates being something like user info so back populates as in the blog post model itself is going backwards with user info we'll see what that looks like in just a moment uh but now what we've got is this reverse relationship so both of them are defined with this back populates relationship they both need to be defined to be able to define the back populates otherwise only one side has it as we saw here this is the one side that has it once again the local instance can't grab the user info without an additional look up which we definitely did see okay so that's how we associate it and so we can take the same concept exactly exactly the same with one change into our contact model entry here and I'll paste this in of course the user ID can still be stored there so we can still do that and we'll take a look at how we change it in a minute and of course the user info still user info this back populates now is going to be something like contact uh let's do contact entries here okay and so so now we go back into our user info and we'll go ahead and do our posts here and change this how we want I'll go ahead and say contact entries once again our contact entries model let's go ahead and make sure we grab the exact class name itself and then back populates user info is just fine okay great so now we've updated our models quite a bit so let's go ahead and run our migrations again now I know if there's any issues right now with the migrations I'll just delete everything related to the database and the Mig ations from before and they just rerun it all again part of the learning process is getting really comfortable with migrations and your database tables and making changes of them and so the local environment is really really useful for this and so I do have an issue with here we've got constraint must be a name so what I'm going to do then is I will quite literally delete all of those old migrations and then we'll go ahead and delete everything related to our database in here and then we'll go ahead and run this once again so now that I've deleted everything related to this database I'll just do reflex DB and init I should not have to do migrations after doing init it will do all of the migrations for us the it will make those migrations so right now it shouldn't have to make those migrations and then it'll even run the migrate command as well and so now we should have no errors anymore and of course this means that all of our data is gone that we had before but now we're in the place where we can start really using the user info model quite a bit now again if you try to do this with the models all separated in separate locations what you'll probably see a lot is circular Imports this mod models.py module removes the need for all of those circular Imports but each like component like the off component itself all of these things are still valid as they are we won't need to change these at all just the user models themselves we needed a wait to be able to import the blog post model into the user info model and we needed to be able to import the user info model into the blog post model and the other way wouldn't have allowed for that to happen so now that we've got this let's actually take a look at what we can do with some of these related fields as we start to build out more aspects of it but first of course I need to actually create this user info I need to tie these things together in our blog post when we create new blog post all right so with a fresh database with no blog post yet and a fresh user we're going to go ahead and actually create blog posts and assign the user info ID before we can start doing that we need to go back into our session State here and actually get my user info ID so very similar to what we did right here I'm going to go ahead and copy this paste above it and we'll call this my user info ID what we need to grab is of course the authenticated user info which will be an instance of that class which of course has ID in there I'm going to go ahead and get rid of this result. user we don't want that to show up anymore it's not NE necessary at this point I'm going to go ahead and grab this authenticated user info here and we'll go ahead and say if self. userinfo is none then we'll return none otherwise we'll just return the authenticated userinfo doid still very very similar to the local user but now it's just the user info itself and so with this in mind we're going to go ahead and jump into the blog State and as you recall the blog state had this blog ad post form state that handled the submit in here we also have one for edit to do all of the things related to edit but then we also have sort of a master one that does the lookup otherwise this master one we're going to change from the default reflex state to being our session state so we'll do from off. State import our session State here and we'll bring that in and of course the reason for this has to do with the fact that we can now come into our other ones and we can actually quite literally print out the self.y user info ID that exact value because again we can't use session state. that value we have to use self do because it's inheriting so this one still inherits from that even though it's coming from the blog post state so it inherits like a couple levels up but the idea is now we can use this data so really we want to say if self.y userinfo ID is not none then we'll go ahead and set our form data in here so we go ahead and say form data actually let's let's go ahead and make it a slight variation of this and we'll call it data equals to form data. copy and now I'll go ahead and do data and user info ID equals to self. my userinfo ID then I'll go ahead and say self. form data equals to data and then we'll go ahead and pass in the data to the ad post itself great so at this point I could also print out this data if I needed to just just to make sure that that's actually coming through so let's go ahead and do that I'm going to go into my blog here no notice that I have no blog entries I'll go ahead and create a new one with just saying hello world and hello world again we'll go ahead and submit this and there it is now editing this and of course if I go into the blog itself click on the blog itself we well don't see anything just yet but what we do see in the print statement is the user info is the correct user info instance ID keep in mind in this case our actual user ID and our user info ID just so happen to be the same ID that's not always going to be true it might be true but it won't always be true so what we've got here is our user info ID on this dashboard is the same thing as our user ID okay that's just an important point to point out because if you accidentally use a user ID it might still associate the data close to being right so it's really important that you make sure that this is the correct version versus this Okay cool so with that in mind let's actually go ahead and jump into the detail page for this what I want to see is I want to see that user info ID on the post itself so once again we'll go ahead and actually use let's use the text value here and I'll just go into the post and of course there going to be user info ID and I'll just go ahead and say user info ID with that data and of course on the post itself once everything is working out we'll go ahead and take a look at our blog Hello World there's that user info ID that's showing up so the logic of course would be okay well now that I can get the user info ID can I get the related data as in the user info itself which will do to string here and this is going to be now the user info itself with that string data so in theory it would then be a dictionary value that would end up showing up here but of course it does not do that it not automatically bring that data in because we never did that proper lookup in our state so going back into the blog post State we'll get rid of this data here I'm going to scroll up a bit to where we actually get the post we've got load posts here get post data in here there's nothing in here that's getting that relative data at all so all I need to do is say result. userinfo here and that will then do the database lookup so DB lookup right and maybe we want to do that in other places we did have it in here at one point with the result user so this is basically that same idea and now of course if I were to refresh on that page I now have that user info so we go one step further and we're like oh do we also have not just that user info but also the user the actual user itself so user info. user right so the real user data does that come through now inside of that lookup and of course it does not right so this is going to be just simply user so once again if we wanted that data as it stands right now we would need to do a user lookup then as well and then we would come in here and we would probably have to do something more like if results user info then do the next result user info like that and then in which case you can now have the three lookups that are going on the actual database entry itself let's go a and make sure that we didn't have any errors in here give it a second as the cache refreshes but we have the blog post database entry then we have the user info relative entry that's going through in there for some reason that cach isn't clearing so I'm going to go into disable cach on my network and just refresh in here let's try that again on all across the board it might have something to do with that related database entry look up this right here um so let's go a and refresh in here and see if it does it okay there we go so now we've got those multiple entries that are coming through so the first one is that database blog post the second lookup is the user info the third lookup is the relative user directly so this is where you know we actually do see the related user info in here right so let's go ahead and go back and I'm going to go ahead and just use if user info I'm going to comment this one out right now and we'll print out working or something like that so again we had the user info right there it's right in line so once again with that in in mind we will see if it actually does print this data out so if I were to refresh in here it does not do that so the actual additional lookup just doesn't happen if we don't make it happen so of course that's something we're going to continue to need to improve before I go any further though I want to do the same stuff with contact and it's actually going to be very very straightforward it has everything to do with this handle submit and literally just this two lines here that will now associate that user dat data so inside of our state for our contact we already have the session State Associated to it in this handle submit here we already have that my user id which we could use basically the exact same thing all over again and this is how we can now associate two forign keys in here as well and now it's also going to be on that contact State and of course if we wanted to do a lookup we totally could but the point here is now we can actually just put in our data some message and now it should actually give us uh you know some relative data in there which I don't actually have the data yet I'm not going to do that lookup on that page you can do it now but the point is this is how easy it is to then start associating this data of course we still want to have the reverse lookup we want to be able to do some of these relationships in here but that's something we'll do in a little bit now we want to implement a more efficient way to do related field lookups related through a foreign key lookups so this right here works but it gives us three database lookups which is not what we want we want just one because we totally can and it's actually not really that complicated to do so the first thing that I want to bring in here is we're going to import the SQL Alchemy package and then in our actual lookup what we've got right here I'm going to change this a little bit and we'll call this our SQL statement and this is going to be what this is right here and then I'll just go ahead and pass in that SQL statement into that result the reason I'm changing it to being just simply SQL statement is because what we're going to do here can be used with other kinds of SQL statements so like in the list view or for example you can have a lot of these same things happen in there as well so we go through the process of actually selected selecting out our model then we can do something called options so inside of here we can pass in additional data for our options the additional data is going to be from our SQL Alchemy package .m. jooin load so we want to join data and load it at the same time that joined data is going to be based off of our blog post model and then dot the related field itself so user info that's the relationship field do keep in mind that so if we go into our models here we've got our blog post model there's the relationship field and it back populates which means that it's also on the user info field as well this is how we can do these related field loading and so that will actually bring in our user data we can now get rid of this print statement I'll get rid of both of them so we'll save that and I'll actually just rerun the entire thing just to clear out some cash if there's any caching issues then I'll go back into any given blog post and I'll also make sure that I've got disabled cach on my network just to make sure these lookups are working correctly so if I refresh in here now user info does come in great the related user from user info does not come in so that's kind of two layers deep right so that means that our statement here doesn't capture the next layer now of course what is the next layer well let's go ahead and look at our models again what I'm referring to here so we just did a lookup the first layer is the blog post lookup the second layer is the user info lookup the third layer would come from the user info and the actual local user model itself so that's the third layer and you could go even further than that but what we could do is we could take this same concept here and then just put a dot here and do joined loaded again or join load again then we grab the user info so we'll go ahead and grab user info model and then we'll scroll back down user info model dot user just like that so now it's just one query that will then go into our database and load the data that we need need for this particular blog post now this is about efficiently loading things and much more for as your site starts to scale up you're going to continue to want to efficiently load things and maybe even eventually Implement a caching system directly into the statement itself or rather the results themselves based off of everything that's going on here so you're not necessarily hitting the database every time you need to go to this blog post right now when I go to this blog post it actually reloads every time there is some caching involved in terms of the front end and in the back end and how reflex ends up working but in the long run you'll want to update this to being some sort of level of caching whether it's something like redis or something similar the idea being that then you won't be hitting the database in this way every single time you'll do it only when it's 100% necessary but this will actually get you pretty far you'll be able to do this for a long time the caching part will be when you're getting a lot more more user and you're starting to see degraded performance from just this single lookup so yeah this right here does still work um and it will work also for a long time but since we can do this join load we might as well do it and do it whenever necessary now of course not everywhere will you need both of these things right so like if we think about our load posts down here we've got our blog post model with those lookup args but we can add in the options here as well like the you know the blog post user info so if we come down here a little bit and add those options in I'm going to go ahead and tab it over and I'll get rid of where the actual user itself and just leave in that one single option for the blog post user info so that now in my actual list view here I can just go ahead and say something related to it which is going to be our blog post detail uh link we've got our heading and maybe something related to the post itself which I'll just go ahead and grab this and just do our post. userinfo and then dot let's say user ID just so we can see what that ends up looking like on our blog post list and let's go ahead and make sure that we actually have Post in here looks like we've got three items that were given did a little mistake on that information here so go ahead and update that just slightly on here here which is giving us our child and our post so let's go ahead and just move this over here so that we have that coming from that and we'll go ahead and refresh this a little bit and so there's our user ID right so it's actually doing the lookup in both places and of course I could just change it to being something more like buy and then post user and let's just say email because we have the email and so it actually show up the you know blog post title and then who it's by and we probably want to put some space in there and and there we go so now we can actually see that we can associate more data to it we can do it in an efficient manner and then we can render out that data however we see fit whenever we need to now of course this also assumes that you might need that data do keep in mind if we did not have this options here let's go ahead and get rid of it and save that we probably won't have any of that related data actually come through so then it will just give us something more like that which does create a little bit of an issue so really knowing how to do the query lookup is something that you're going to want to continue to experiment with as well so that is pretty nice and it makes it really easy on us to be able to get that related data I have a simple problem that we're going to solve right now and that has to do with these blog posts so I created a user off the video and I logged in as that user and I actually have access to the other users blog posts and I have access to edit them as well now we don't want that instead what we're going to do is our blog and our create post and edit them all of that is going to be related to our single account then we'll create a new asset somewhere where when we do want to publish any given blog post those things will be published and you'll be able to see them there that's where it'll actually combine all of the blog posts that are published so at this point what I want to do is narrow down the current blog as is so the way we're going to do this to start is of course inside of load posts now we've already seen how to narrow down based off of whether or not it's been published we're going to do the same idea but based off of whether or not it is the current user so inside of our lookup ARs here for our load posts I'm just going to go ahead and do our blog post model. userinfo ID equaling to self.y user info ID those are now going to be my lookup args for any given blog post so if I save this as is what I will see on this particular user assuming like the cash all gets cleared out and all that it will eventually just show me my single blog post user ID in here just like this and so the load posts I actually don't need it based off of all this publish anymore I'll just go ahead and have it as the single wear Clause that's in here and that's all we'll end up doing we will come back to the if published only later um when we actually Implement that feature on the site and I'll just go ahead and put these loog load blog posts in here as args and keyword ARS just like that we save it and we'll just go ahead and make sure that this is all working as intended in terms of the blog post so now our ABC user should only see theirs so my new post exclamation mark some gibberish here we save it we see that that's in there now we see the post is by that one single user and of course if we were to log out we would end up seeing that one single us user but this didn't solve everything because if I actually change in the URL the ID there and hit enter it actually shows me this other user data still we don't want that so we're going to go ahead and change that really simply with a same sort of query in here but of course in the G post detail view here so the idea then is we're going to go ahead and update our lookups here so we'll go ahead and say lookups equals to this uh you know empty dictionary here or empty uh tupo and we'll go ahead and bring the blog posts and we'll go ahead and do something similar of course that we just did and so we'll go ahead and just say user info ID and it's equal to my user info ID and this is what we'll then pass inside of our wear Clause just like that let's just make sure that this ends up working in terms of loading everything so if I refresh in here now it's showing me none okay great so that's a good sign naturally with our detail here if the blog post is is none we probably want to change the how the child element ends up running so basically something like this where we change this to rx. condition and then the blog post if it is value if there is something in there we'll show that otherwise we'll do rx. heading something like blog post not found or something like that as the fallback and so hopefully this this will actually refresh to being blog post not found great so definitely a good start maybe we want to add in this information in here as well so rx. what do we call it hstack and then put that heading in there with those arguments in there as well so that it's a little bit closer to what we might want for that particular blog post and so once it refreshes we will end up seeing that same thing now the idea of course is in the edit page we also want that to show up the same way basically so I will go ahead and do a blog and we'll just call this not found. piy and we'll go back into our detail and I'll go ahead and copy this H stack right here and so we'll come ahead and say Define not or blog post not found and it will turn return rx. component and then it's just going to return back that value so let's go ahead and import reflex as RX great so now that we've got that going back into the det detail we'll do from doot found import blog post not found and now we'll use that instead of what we had before great simple enough in terms of the single detail page it's not found it's not accessible we could talk about different arguments we might want to have in here for that lookup but I just wanted it to be very simple because now in the edit page I want to do the exact same thing so we'll go ahead and come in here and do from do notf import blog post not found the child element rx. condition of all of that stuff and then you know blog post not found and there we go so now when we go to try and edit a page that's not simply ours that will that should also change depending on when the caching ends up catching up um but the idea is we've got a little bit of an issue with this one let's see what's going on we've got our vstack oh that's why we didn't actually put a condition in here so I'll just put my post in there like that and then we can have our standard post coming through now and then our blog post being the other condition like it should have been in the first place okay so now we've got the edits coming through and saying blog post not found this is another way of saying you don't have access but for now we'll just leave it in as that and so now if I go to my blog posts and edit them all of that is working and looking exactly like we want okay so back into our state element here all we want to do is verify these things are working correctly the lookup is based off of my user info this post detail well of course if the user is not actually logged in we want to handle that as well so if my self. user info is none or is none then we'll do self. Post equals to none and then we'll just do return which is essentially what's happening in here but not quite so I'll go ahead and grab a few of these other ones and we'll change the content to being this publish post active I think is a true false value in this case it is a false that we would put in there and we just want to set basically the detail items in here like that so that if I do go to a blog post and I go in here and copy and open it up into another page we see blog post not found now this should probably be a login required route as well I'll leave that to you if you want to do that but as it stands right now we at least have something that's saying hey it's not found um directly on there so now that we've got this in place we have a isolated resources for this particular user they're isolated in the sense that there's no way to really query these blog posts as they currently stand this is not isolated in the sense that the database is isolated it's just isolated on how the lookups end up happening inside of this particular blog post state so naturally we're going to expand this and then actually have a published version of this so that anyone would be able to see it so yeah that's let's go ahead and start that process now so we have published blog post of everybody on the entire site which I'm actually going to do some publish blog posts in the background just to make sure that that's working as well now before I jump into the public ones I realized that we never actually implemented a login required decorator so we're going to go ahead and do that now it's fairly straightforward so in all of the different pages that you want login required we'll go ahead and do import reflex local off and then we'll just add in the at reflex local off. require login this decorator then will be applied to Any Given page that you want to require a login so if we go to a new blog post here of course I'm already logged in if I were to copy it and go to an incognito window uh it's going to require me to log in it's really just that simple it's not actually that hard to do so so you can always add it anywhere you want to depending on how you want to run the logic behind a logged in user so add edit those two make a lot of sense to have them uh but the point being that we actually need this decorator so that it's kind of like that password protected page that we had before um which was this right here which also didn't actually come in with this login required as well so even if we did discuss it before or you saw it before the idea here is we want to make sure that we have this login required component across our project so that at any given time we can see exactly just the data for a logged in user when that logged in user needs to access that data now we're going to implement published articles and they're going to end up living on our dashboard our main page here so if they're not logged in we'll probably have some information about the site but then if they are Lo Lo in they'll see just recently published articles and they'll be able to go based off of that now there are more advanced features that we could eventually build but for now we just want to keep it nice and concise based off of everything we've done so far so to start out what I'm going to do here is inside of my module I'm going to go ahead and create a new one this time I'm going to call this my articles and state.pay inside of Articles we will be doing a lot of things we've already done I'll go and use init.py in here as well I'm going to go into my blog and I'm going to grab the blog State copy everything from here paste it in and now we're going to call this simply our article State and we would use the article route or articles route article let's call it article list route and we'll do a lot of the same things we did before so inside of navigation we'll go into our routes here and we will now put in our articles list route and of course it's SL articles just like that okay so the first thing's done next is going to be post post content all of those things are probably fine the post ID is now just going to be simply instead of blog post ID we'll just go ahead and call it the post ID which will take in the arguments for post ID itself the blog post URL this is now going to be our post URL so let's change it a little bit the only reason I'm modifying these things is so that it actually makes sense in the context of what we're trying to build out here now we actually do not need an edit URL at all anymore cuz that's completely gone it's not necessary anymore next up the actual detail view itself I'll go ahead and get rid of everything related to the user now I will still keep the blog post ID which is going to be the post ID and it's still going to be going off of the blog post model but the next thing is not going to be my user info but rather the thing that we commented out before and whether or not these things are active so I'll come in and just bring that in like this we will uncomment them out and then tab back a little bit and so now we see the three different queries or three different conditions that are coming in to our SQL statement that will then end up looking up this user we still probably want the related user information so we can put stuff related to the actual end user next up we're going to go ahead and say the post is not there then we'll go ahead and set the things as necessary uh and I'll also go ahead and put in here post content just like we may have seen before but I'll go ahead and do it once again there we go next up we want to get the load posts in here once again we will bring back the publish only in here and I'll get rid of some of the other arguments that we had because we don't need anym so now the select the select query is going to use just that for our wear Clause there we go add post we no longer need to support that say posts edits we no longer need to support that either to blog post we actually might want and this time I'll change it though to to post itself and then of course if the post does not exist then we'll use that article redirect that we have or the article list route let's go ahead and use that one scrolling down and edit page will no longer be one and then we've got a redirect to the post URL great and so we should see everything as such I'll get rid of a lot of these comments that we had before and there we go so now we've got our article State and then I'll change this to being something like article public State and then I'll get rid of all of the form related things because we no longer need those and so that should actually solve the vast majority part of the state elements in here as to how I might want to look them up next we're going to go ahead and bring in the list view here so the first one is going to be basically my article uh we'll go ahead and say article uh public list view something along those lines and then we might need the state element again depending on the actual blog post that come through so this one is a little bit different it's now going to be our article public state. posts and then we have our blog post list item which is is generally okay but I actually want to improve it a little bit so go going back into the docs we've got this card element here this is actually what I'm going to go ahead and use instead of what I have for this list so I'm going to go ahead and go back into the detail link and I'll just go ahead and paste this in in just a second let's go ahead and comment out the original return and then we'll return back the card element itself with that link I don't have an avatar for this I'll go ahead and get rid of that uh but I do have stuff related to the blog post so I'll just go ahead and use the blog post itself so post. tile and then maybe we have some content in in the text area here I'm just going to go ahead and leave those out and then of course the link itself we want to make sure that this is linked so I'll go ahead and use that original href and so I'll get rid of some of these other things in here uh including we probably don't need that child element anymore either so I'll go ahead and get rid of uh those things in there like this and post ID should be in there as well otherwise we'll return back uh basically like not found or something uh but it should have an ID so we shouldn't really be worried too much about that and I'll change this to really just the uh post link or article link there we go and so I'll put this as article link and we'll go ahead and call this article list item there we go and so down in here there's our article list item showing up a little bit better okay so now I want to show these let's take a look into our full python I'll go ahead and import this directly so we'll go ahead and do from. articles. list import the list page itself and then now I'll go ahead and come down next to my blog list page right above it we'll go ahead and do our different things related to this blog list page or rather the blog list they the article list page and then the article list route and then next the state element we also need so going into that we will go ahead and bring that one in as well so from articles. State import the article public State okay and then we'll bring that in down here article public State load posts great so now going into our full stack python let's go ahead and make sure that everything is running and it gives me this positional argument error here here let's go ahead and change that to just being simply the post that's coming through along with the padding we probably don't need a bunch of these things we'll take a look at if we do in the future but let's go ahead and refresh this here in fact I think we could probably just augment it all together and just use the article link based off of how those cards are but the thing is this box here we might want it to show up with a box so now I'm going to go ahead and use that same idea inside of my navigation routes I still have this let's go ahead and add in our two articles here and here we go so two articles and article list route and then in our utilities into our sidebar we're going to go ahead and grab our different items in here as well let's just find them there we go and so we've got our blog now I'll go ahead and say articles and we'll leave that in as articles for now article list route let's go ahead and grab something like Global or Globe there we go so grab Globe as the item there we go and so now let's go ahead and take a look we've got our articles in here now everything should refresh in just a second and so let's go ahead and do that we've got blog and article so no articles are in here so going back into our article list we want to change a number of things these are going to be published articles we no no longer need the link in here so we'll get rid of that as well so we save that and now it should give me just simply published articles which there are none currently so let's go ahead and publish one one of our own I'll go ahead and publish this one right here we're going to go ahead and say publish active and I'll just put it to a few days ago we'll save that go into articles now there is the post itself articles but unfortunately it's going to my original blog post it doesn't go to the correct detail page so naturally we need to change that so we'll do it and we'll do it in a few easy steps so going into our blog here we'll grab our detail element we will paste it in here and so not found we'll still be there and I'll just go ahead and use blog not found as in blog post not found that's probably fine next up we're going to go ahead and use our state we don't need an edit link anymore we don't need it at all as far as can edit we'll get of that Al together and there we go so what we want in here is of course the blog post itself so there's going to be article public state. poost now and then the just changing the state value basically all throughout and maybe changing the content in a moment but for now I just want to make sure I can render out this page with is of course is going to be my article detail page so let's go ahead and bring that into to our main project here and so we'll do that and in from. articles. detail import our article detail page and I'll go ahead and grab our article detail based off of our original blog post detail so go ahead and copy this and we'll bring it right underneath our article route here and so this one is going to be based off of that article route and this time I'll go ahead and bring that in just like that this is not our post ID or our blog ID anymore it's now our post ID and we'll just actually use use navigation Dot and there we go that should be post ID this should now be our article State doget the post detail I believe it's the same name let's go ahead and just double check that and so there's our get post detail and our post ID is the argument great so now that we've got that let's go ahead and go back into our list here and so the root path is no longer this but rather our article list root path so that the link actually does change going back into the Articles let's go ahead and make sure that we've got a few things we got canot find blog oh yeah okay so going back into detail we need to do dot dot blog not found for that element this might be one that's useful in other places so maybe we put it into our UI uh but for now this is probably fine we've got our published articles in here new blog post and we see that it's still going to the wrong place so let's go ahead and see why in our list element here we've got our root path and that's it so maybe I just didn't save it which was probably the issue so let's go ahead and do that again and there we go now it's showing that article of course it it's got a few things that are wrong about it like the edit button itself we don't need that edit button uh wherever it ended up being so we'll get rid of the user info stuff in here as well so there's that then we've got our publish data our content those things look fine the edit button should go away but perhaps we're just not using the correct function for the page or the correct component and sure enough we are not so go ahead and bring that one in assuming that we did import it already and so there we go so now this should actually refresh the article again let's go ahead and see there's our now published article in there and it shows us when it was published and of course if I log out let's go ahead and log out and log in as a different user and just go ahead and see the Articles there's that other article and of course my blog post if I wanted to make this one public I could and I will just go ahead and submit it now and there it is hello world and my new post naturally the article themselves we should probably have the maybe the username or something along those lines so inside of the detail let's go ahead and grab the username and the way we're going to do this is by grabbing the post the user info. user. username let's just make sure that that stuff's being uh you know added so we'll go ahead and and say buy and we'll add a space there add a little element there and we'll go ahead and see if that ends up solving everything related to the public ID sure enough it does and there we go so that's exactly what we want we want a public version as well as a private version both of these things we can change at a moment's notice we can take them off from being published we can see that they that it just happens just like that great so this is definitely the foundation for something much bigger but what we just did was just run through everything that we've already done just in a different format which is why it went so quickly now we're going to change the homepage so it has a few of the most recent articles and we're also going to change the navigation so that it's no longer blog but it's about articles so let's go ahead and start with the navigation this is fairly straightforward in the UI here we'll go ahead and look for nav and I'll just do a search for simply our blog and of course there's number of blog items in here so we'll just change it to article and then this is simply to articles or we can change it to articles as well so once again we'll look for the next blog one which is articles and then our article list route save that and sure enough we will see the nav bar changing to adjust for articles and also articles great now one of the things we don't want though is if I go to the blog I actually want to make sure that if I'm going to the root blog not to Any Given item on the blog I want to go ahead and make sure that this is login required as well so we'll just do that really quickly inside of the blog we'll go into list upy and then we'll go ahead and add in that reflex local off. require login and of course this means we need to import it just like that and now the blog post page will require me to log in going forward so that it's a little bit more accurate to what you would want with the dashboard setup okay so this article page this is not how I want it set up going forward so let's go ahead and take a look at that one now inside of Articles we'll go into the list here and I want to change a number of things the first thing is this list item we actually don't need this this is kind of redundant so I'm going to go ahead and just use the article link and that's it uh for the Post we don't actually need to call it we'll just call article link itself the argument by default will be the post so now I'm going to go ahead and get rid of this article list item in here now a thing that would be better termed here would be the article card link and so that's what I'll call it here we'll go ahead and save that and we'll take a look and what ends up happening of course is the pages the actual spacing here might change a little bit or might stay the same in terms of well we've got spacing right here as well so that's actually kind of nice I've got this artical card link but now I want to actually Implement something new that will do all of the iteration for me this is so I can reuse it and this I'll call my article instead of public list page my public list component and this will then be responsible as rx. component and this will be responsible for really just doing this portion right here so go ahead and return that and there we go okay so this is almost quite there but it's not quite it's getting closer so the next thing is instead of having v stack here I'm going to change it into just simply box I'm going to get rid of spacing and I'm going to get rid of alignment once I do that the article's homepage will change quite a bit or at least it should in terms of the way it's being rendered out now before I actually take a look at the rendering what I want to see in here is I actually want to use something different which is rx grid so RX grid is going to be nice because then it will actually be able ble to render out each one of my posts into columns so let's say for instance we put it into three columns here save it what will end up happening on the article list is it will actually start having three different columns here let's make sure that our reflex project is running and I didn't forget a comma looks like I did forget a comma let's go a and add various commas in there and let's see if that ended up compiling then and it should change the layout of this page a good amount so with the columns in there and now with it refreshing let's go ahead and just do a quick refresh here and it's running again and here we go with the articles there we go so now it's a little bit different or quite a bit different actually so the whole width is here and it's got you know quite a different type of columns going on so if we wanted to keep those columns and then add in some spacing here we totally can we can say five as far as the space is concerned and then I can refresh in here and now it'll be a little bit more spaced out in terms of the recently published articles okay so now obviously if I add a l a lot more it's going to start looking like a grid so if you look inside of the reflex docks for grid you can see where it's going it's going to look sort of like this in the long run which is kind of nice for articles because then you can get a quick glance as to all the different articles that are there and granted you could always change things maybe add images and stuff like that a little bit more advanced features that we're not going to cover right now but with this in mind I want this same idea to show up on my homepage maybe like right underneath here and so as it stands right now we could actually import this and use it on our homepage so let's go ahead and do that back into to our full python here um we've got this list element I'm going to go ahead and bring this in the public list component for my index page here I'm going to go ahead and get rid of the user stuff we actually don't need that anymore I'll change the label to being something like U you know welcome and we'll call it two SAS or something like that great so now that we've got that we can also get rid of this you know get start editing you can add things in as you see fit right below this stack here I'll go ahead and bring in my public list component here we'll take a look at what that ends up doing I'll get rid of the session State stuff or actually commented out for the moment and then we'll go ahead and take a look and what happens with this welcome to SAS page it should now render out those different components but it's not now of course the reason it's not rendering out those components is because they're never loaded so there's a bunch of different ways and how we can think about loading them one of the ways was what we did with all of our other Pages we've got this onload method here which is actually probably pretty good for our homepage if we're going to go about this route where we actually have some of our items showing up on the homepage itself right so if I come in here and do onload load those articles there then we will actually be able to see some of those articles come in on this homepage cuz now they're being loaded in and they're being loaded in a similar format as before but they're just narrowed down a bit so something that I might want to do then is right underneath here maybe I put a rx. divider and then I do rx. heading again this time the size is going to be a lot smaller and I'll go ahead and say something like recent articles and have that come through with those recent articles and show so this will show me something slightly different here right so now we're getting a little bit closer to maybe what you'd want for a homepage but the idea being that we have these recent articles in here and we should be able to use them um so for some reason they're not actually being loaded just yet but we'll come back to that for in a moment but for now they're loaded right here but of course this recent article is the way it currently works if we look at the state element for loading these posts it's going to load everything that may or may not be what you want to do the other part is the actual component itself well we have some default columns and spacing so I'm actually going to allow for this to be different so we'll go ahead and set an integer here and we'll start it off with just simply three and then spacing being the same also an integer starting off at five then when we actually use the grid we will convert them into to Strings themselves just so that they do come in as a string but then they start as an integer the nice thing about this then is on my main page I can change how I want the columns in here and let's go ahead and say columns equals to one I believe that's what this should be called is columns and so now we've got it as one and so once we go into our homepage we should see a stack of well one column one article great so it's a little bit closer to um even more so what we might want for our recent articles where our original page is still there but of course this actually takes me one step further is going well what actual posts do I want like how do I actually want to monitor these posts so going back into our state element here this is where we can start thinking of doing pagination so if we come in here and add something called a limit and add in the default limit the default number you might want to bring in on your query what you do then is inside of your posts you've got this load posts here you can actually come in and do do limit after the wear Clause to the amount that you would want to limit it to in this case it's going to be uh whatever number I put up here the default that's the default limit we could also do something like Define set limit and reload which is going to be taking in self and then maybe the new limit which of course is an integer and the default I'll go ahead and set it equal to let's say five and now we'll do self. liit equals to the new limit and then self. load posts which will then re-trigger those loading of those posts and then just simply yield so change the limit whatever that default is and then it's going to go ahead and reload so the nice thing about this then is inside of my public list component here I could go ahead and bring in a limit and set the number that I want in here let's go ahead and say one just so we can see that as being a result now what you might think is like oh well then I can just run the state. article uh public state. set limit and reload of that limit right the one that's coming through you might think that that would be how we go about doing it but of course it is not so what we're going to do is instead is we are going to go ahead and add in something like on Mount and now we'll go ahead and do that same idea but the idea then would be taking in the Lambda and then going ahead and running in that set and reload limit which should then update this as we see fit so I'll leave the default in as let's say for instance 100 100 items is way too many but we'll go ahead and put that in there and then on my actual homepage when I do initialize this component I'll use those arguments so that I can set the limit to one and now we'll go ahead and save that and then our homepage should actually update based off of that new limit assuming that I have commas everywhere and sure enough it is if I go into my main articles it's back to the standard limit homepage articles great so now it's showing me exactly what I might want to do when it comes to narrowing down what gets the displayed and where so naturally what I want to do though is I also want to have a you know a different look at my dashboard as in getting rid of this welcome to SAS portion on my dashboard so once again there's a many different ways on how we can think about doing this in my case I'm going to go ahead and do dashboard as a page and mostly real realistically a component just a component so I'm going to call this my dashboard component and it's not going to take in the base page it's just going to return back what I want for my dashboard which will be rx. boox and then I'll give the same sort of minimum height in here I want to get rid of that break point we don't need that so there's going to be my dashboard now with that minimum height maybe a heading like rx. heading and we'll go and say welcome back and size being I don't know two small heading not very big put a comma here great so now with this in mind I can go ahead and then from our actual articles we'll go and do do do articles do list import our article public list component right underneath that I'll go and do rx. divider and then the component itself columns being three limit being 20 there we go and let's make sure we've got all of our comments commas in there now that we've got this component here I'm going to go ahead and bring it into full stack python so back into um we got off to Pages no we want to go ahead and grab our Pages I'll go ahead and import it just like the other ones so we go ahead and do from. dashboard import the dashboard component and there we go back into full stack python here we will go ahead into the index and just change this child element based off of the state itself so once again we will go ahead and do rx. condition and this is going to be whether or not the user is logged in which is why we've got this authen icated user info here we'll go ahead and bring that in as our primary condition and if it's not we'll go ahead and do pages. dashboard component just like that and let's see for instance we need to close off the parentheses there there we go and so now our homepage let's go ahead and make sure that everything is working now it's all compiled up we refresh into our dashboard here this is not giving us the correct value so let's go ahead and see uh is authenticated so go ahead and change this to the opposite of that so if they are authenticated then we'll show that dashboard otherwise we will not get rid of that there we go and we'll refresh this and we'll see what's going on in a moment I will change this back to being the landing page there we go we've got our welcome back in here and so going back into maybe our uh dashboard element here perhaps we want to add in some spacing here let's go into the box we notice that it doesn't look like there's a whole lot for simply spacing on the box so all I'm going to go ahead and do is I'll add in the margin in here as margin top being 1 M and then margin and bottom being 1 M and there we go so that should actually update that dashboard component so with this same thing in mind we go ahead and do our landing dopy and this will now be our Landing component same sort of idea that we already were doing with this child element here so I'll actually copy basically that whole child element in here and that's what we'll use instead so instead of the child element here we'll go a and do that same uh about us we still might want that so we'll go a and do from dot dot navigation or rather from do do import navigation there we go so now we've got those rout there Landing components let's go ahead and do the same thing so from Landing import The Landing component and there we go so bring this in here back into full stack python now it's just Pages dashboard component and Pages Landing component no need for that child element any longer so we can get rid of that all together there we go and we can also get rid of this State I don't think I use it anywhere uh because it's just not necessary any longer and now that index page is a lot cleaner in terms of how we might want this to look for both our landing page and our dashboard page there's our dashboard page there granted we could always improve what this looks like over time I do recommend going through various things on the documentation inside of the components inside of layout just play around with it as you see fit um but what we've got here is now this welcome hello world here our dashboard is now closer to what a dashboard might be granted it's just the Articles at this point so we can always improve it and add different elements and we can move around components as we see fit the landing page now looks like this and once again we could improve that as well by adding different components as we see fit as well as a final step we want to take a look at colors and theming colors can be applied to individual elements theming is more Global as we'll see in just a moment so the idea is jumping into the reflex docs under learn you can go into styling and theming this is a quick way to do the theming that you might want on your entire project we'll come back to that in just a moment but we can also look at the radx themes so rad itself we can actually take a look at radx UI jumping into the different colors and here's all of the different colors you can use out of the box so that's actually what we want to take a look at what I'm going to start with is this tomato color we'll do tomato 10 this tomato 10 is going to take place of this blue button that's here now not surprising we'll be able to find that blue button which is probably this blue right here at Blue 10 or you know Blue 11 something like that uh but there's obviously other choices that you could have in here as well but I want to do tomato and we'll do it at 10 so how do we actually change that button's color first off all we need to do is we need to go into our Landing component where the button exists which is right here so the quick way to change the color is to do something called a color scheme and I change it to Tomato once I do that color scheme it will change this element to fit with what it should be at that color of the color scheme of tomato right and so we should see it after everything works through as far as the reflex compiling and there we go so we got a new color in here but maybe that's not the color we want maybe we want to go for something a little bit darker and that's where in the rad colors we have this is probably fitting in maybe nine maybe 10 let's put it into 12 let's make it that color that deep of a color the way we do this then is not color scheme but rather doing something like BG equals to rx. color and then the actual color that we want which again was tomato so tomato and it even gives us a bunch of these options in here right so we can use tomato we can use red can all these options in here then we can set the value the shade value we want in our case we said 12 so this going to be the darkest shade in this case and then I also don't want an alpha so I'll go ahead and just say false as in I don't want it to be transparent at all and so that will also change that color and it changes it based off of the alpha whether or not that's true or false the number that we're using and of course the color name and those are coming from radics so we did 12 that's exactly what it looks like now if I wanted to hover over it and have it change well we have a little bit of a challenge and that of course means that we need to put in style here and inside of style we'll do underscore hover and then we will put another dictionary in there for the background itself so once again we'll go ahead and do BG this time to you know hover we'll go ahead and change it to Tomato four we'll go ahead and save that and then we refresh in here and of course what we'll see is as soon as I have it all compiled when I hover over it it changes pretty dramatically now granted we could also change the cursor we already saw that so cursor to being pointer and it gets a little bit closer to the original theme of the button um but of course we could do this with any of our buttons now and this about us this should maybe want to be our primary button but maybe not but in this case this is this is a pretty good sign as to what we can start with now there's another part about this and that is the colors related to the mode that we're in so if you remember back we had the actual dark mode uh so if we do a quick search for our dark mode here look at that sidebar and then we see this color mode condition here for the different colors so this is another thing that we could bring in to the color itself so inside of the background here we would come in and we would give a different color for each mode so RX color mode just like that and so for maybe light we have it as a super dark tomato which is a funny term uh and then in the dark mode maybe we have it a little bit lighter something more like eight and of course we could take that same concept and put it into this background color as well uh so if we toggle in here we can see the different colors changing differently so you could spend a lot of time on how you might want to style this out based off of your button what I'm going to do though is I'm actually going to change this to being a accent we'll go back to being the color scheme and we're going to just go ahead and set it to being gray now the reason for this has to do with what I can do with the entire theme itself so turning it back to being gray it will actually change these to being a gray color but then back into the reflex docks Under The theming Styling we've got this theme here that we can use and we can play around with another thing is if you go into components you can look at a component that is called for our theme panel so we can actually take a look at really modifying the theme itself so first off we'll go ahead and grab that that default theme that comes in or the one that we might want to use and I'll just pass it into my app here so this is going to be how I'll start out with my theme just so I can see what options I do have now vs code is really nice because if you go over any given function it will give you a bunch of argument options in here in the case of the accent color we can see accent colors in there as well but I'm going to leave it as is then I'm going to go ahead and grab this theme panel here I'll go ahead and copy default being open and we're going to go ahead and bring it into our base page and I'll just make sure that that thing is open and then I might need to refresh my compiling and just give it a moment to adjust based off of all of the color and theme changes that you might have so going back into our project here it already changed the color changed to something green right and of course that's coming directly from the component element itself okay so my homepage is not actually showing up part of that is because of this base page here so let's go ahead and just change that a little bit as to where we're going to render that um I'll go back into our main sidebar landing page itself and so let's go ahead and grab the landing component and I'll bring in this here so not logged in to mess around with a theme you could always do it in your dashboard over there as well so with it not logged in we do see this gray in here so I can actually change the gray color as well uh although this one is not changing a whole lot but it is changing subtly it's hard to tell uh on the video probably but it is changing subtly so there are other ways to change that gray color but also we can see all of the different themes in here that we might want to use for this we can also change the radius the default radius we can change the default scaling we can change the background whether or not it's translucent or solid I don't think that makes a big impact on the way we have our background um but we can see the appearance we can do all sorts of stuff with the theme itself so if you really wanted to change the theme you totally could let's say for instance you wanted it to be this this uh like bluish theme here this is actually very similar to what we've been working off so let's go ahead and do let's do the Jade theme or maybe the sky theme I'm going to goe and copy that one and then I'm going to go back into my full stack python here and I'm going to paste that theme in so what we notice is this is not actually a copy and paste for this theme but rather we just use some of the varying things about this so panel background we can come in here and say panel background this is going to be solid the radius is large what if we want it to be medium let's go ahead and just put in medium here uh the appearance we'll start off with dark mode scaling we'll put it down to uh let's do it to 90% just to see what that looks like and you can obviously play around with this a lot more now go ahead and get rid of that accent color that we had in there make sure that everything has commas and then we'll go ahead and take a look back at our page here um naturally this theme toggle will get rid of at some point but there we go so now it actually has a slightly different look and if I do the scale to 90% um let's get rid of the actual theme panel itself so we can see what it actually looks like without the theme panel uh causing any disruption to what we actually wanted to see for our final theme and so I'll go ahead and let that finish and with that finished we now have a much different look at our entire project in terms of the theme itself we still have the dark mode and all that which is really nice our pricing you know all of these different pages now fit with the original theme or the theme that we were going after um based off of all of the different radx colors that are available as well as that theme panel so this would also have effect on other things other components in here as well so like if you looked at something like this you can use different colors in here that would follow along with those different colors that we have that are available to us all the different radic colors we can definitely use with other components and we can use it in ways that are like pretty intuitive so in terms of the color itself so like um when we take took a look at that button we can actually use the colors on any button any element in the same way that we did before where it was using something like you know this whereas like BG RX color we can use these Style Elements in here throughout any given element or component that we might want if we need to have different colors for any given reason um and also for light mode and dark mode so that would also work on these different charts and all these things that you can just copy and paste and really play around with if you were interested on how this would end up looking on your own page if you were going into graphing if you're doing all sorts of other robust components for your application hey thanks so much for watching hopefully got a lot out of this now of course there's still things that we would want to build into this application to make it a lot more functional for our users but the idea here is now we have a foundation for you to be able to do that now I also recommend that you definitely check out the reflex docs in the gallery in the recipes there's going to be a lot more things that are added to this like look at here's a pricing card one this is something you can Implement now and if you look at the code itself it's very straightforward it's straightforward just like of what we've been doing so far and a lot of this is just copy and paste and just trying to figure out what exactly is going on in here so of course for example if I were to grab this right now this actual pricing card go into my pricing page that's in here and maybe change some of the elements in here for it let's go ahead and just bring it in I'm going to paste it in right above here and I've got my pricing cards right above my pricing page I'm going to go ahead and leave that head the heading in there save that pricing card make sure the reflex updates itself and then then if I go into pricing now after it actually does compile we will see something just like this and this is a great start in terms of our pricing page of course now in this case what we want to think about is really how do we use the documentation and just do copy and pasting based off of everything we've built now that we have off now that we have all of the fundamentals with a database how we can go about using that how we can log in and have very user specific data which is of course all of these things that we ended up doing which I think is really really important for a full stack python application now of course there's still more things to be learned inside of reflex and something else that's really cool is yes you can absolutely use this with other kinds of backends because realistically On Any Given State element the state elements like our state here we can actually do different backend requests we don't have to actually only use our database we don't have to do these sessions we can do a request to Any Given API whether that's something like open AI like to do it you know chat GPT type thing or that's something like your own third party API that you're building with a different kind of back end altogether but at the end of the day the actual front end itself we have a lot of different components to pick from and ones that we can really use in a really robust way so thanks so much for watching my name is Justin Mitchell thanks for reflex for helping bring this project to life both in terms of the tutorial as well as the code itself I think this is a really exciting step forward for so many python Developers that don't necessarily want to learn front and that don't want to spend the time you know figuring out how to do all of these different components in any sort of JavaScript language but rather just copying and pasting a bunch of different python modifying the things that we know well and then going off to the races and hopefully helping our end users do something really really cool thanks again for watching I'll see you next time [Music]