Working With django-htmx - Building SaaS with Python and Django #119

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi welcome to building sas with python django my name is matt lehmann and on this stream we work on a django app and i teach you what i know about django um and i've been doing this for many years so hopefully i can pass on some knowledge to you tonight we're going to be working on a continuation of my homeschool project we're going to integrate django htmx if you haven't heard of htmx before it's a cool little javascript library that lets you do dynamic stuff on your web pages and i have a need for it on my project so we're going to go through the process of integrating that tonight to finish off a feature that i've been working on the past few streams before we do that though i want to say thank you to my patrons of rupert andrew dragos patrick eric phillip miguel peter and shiva i appreciate your contributions to help make some of this possible and give me some financial motivation to keep going if you would like to become a patron if you like what you see after watching the stream you can go to patreon.comlayman and support me that way if you're not able to do that you can give me a like or a comment or a thumbs up or whatever follow wherever you're coming from whether that's twitch or youtube and i'm happy to answer any questions that you might have so i would be happy to do that if you're live on the stream you're welcome to ask me anything about python django or web development the process that we do here is that i work on an app but i'm i do take plenty of breaks to answer your questions as you might have them so you can see some development as it's going on for a real application which is what this is it's serving real customers but you also get to ask questions that you might have about web development so let's get into the code shall we the first thing that we need to do is add django htmx and so why am i doing this i was working on a feature and i guess maybe makes sense to remind people of what's going on and that feature is a bulk deletion page so if we come over to this page and we come over here and the vast majority of this actual page is complete with the exception of one thing and let's go so let's go to the app and go to where this feature is so we've got this feature we've been working on and it's the ability to delete a bunch of tasks at once so here's all of our tasks and we have this possibility to come into where um my brain is not remembering stuff um well what's going on brain let me check my issue list am i thinking of the right thing this should be task deletion make it possible to bulk delete test that is the thing we're working on what i'm what i'm looking for and what i'm surprised about is that there should be a button that actually gets you to that ability to do that deletion so where did i put that i would think it would be right here my brain is like not recalling that though that's pretty oh you know what it is ha i had to do some upgrades to my project and i'm on the master branch rather than the actual branch that does this work so we want to switch branches to the bulk delete branch all right that not i'm not crazy i'm just working on some old an older branch and doing it somewhere else so okay let's try this again shall we let's refresh the page hey there it is so this is the button we were hoping to find and you can you click this button um you get this page it's not a very complicated page but the idea is boom boom boom you click some task that you want to delete and then you click this and here's where we're going to like observe the goofy behavior that happens right now and the thing that we're going to try and fix so i'm going to actually just click one because i want a bunch of these to be around but you can get the idea that this would expand to many and i should be able to click this and hit delete and it should take me back to the course page but instead it's not going to do that so i'm going to click delete and you'll see what happens there's a confirmation button we'll click that and boom okay so rather than taking me to the page that i wanted to go to it loaded that entire page into the delete button and gave this funky result with this like red background on that um that's clearly not the desirable behavior so what happened there when we implemented this feature we used htmx and i'll show you the code so we can get a flavor for it and this would be the bulk delete page so there's a bulk delete somewhere in here here it is uh and there should be hx yeah so we're doing a post of this particular page this bulk delete page and you saw the confirmation and so when we click that confirm button it does a post request to the the actual uh web server and that web server processes and does the actual task deletion and what it's doing at the end is it's doing it should be doing a redirect back to the course page and that is actually happening in the code if we go over to the courses views area and look for this bulk delete page which should be down here you can see that it does issue this redirect and i tried to do some stuff here and it wasn't quite working so what's happening is that the redirect is happening at the browser level so htmx doesn't have any time to react to that response so rather than what doing what i intended to do which is to have hdmx do the redirect which is what i was hoping for with this hx redirect property instead the browser is doing the redirect for it and it's loading that and returning a real response and by the time htmx gets it it doesn't know about this redirect stuff because it's already happened and so it's loading that response into the into the spot where it's being called at which is the default behavior of htmlx the reason that that happens is because we're using django's http response redirect which is going to do the standard thing and return [Music] 301 or 302 i never remember the status code for redirects it's one of those two though but what htmx is expecting is a response code of 200 with this response header attached to http header so that's the problem in a nutshell and the way i was solving it i could make this work if i passed in a status code and did all that but it's not a very elegant solution it requires a bunch of fiddling and the nice part is there's a cool package out there that can make this happen for us in an elegant way and that package is django hdmx now django hdmx is kind of a thin layer that wraps on top of django and provides some nice features that you can use when you're using the hdmx library like we are and we're going to add this project to night i have used it on another project before i haven't actually used this redirect feature before so that'll be new but we'll go through this process of adding this and we'll see if there's any actual other stuff in here that we might want to take advantage of because i think there is some goodies in there that i want to start using i just hadn't committed to it yet so first things first we need to go to the requirements file and i use a tool called pip tools and it has a pip compile command so what i need to do to actually install packages for my app it's a two-step process first i need to add the actual package to this requirements.in file and then compile a txt file and then install that so it's some kind of a multi-step process so we'll come over here and we'll say django htmx now i don't know the latest version of htmlx so let's um go it's probably some knowing adam it's probably his release and or his release tag but let's just look at pypi for for reference and get the definitive answer because i want to pin to a specific version of htmlx and here we are the latest version is 1.6.0 now i'm also on the latest version of django and stuff so i know that this is going to have compatibility also atom dutifully tells us that it does so we're supported from django 2 2 to 4-0 and i am on 3-2 i believe so we can say what was the number 160 as the value that we want to put for django htmx and let's stop the web server and we're going to run a pip compile command so pip compile and it's going to take the requirements.in file you can see there and it's going to output this requirements txt file so let's go ahead and do that i don't think that htmlx actually has any dependencies so this might be kind of a boring change output um but never know there might be some pre some surprise in there that i'm not aware of i think it's pretty lightweight package though so what this is doing right now is and the reason i do this to be really clear is i want to capture in the requirements.in file the packages that my application uses directly so we're about to use htmx i want to i want to capture that directly and that's some interesting reordering stuff so that's what the requirements to infile does the requirements.txt file is the whole list of packages in the fancy term it's the transitive closure of all the packages just means all that is fancy speak for is the dependencies that i care about for my my my particular project and all of their dependencies too so a whole tree of dependencies and it all gets flattened into one file in requirements.txt and that's what what matters is that's the thing that we actually want to install the benefit of doing this kind of two-phase approach is you know what packages you have and then you also like compile out to the the stuff you care about and so you get a very repeatable installation process because every package that you want to install and all the packages that come along with it all have their version number pinned so that's really good for making something that's deterministic as as much as can be done in a reasonable manner with python okay so we've got um this change added to the requirements.i i n file it did some weird stuff i was surprised that it moved seemed to move the django to the bottom i don't know why that happened if i my pip version changed uh pip tools that could be and it did some reordering there on different alpha sorting stuff so i don't really understand that part but it didn't materially change it i mean we can look at that diff so let's go ahead and add that to the stage and we also want to do a pip compile and because of some local funky stuff with my ssl set up here i have to do this ld flags don't worry about that part the part to pitch pay attention to is that we're pip installing the requirements files down here so we'll do that and it's going to run through a bunch of stuff and you'll see at the very end the only thing that it added because i ran pip com pip install recently was it installed the django hdmx package which is what we need to do our work tonight okay so we've got those changes made to the actual packaging and now it's time to actually integrate this so let's go to the documentation and look at what it says here so first thing to do is to add django htmlx to the list of installed apps we can go to the settings file and go down to installed apps and i like to sort these alphabetically so we'll put it right here after django extensions so django htmlx that's step one and the other thing that says to do is add this django htmlx middleware the middleware if you go and look at it which i have done it adds an htmx property to the http request which is then useful in your views um so let's do that next now he doesn't really give any his any opinions here on where to put this middleware i'm not sure that it matters very much so let's find a reasonable spot for it generally try and put stuff after the django middleware so all of this django middleware is up here white noise has to be up early and i customized it which is why it's high in that list but usually my third party packages can kind of all go together which i do here and then i've got these two custom middlewares that i've written and then there's this rollbar middleware which i think they recommend to put at the bottom so i think what i want to do is put the middleware kind of right in the middle of the stack here because that's as good a spot as any and to continue with the sorting here let's just put it as django htmlx i don't know that the position really matters too much in this particular with this particular piece of middleware but that's my thought process as we're walking through this so we've now have the actual middleware and um we have the installed app and i think that's it for what to do for the basic setup now there's a bit of extra stuff that we can do which i'm going to do because i actually want to um one thing that adam added with this and i keep saying adam so this is adam chains he's a i believe he's a django core django developer he's on the technical board and his name is adam johnson he just goes by happens to go by adam chandler here on github so kind of think of his name in two ways in my head one of the things that adam added to this package is this django htmx script and i believe what it does is like if there's a problem and you're in debug mode and you have a problem with htmlx like a view that is rendering with htmx if you think about the way htmlx works it's doing an ajax request and that ajax request is going to do some kind of operation and try and render some html now the problem with this method is that if there's a problem with your your page with your view normally you'd want to see the django debug page if you have debug mode on you get all of the detailed information from the debug page but with an ajax request that's not necessarily guaranteed to happen so i think what the htmx script does here is it intercepts those responses in debug mode and takes them out of the ajax request and kind of splats them up onto the actual page so you can actually read the debug output so we'll actually play with this and see if it works that way i want to make sure i understand it myself i've not used it but i believe that's how it's going to work and we're going to add that to to the base template so let's actually do that now and let's try and try and break the behavior so we can kind of confirm that it's going to behave that way so first thing let's do let's start up the the web server and we'll return back to our page over here and we'll give this page a refresh so it doesn't have that funky button that number eight that we just had is now gone so we can tell that the task deletion code is actually working it's just the the actual response handling is not correct and we can go into the view which was uh where was that that would be in this file and what i want to do is during this post right here i'm going to just do make it blow up i'm going to raise an exception on is valid we'll raise an exception and we'll just say boom so this is just going to trigger this behavior um and it's actually even before the task deletion so we're not actually even going to delete any tasks which is good because i don't want to be deleting stuff as side effects of of our poking around here so it should have reloaded and it did it's got this line here that says that the file was modified so it reloaded the worker which is what we want to have happen and then we can come into well before we do that let's bring up the inspector and let's click on one of these tasks and go ahead and hit delete and it's going to confirm now what's going to happen what should happen is there shouldn't be any change to the page you shouldn't load anything in the delete button because or it actually might well we'll see let's see what happens nope okay cool this is the behavior i was hoping that would happen so we can have a real test to see if this little script utility works the way the way it's advertised um the thing that we have is is here's the 500 response and you can see because xhr means ajax it means x what is it xmlhttprequest is the original name of this that was a microsoft technology that's a bit of trivia for you um but when you look at this and get down into it we can look at the response and oh here is our django debug page the thing that we'd want to see displayed up here but instead it's it's locked away in this ajax request so i could you know with some network tools i could clearly get into this but that's really inconvenient it's kind of annoying so this is what adam's little script extension is supposed to do with any luck it will show up here the next time we do this so let's go into the base template and we're going to load django htmlx tags i believe was what it said it was called oh just django hdmx we'll add that to the list of things to load here okay and we can close the settings over here so now we've got the new tags library is available it's loaded for this page and then we can go down to the bottom where i have htmx a script tag here i think what i want to do i don't know if he really talks too much about the placement [Music] no all right i think what it needs to happen is it needs to go right after this i don't i don't know the order strictly matters but it's sensible to load htmlx before loading this other script so let's try that we've got these two modifications and now with any luck if we refresh the page um actually well let's go through the whole exercise here and see what this does to the actual source code so here's the source of the page now and you can see at the bottom yeah there it is he's got this um static django hdmx little script here um i i bet that that tag will render nothing if it is on a non-debug view actually a little interesting little exercise let's go check it out see if we can figure that out so this is a template tag it's in django hdmx um he's got the oh interesting it's over in jinja yep there we go cool so if you're if you're in debug mode or if you're not if you're not in debug mode it should render nothing because you don't want this little extra uh script in there so it's only a debug functionality so it's behaving as we would like it to and now we're in a position to try it again so we've confirmed that it's on this page and if i do this a second time and click this with any lock it will actually render hey cool it renders right in the page so it is taking this content out of the out of the xhr the ajax request and put it right in a place that we where we can actually see it and it's telling us that it's the exception of boom which is cool i'm really thankful for that little piece of debugging help that we get let's go back to the course page and delete this exception we're done done checking that out i think we're actually ready to try this stuff out now so what else is in this package that we should know about if we come down the documentation i don't think there's a separate documentation page i think it's such a small package that it's all in this singular readme maybe that'll change at some point in the future but as of today that's the case and we just did the extension script so we're actually down into what do we care about um you can see that the middleware adds this http htmx property so that property is is essentially a boolean it behaves like a bullying does some other stuff too i think but when you use it like a boolean it tells you if it's if the request is made with htmx or not so you can change the behavior in your view if you want to and in fact he's got an example here do a partial versus a complete render and he's got some other attributes here for different kinds of behavior that you can add but what i was really after with this whole entire change is this line right here i believe the http response client redirect that's the big difference is that um htmx is a javascript package that is on the client it's in the browser and so we're asking the client to do the redirect and the client has the ability to do that with the the window attribute i think it's like window.href or something like that and set the status code appropriately which causes the page to refresh which is what we're trying the effect we're trying to get so what we want to do is import this read this response redirect and use that instead of the current redirect that i'm using i want to make sure just looking to this list and seeing if there's any other stuff in here that i care about i don't think so i think there are there are other features but i don't think that we need them for tonight so if you're looking for this package here's a link that you can go reference later alright so what are we doing here we now have the package available to us it's totally loaded it's an installed app i think it's time to replace this and i think it behaves just like any other http response so we want this and we'll put this under [Music] django right here it's not used yet so my linter is complaining and we'll go back to the bulk delete page and i think what we can do i don't think we need to do any of this business anymore i think we can just go straight for the thing we care about which is to say we're going to do a return of the http response client redirect on that and it's too long there we go so re redid that you know what because it did that let's let's actually pull it out into a local variable that way it'll make it down in two lines okay all right so that gets rid of that to do and i so i think what that should do is this that should give us the right behavior that we expect let's check it out all right we're going to the delete page um we can make this a little smaller and let's try deleting lesson nine here now hopefully with any luck the client side redirect will kick in and the delete will actually take us back to the course page after we confirm hey look at that that's so slick we're right back here lesson nine is now gone so we did what we wanted to um that's an interesting message here cookies has been rejected because it already expired i don't understand what that means and we deleted that one task okay so there is one other one here that we want and we want to replace this as well this one is a more of a it's the other error condition which really should only ever happen if somebody is monkeyed with the actual http request but we'll have it for completeness all right so now that we've done that let's actually go back to the course views file the test views file and run all the tests because there's a possibility that i did a i did a 302 check that's going to fail because it now with this response code what it's actually doing is the secret behind it is it's doing a um a 200 response but it's using this extra hx redirect header and i wasn't paying attention to the test test that failed so let's rerun that one more time it's too quick on hitting enter all right test error redirect that's pretty cool to test bulk go to the delete and we should be able to go we're done with this little chunk of code for now and we need to check the redirect is there more than one failing here so this definitely should fail that's one of them but there were two what was the other one worry about one thing at a time so we're going to say that this is actually going to be a 200 response and instead of checking the location header what we instead want to do is check the hx redirect header that's what we're looking for instead cool so that test passes so this is kind of the test is now signaling to me in the future that this is using a client redirect and not a standard redirect um this delete i think is probably the other failing test yeah okay actually so i guess what we're really doing is testing both of those things that i just changed both of those returns this delete is actually the is valid case and this error redirect is for that case when again when somebody is like monkeyed with the post data so the case that should never happen so i'm actually testing paths that are unlikely to ever be touched in real life but just had them for the sake of completeness so we want to change this to a 200 and we want to change this to hx redirect re-direct there we go and now if we run the whole views file again we should have behavior that we want excellent okay let's go back to the issue itself and see if i've kind of cleared up things now so we have a button to bulk delete that was on the course page you saw me navigate to it as i did this process so this is right here delete multiple tasks is not not my favorite name in the world but it is a reasonable name for now and maybe i'll get some feedback later of like hey this could be simply named delete tasks um i don't know if that has enough meaning by itself but i'll just leave it as is for now it's it's fine the way it is at the moment so we have that bit done we have the bulk delete ui page that's this page over here and we have a notice on here we set it up in this format it's pretty simplistic it doesn't look it's not the most elegant page in the world but it's very functional page and the average course is probably going to have more detail than than this kind of thing some of them might actually have be scant on detail like like this and just be numbers but that's not always going to be the case so we have a page it has checkboxes by each task oh i don't have any show linkage to existing coursework or show existing grades i'm going to punt on that part i could could add that in but i don't want to delay getting this feature out that is an additional benefit um and i put this kind of note here saying hey watch out if you delete this stuff you're going to delete any additional records so there are some foreign keys two tasks that are here and those foreign keys are set to cascade so by deleting a task anything that has a foreign key to that task is also going to say i need to delete myself otherwise i'm going to violate the database constraints and be referencing a row that no longer exists in the task table so um we have that covered there we have this cover confirmation alert that's the bit that we just did with htmx to make sure that there's is some kind of notice to users that that change is happening and in the process we integrated django hdmx all right i think there is a little bit more to this feature that we'll probably do this evening and that it might just be a shorter slightly shorter stream tonight but that's that's okay um i think there was another to do here let's take a look so this was 446. so let's look for to do 446. yeah one less one last thing so this was an edge case that i thought of that i wanted to have in there and this actually might be a reason um for handling for this this being something a real scenario that might happen where if somebody submits the page and doesn't delete anything they click no no buttons what happens i think that's a totally reasonable expectation for that to be a real scenario and so we want that to cause some kind of validation um so let's let's do this let's go to the form and make it happen uh so we're done here let's bring up the course forms and i guess we also want we should do this by at this point we can do test driven development on this so let's go to the course and test out this particular chunk of functionality and there's a should be a bulk delete form there it is and what we want looks like there's only one test right now so we want to have a scenario where there's no data all right so we'll take all of this test as a starting point and we will come down to here and we'll say what test error no tasks a when no tasks are selected inform the user so that's like the behavior that we want to happen out of this the way to check this i think is going to be to delete the data that goes into the form we want the form to be um not valid so this is correct and we want to have a non-field error but it shouldn't be this message this piece is something else we'll say you need to select at least one task okay and then my pi is complaining so let's add a little type annotation there because we don't care what goes in this data and we'll leave the other set up we'll have some actual tasks in there do we well do we care um i don't think we even care about that there doesn't have to be any tasks because this page is not going to be a page that you can reach with unless there are tasks maybe we should leave one um let's leave one delete the other that kind of gives us a representative data set that's what these first three lines are doing we've got the user um but right now this is probably going to fail because it does think it's valid because there's no code in here in that form that is is checking for that condition so what we need to do is come down to the bulk delete form and this is where we need to put the the check so if there are no task ids it doesn't find any tasks this is a scenario we're trying to protect against so if not task ids again this is python so an empty list is going to be falsy and that just means that if it has nothing in it it will evaluate to false and so this is why we can raise we can put this guard in in this way without we don't have to check that r u equals zero so this is generally considered more idiomatic python to just kind of check the uh the list itself rather than the actual count on the list so we can say forms validation error and say you need to select at least one task so that's the actual extra check there see if we got it right cool so there's that and this has been running the background the whole time it's probably not the best way to go to actually i mean it doesn't hurt but it was it was causing reloads every time we were saving that file which is kind of silly so let's do this final bit of checking and reload this page so what what i exp what i predict will happen here what should happen is well let's let's walk through it with the code come back to the course view we're going to have this path we're going to fall into this path down here so the the form is not going to be valid we're going to pull out the error message which is that non-field error and the way i've designed this form is it's always going to have one so i'm pretty confident that i can just index into zero it's going to add a a message to the flash messages area that's the thing that you see at the top and since we're returning and we're doing a client redirect back to this page um and what the effect of is like when it gets redirected back to this page the messages should be in a cookie and they should render so the the user should see the warning that says hey you didn't you didn't select anything but they'll be right back where they started that that's what i expect the behavior to be i guess well while i'm doing this i actually want to do the thing same thing that we did before factor that out into a local variable just because it i think it does i don't really like that hanging um closing parentheses that sometimes black will put on things so this makes this just adds a little bit more semantic meaning here okay so we know that that's the behavior we're going we expect to see so let's let's try it out now so let's pick a like a number uh lucky 13 here hold delete oops actually no that's wrong that's not the that's not testing the behavior we want unchecked unchecked we'll click delete hit ok perfect you need to select at least one task all right so functionally i think this feature is done we've walked through the case where it deletes a task maybe we can do one more test and we can actually try and delete let's delete like a bunch of them to delete all of those so 11 13 15 and 17 should be gone after this 11 13 15 yep all gone so we've walked through and we've done the the happy path of this we've tested the arrow conditions we've got unit test coverage on this in fact we can probably run the test suite now and see that should be a 100 unit test coverage but we should check we've added a new library and made use of that library to do client-side redirects and we talked about why that works so that's all good um from an actual like software as a service perspective like there's you know people will say like if you don't document something it doesn't exist or if you don't do anything um vol warframe i'll get to your question just one second uh if you don't tell people then it doesn't exist so the things that i'm not going to do in the stream because they're they're not very exciting and i found that doing documentation is both really dull on stream and really hard to write well while trying to like communicate verbally with people it for me at least it triggers different parts of my brain and so what i'm going to do after this is i'm going to document the feature in the documentation section of the app and i'm also going to write a quick product blog post that i can notify users of hey there's this new feature available that they can take advantage of so that's that's what will finish off this feature to me uh getting to your question vol what languages do i write i presume you're talking about programming languages um these days i am writing a handful i'm naturally i'm writing python that you see here um i if you call html it's a markup language is that language i don't i wouldn't think so but people are willing to debate me on that because it doesn't have turing completeness most likely definitely css for cascading style sheets i do javascript very typical web stack um outside of that as a side project i've been writing a bunch of lua lately [Music] i think those are the languages that i'm touching at the moment i'm dabbling with go at work i have to look at it for reasons um yeah that's the primary set professionally in my history i've done a lot more than that and i've been i've been kind of all over the board um between microsoft stuff and and uh java enterprise stuff and pearl and dynamic other dynamic scripting languages and then research on more esoteric languages or lesser used languages like erlang to kind of stretch my brain into functional programming and how that works and stuff so um but i haven't touched many of those recently so what have i written code in versus what i'm am i doing these days is pretty different answers but hopefully answered your question there looks like we still have all the tests passing and we've got 100 coverage so i think that's all good whoops i using the chat to type out my terminal commands not what i meant to do so we finished off the to-do's we've got django htmx integrated let's go ahead and add it see if there's any formatting that needs to be done or lint that i mix missed and um let's just say finish off bulk deletion now i think there's going to be a problem let's try it figure it out let's go back to the the main branch and i think this is up to date no it wasn't i had some other things that emerged super all right so let's go back to bulk delete and merge in the main branch yeah i know there's going to be conflicts oh boo boo hoo um okay and it's conflicts and really like an annoying place all right let's sometimes though if you have conflicts let's go fix them up i just want to like show you that the overall experience of writing a feature doesn't stop when the actual code is done like there's not only do i have the other things that i have to do in terms of letting people know about the feature but there's also the cleanup work of getting it merged and into the main branch and to getting it deployed i don't know that we'll actually do deployment tonight that's a it's really just watching something scroll by so that's not very exciting but yeah i just want to have the to have this all in here for completeness so let's take a look at what i got wrong what's happening is i added django hdmx but uh every every month i've i've got depend about configured to update all my packages so some of these packages were updated and django hdmx was added into the mix at the time so i need to deconflict with that and it looks like there's not too much here so django hash field and django hijack were both upgraded then i have django htmx there so let's move that down here and get rid of the the diff so that should clean up that all right now i could try and go through and clean up this generated file with the requirements txt and it doesn't look like it'd be terribly terribly hard but i think what i'd rather do is just run the pip compile tool again and hopefully that will work although it might complain but we shall find out yeah okay it's complaining it doesn't like the conflict markers that are here so i think what i'll do is i'll take this stuff out and i don't know if it's right or not but we'll run try running pip compile again and with any luck it'll wipe out the old requirements txt file and replace it with the new stuff and give me an accurate file this is all done in a branch so what i'm going to do is pull push this up to the code repository as a pull request so we'll be able to review the folder anyway and we'll see if there's any funkiness that i didn't anticipate um so we've got that thing that we fixed and it generated new stuff there and it's on new thing here okay that looks good so that was merging in the main branch so now we should be ready to create the pull request because i don't think i have one um tuna hobby do i separate them i kind of do i don't do them in the way that you're totally saying though i don't use folders so my requirements files for development packages are they are in a separate requirements file and i'm kind of to be honest i'm a little lazy about this i probably should be better to my credit i'm not like building a docker image or something if i was i would absolutely be pinning all of these things but i have my requirements dev stuff which i just sort of layer on top now the uh very observant people might observe that there's a there's a chance that because i don't pin stuff and i don't i'm doing stuff separately that's not in my deploy that you know i could accidentally install something from my development packages and only see this in development and then experience a problem when i go to deploy and that it would be a fair critique i'm trying to remember yeah because i also install my development packages when i'm doing ci work so there is a risk there what i bank on is that i'm aware of that risk always and so i think pretty hard about what i put in here but hopefully that answers your question i have thought about like maybe i should just i'll put it put it all in the same place and have one requirements file because there's nothing about the requirements in file that doesn't say like i think i could use comments and say like hey this is my dev section and this is like the the app section um that's totally doable i just choose not to do that so that's my strategy for doing it i don't even know that it's the best one i'm kind of on the fence about it and i have seen and i work at a place that does it very differently with like a whole requirements directory and using multiple requirements files to split things out and then kind of combining them in interesting ways i think where i stand with the simplicity of this application if you can get away with one or in my case two files i would i would recommend that it works well for me okay looking back at the repository we have um oh you're welcome to navi happy to answer your question uh there's no poll requests here so we need to create a new pull request so we're going to do i have an alias here so that's what gp is it's git push and i'm going to follow this for any changes that i might add and we're going to go to origin which is where the github repository is and we're going to put up bulk delete so that should push the branch here and thankfully i love when git added this github out of this messaging here they give you a really easy place to open and create new pull requests and we're going to do that so let's see add a bulk task delete feature this will fix number 446 fixes 446. create the pull request and got all the commits there which i i do like to after i'm done uh ci hasn't run yet but i like to squash my commits down into a single one so that if um i need to revert the change on my main branch that i get all of that in one go that's kind of an atomic operation there just i'm not i probably won't do the merge here today because i'm also going to add documentation to this pr later but that's that's my process there so you know this is a bunch of this is from previous streams and i don't need to borrow you with all those details in fact if you want to go check this stuff out i think there's actually a notice that is now popping up periodically on my on my stream um but my content's up on youtube it's available if you search for matt lehman you can find all of the streams associated with this project and i don't do everything exclusively on stream so it's not complete of all the code but there is a lot of streams about this content and you can go back and back a couple of them and check out what's going on um but broad strokes we made a form we wrote tests for the form which we wrote one of those tonight we wrote view tests for this view page and checked out these error conditions that we walk through we wrote one of those tonight or corrected one of those tonight added a new url to the urls file and added the new view itself kind of clean things up along the way and let's see did we check we check login required i want to check that really quickly i like to make sure the access control tests are there yep so there's that okay there's both of the access control tests that's what i really care about um so the view looks pretty good to me it's it's very straightforward hopefully you'll agree with me there's not a lot of code here and we added django hdmx so this is a the purist might say that i should have done that separately and then merge that in this is my own project and i'm not much of a purist so i don't really care um curiously i don't i don't know why this happened i don't know why django itself got moved from down up here to down here that i don't really care though i speculate i i know what about it is i bet i need to upgrade my pip tools because i think dependabot from github yeah let's try that let's let's see if i can i want to understand i like to understand things if you can't tell by now um i know it's probably some weird flaw in my character um but if we go back to that requirements dev file one of the things that's in there is pip tools and notice that it's not pinned so i'm just using whatever version that is in this repo which is um five five zero and i bet that on pi pi which we already have up over here that they have a new version out and my guess is that new version changes some ordering on on the requirements it looks like it's on pip tools six four zero so let's do let's upgrade that pip install oh man i don't do a lot of upgrades is it upgrade with a capital u i think that's the way to do it cool we went we installed pip tools six four and got rid of the old one now now let's try and rerun pip compile and see if it will regenerate the order to be to match up with the order that should be there oh yeah look at this um so this is moved back in the top so that's that was the issue i was on that old version let's push that up i i like to what i'm trying to get out of here is like i want the diff to be meaningful i don't want noise in there and if there is noise in the diff of of the branch i want to like understand why why it's in there you know everything about code is understandable as long as you do it are willing to do enough digging which is what we're doing here so let's say fix the order of dependencies to match the pandabot and that's actually going to actually in this case pretty dramatically shrink the dependency changes in that pull request because i'm now syncing it up to what is actually already on the main branch johnston f thanks for thanks for joining in appreciate you being here so we have now pushed up that commit and the requirements text file yeah that's that's way better i still okay there's still this thing that is interesting that dependable doesn't seem to do this it doesn't seem to say with python version blah blah blah okay so it's going to change again when when dependable comes back that's okay i'm okay with a little bit of noise in a diff but really we get down to the core of it which is we added django hdmx that's the big change here that's what we care about then we've got this minor modification to the base template we saw the effect of adding this django hdmx script tonight it's really powerful way to see see your errors if you're using htmlx and we've got the actual here's the button that we added and then the actual bulk delete page which we spent the better part of a stream putting together even though it looks very simplistic so that's the change and i think that's that's a good enough place to to wrap up for the day i hope that you learned a little bit about htmlx this evening thank you for the the questions um happy to stick around for an extra minute if anybody has a question here at the end um i do try and stream every every week when i can except when i'm running my local python meetup which runs the second wednesday of the month but generally i try to be here unless i'm on vacation and we continue to work through this project my next the next thing that we're going to do here so next time if you want to join in the stream is we've got to deal some more bug hunting so there are some scheduling bugs that a couple of customers have surfaced in in weird scenarios and work this is the kind of the sleuthing part of um working with this application but i've said it on previous streams and i'll say it again um the scheduling tool is the core benefit of working with this homeschooling application we haven't really spent much time tonight talking about the domain and that's fine but what is really the big benefit of using this particular tool which is called school desk is that it generates a homeschool schedule automatically for the user and so that automatic part is really important to get right as you might imagine and um users have identified a couple of weird scenarios where it's not quite right so it's close but not quite right which are are some of the trickiest bugs to find um are there any software interns for dod uh good question i think the answer is probably not right now because uh recently doctor on demand so the dod stan isn't the department of defense although it is i used to work for department of defense a long time ago as a contractor but it stands for doctor on demand for those of you that don't know and tuna hobby seems to know where i work which is cool doctor on demand is a telemedicine company and does a lot of django which you've seen here tonight so that's part of why i'm knowledgeable about it i use it at work all the time but we recently merged with another company we merged with a company called grand rounds health and i'm not going to go into what grand rounds health does it's it's more healthcare kind of work it's not telemedicine but it's it's related to um offering services to medical services people online [Music] oh cool yeah glad hopefully doctor demand was a good experience for you um but the company to get back to your earlier question toon hobby the company merged and we just recently announced a new name and that new name is included health um and we have a ton of work to do as we're trying to merge companies together so there is definitely opportunity there's tons of growth that's happening uh i don't know that our recruiters are quite in shape for interns right now though so i suspect that come this summer we will probably be on on the lookout for interns but at this stage at this time um i don't think that's available um if you want to message me on twitter uh and send me an app message and contact me that way i could probably find out for you from from our hr team directly but my speculation is it's just not right now um good question though appreciate that so we're we're going to work on scheduling bugs next time and if we we'll we'll see how how it goes i i'm knowing these bugs and knowing the characteristic of them will probably spend the whole stream on it because these are these are tricky to track down and then the act of writing the unit test to prove the failure is a whole other category of problem um and then actually doing the fixes is another third thing to to do so there's a lot that goes into finding these um these very nitty-gritty bugs but they're important to track down since again this is the core part part of product um thank you for all for joining in this evening i i hope you have a great evening and i wish you well again if you want to uh catch this later catch streams go to youtube check that out if you can give me a follow here on twitch i think that's the right word and if you catch this on on youtube like subscribe all that stuff would greatly appreciate that and with that i will bid you all good evening take care bye you
Info
Channel: Matt Layman
Views: 613
Rating: undefined out of 5
Keywords: twitch, Python, Django, SaaS, htmx, django-htmx
Id: PKL9bIjKbl4
Channel Id: undefined
Length: 60min 32sec (3632 seconds)
Published: Thu Nov 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.