Skip to content

Instantly share code, notes, and snippets.

@brylie
Created January 11, 2024 08:05
Show Gist options
  • Save brylie/c77f144f6b97c6b63658888ff2998b59 to your computer and use it in GitHub Desktop.
Save brylie/c77f144f6b97c6b63658888ff2998b59 to your computer and use it in GitHub Desktop.
Code with Brylie - e45
(...) Hello and welcome to an open source live code hangout. We'll be working on the Jerry Life Caregiving Project today.(...) The code is available on github.com slash Jerry Life.(...) You can see the link below the video here.(...) Let's see if I can move that. I'll turn the link a little bit right here.
(...)
I'll look if there's an issue available.(...) It's kind of a low-hanging fruit.(...) Looks like we've got a duplicate field on the add work form. I can take a look at this
(...)
and as a follow-up issue we might want to at some point at least create a data fake data generator for the work reports.(...) That way our demo project can really show the full potential of the project.(...) So let's take a look.(...) I haven't worked on the work portion of the app for a while.(...) So we might have a little bit of different conventions here.(...) But it looks like we just have a model and a model form.(...) And we're just creating all the fields showing all the fields for the work model. So that means we've got duplicate fields here.(...) I think the idea is that hours should be derived from minutes.(...) Although we might be the other way around.
(...)
We typically display the reports in hours though. I'll have to think about it.(...) But in order to be consistent with the activities app, we're actually collecting the activity reports in minutes.(...) So I'm not sure why I added this. There was a reason for it I'm sure.(...) One of the problems though is having duration minutes and duration hours as fields could lead to inconsistent input. Somebody might accidentally say they had 90 minutes and 2 hours and which value do we use. So really,(...) we have to make a decision here.(...) Well we're already using a positive integer field here.(...) It's not too heavy of a computation to divide by 60 to get the hours.
(...)
So I think I'll move this duration hours to a computed property. And we already have that here in fact. So not sure what happened. Why that
(...)
duration hours field is there. It's all right though. Don't always know why. The key is that we can clean it up.(...) And we'll make the migrations.(...) No change detected. Okay I didn't save. Yeah I was also sidetracked. I need to create a branch.
(...)
This is a very small fix.
(...)
That way I'll keep it focused.
(...)
Migrate that in. Oh I think there was a constraint on there. I see.(...) So you could only.
(...)
Oh I see we were just wanting to make sure it was greater than zero. So we had a constraint there. A constraint there as well as a positive flow. It was a bit redundant. I'm not even sure what was going on.
(...)
So we need to remove that database constraint. We'll migrate that in and we should be good to go. Oh boy.(...) No such call and duration hours. Okay so what I think happened here is my.(...) I basically applied a partial migration
(...)
in my development environment.(...) And I removed the column but then not the database constraint.
(...)
Which is on an unexist call. And then when I tried to move remove the database constraint you couldn't find that call. So what I'll do is I'll just roll back. I'll just delete these two. It's not really necessarily roll back but I'll delete these two migrations and we'll do those all in one migration.(...) I just didn't notice that constraint was there. Now we should be good to go.
(...)
Make the migrations again. Now we have both migrations in a single file.
(...)
And Django can apply that. It's going to apply all the migrations.
(...)
So no biggie.
(...)
All right so everything ran.
(...)
We'll publish this branch.
(...)
Create the pull request.(...) And I think that's about it.
(...)
Closes number 83.
(...)
I'll assign myself.(...) That's usually done in advance so I can signal who's working on this but I'm the only active contributor here.
(...)
And now we should have something popping up over here. Maybe if I refresh. There it is.
(...)
We'll wait for our CI to run.(...) There could be some tests
(...)
that were checking that field, the behavior of that field.
(...)
It's been a little bit of a long day so I don't think I'm going to take anything too heavy today but I will create a GitHub issue.
(...)
I'll just create a simple one.
(...)
(clicking) (clears throat)
(...)
(clicking)
(...)
(clicking) - That should be good. (clears throat) And I'll just give it a couple labels.
(...)
I believe this is a good first issue because we have reference code.(...) I'll link to that.
(...)
But otherwise I will go ahead and consider picking that up.
(...)
We have a management command here.
(...)
It can be refactored, but essentially handles.
(...)
The handler here is just gonna create all the data. It's a bit of a sort of a monolithic function and has multiple levels of abstraction. So that's kind of,(...) it is what it is. It got the job done, but now if we add work data here,
(...)
we have to consider how they would interplay(...) and how to do it efficiently,
(...)
such as using the bulk create method, which was previously the thing was taking like five and 10 minutes to generate all the data for like a thousand homes or a hundred, let's see, probably 10 to 30 homes with up to like a thousand or 5,000 records, activity records per home, something like that, which is not a lot of data considering the scope at which this application has been deployed previously.
(...)
So in the way that was just because the way I'd written the code was inefficient, it was iterating over the things and creating one item at a time. So learn a bit in the process of optimizing that.
(...)
And the key is we need to think in the same terms with the work generation. So it might be nested within here, for example,(...) the same way we did the residencies and we want to do bulk create.(...) So might look something like that.
(...)
Work, bulk create, yeah.
(...)
In fact,(...) I can,
(...)
Oh man, holding shift here.
(...)
Well, it should let me select multiple lines.
(...)
See how it's working.
(...)
Not with that line for some reason.
(...)
Like you can select the whole block, not down to here.(...) One more line, that's the line I want this line, geez.
(...)
Yeah, I got it.
(...)
Weird. Oh yeah, I could have manually edited it as well.
(...)
So it was actually in column nine.
(...)
Column 69.(...) It's like basically line 38 to 60.
(...)
There it goes.
(...)
(soft music) A little bit of context there, a little bit of reference. Not as in depth as our previous issues. Been using tragedy to help me generate a few of these.
(...)
Oh,(...) yeah, it's mine. (laughs)
(...)
So code climate thinks we're good.
(...)
Tests are passing.
(...)
So I'm just gonna go and merge this. This was really a fast pull request. Quick fix.
(...)
Cool.
(...)
Maybe there's another low hanging fruit.
(...)
(clears throat)
(...)
So we do have now a metrics app.
(...)
(soft music)
(...)
Here.
(...)
We'll call it metrics.
(...)
So we know what that's for.
(...)
Well, this seems like a non-trivial thing. It's involving refactoring and some very complicated analytical queries,
(...)
but I'll label it nonetheless. Help wanted and it's kind of like keeping the lights on. It's sort of an enhancement for maintainability.
(...)
HCMX doesn't seem like a good idea to start into right now. I don't have a clear use case for it, but (soft music)
(...)
we might have some views where we want partial templates to swap based on user input or like selecting a button, something like that.
(...)
This dark light mode toggle.
(...)
It's been dormant for a while. Let me just leave it for a minute.
(...)
Create fake work dude. IBM Carbon Design System.
(...)
This might not be feasible.
(...)
And I'm just like really tired. I'm not in a sort of mindset to dig into this on the weekend I think. Now I remember the use case and it's basically what we're gonna do is load the resident page right away with some placeholder graphics and use HTML X, HTMX to dynamically request those charts. All the code on the back inside is written. We've already got the chart generating code. Just need to be popped out into what I guess would be their just views,(...) just Django views that return
(...)
chart data or template partials. There's a couple of approaches there, but I would add a baseline just create one view per chart.
(...)
So the URL scheme would be kind of interesting to figure out.
(...)
I think that users are really responsive experience. They'll hop straight into the page
(...)
because the chart loading does take some time and particularly on the resident page. There's some optimizations we need to do. We need to audit those. One thing I can do is add,
(...)
let's do this Django debug tool bar.
(...)
Let's do this.
(...)
(keyboard clicking)
(...)
It would be nice to have it as only a development dependency where that was too complicated the last time I tried that in the Western friend project. So we ended up just sort of jettisoning the debug toolbar. Although I don't think it includes too many of its own dependencies. I think it's relatively clean. So it might just be easy so we can keep around.
(...)
(keyboard clicking)
(...)
It's better redone it. One thing I don't like is that when you have this template on GitHub, if you leave these fields blank, it just pops them in there. It shouldn't do that really. It's kind of a half of baked solution. I think GitHub oftentimes feels like that. It feels half baked to me. If even sometimes a third baked, it's almost raw and not even integrated. They're mixing different flavors in there. They don't go to good together.
(...)
Or they started going one direction and that changed their minds like almost ADHD development or ADD development.
(...)
Which I don't mean to be a jordan about that. Basically I know what ADD feels like firsthand.
(...)
It's literally like I'll start the project and then forget about it and I'll start another project and this and that. So it really had to be disciplined(...) and try to just say what's my one project I'm doing.
(...)
Right now it's Caregiving, JLF Caregiving. For like five years we were developing the Western Friend app and I made the mistake a couple times during that period of starting other projects at the same time. So I literally making this mistake in recent memory.(...) And it delayed our timeline. We probably could have launched a website sooner but at the same time, well it is what it is and I learned from these other projects as well and they were in with Django. So I thought it was kind of like stacking functions. There was some interplay between them. Or lessons I learned there. Might have helped the Western Friend project. Same with JLF. This is why we're really just, I'm going all in on Django across these projects. So anyway,(...) let's take this task. Boom, there we go. Ready,(...) ready.
(...)
Close out, clean the workspace.
(...)
And this will be it. I'll just try one more.
(...)
Little PR this evening and go and relax for a while. Installation.
(...)
Now,(...) I mean remember in this project, we're not using poetry but we are using PyProject but we're not defining our dependencies and I really would like to define dependencies in here with pip but unfortunately, it doesn't work. So I'm really going sort of primitive mode, just regular pip,(...) regular,
(...)
no nothing else, just pip in Python.
(...)
Now I do have this devpy that sort of like gives us a couple of things. It's like a makefile basically. It's like a Python makefile where you define commands but they're actually just in Python. These are shell commands basically
(...)
but the definition is here in a Python struct.(...) Kind of nice.
(...)
I'm not opposed to makefiles
(...)
but since we got Python and ostensibly, all these commands would be run from in the Python environment. Some of them could potentially run(...) from the operating system Python environment
(...)
but this is not probably a good idea but so here's what we're gonna do.
(...)
I could give myself an alias for adding a dependency. We're gonna pip add this.
(...)
Which is kind of leading me back to seeing what I thought I was defining the dependencies here but no,(...) that didn't quite work did it?
(...)
We do have dev requirements.
(...)
So this actually might be not so useful right now.
(...)
(soft music) Yeah, and see just copy and paste code.
(...)
(soft music) We should definitely remove them.
(...)
(soft music) So one problem is this primitive way of doing it is like it's very manual.
(...)
(soft music)
(...)
(keyboard clacking)
(...)
And I can't distinguish
(...)
my dev requirements from my (soft music)
(...)
production requirements.
(...)
All right, well, I'll read this later but I just poetry started to become just as much of a pain, if not more than it was but the benefit in the project in terms of getting new contributors on and sometimes a little bit of like
(...)
friction in the poetry community
(...)
by the maintainers shown towards like hostility almost towards the towards people who are
(...)
requesting features not myself but things that I actually, bugs that I bumped into are features that I would have perhaps requested but other people were also needing that. So I would like to find a really simple way of just managing Python dependencies with just pip(...) and pip tools is the closest I found to that. I'm not gonna go off too much further in that direction today. So we'll say install.
(...)
And basically coverage is, we're needing to use that as part of the dev dependency but again, I can't separate those out.
(...)
(soft music)
(...)
I might develop this dev.py into something more meaningful and then I can say, perhaps have a function here to add a dependency and
(...)
add it to the dev or requirements dev or requirements text at the end and then sort them.
(...)
Just text editing, so get the dependency name,
(...)
a version and add that and anyway.
(...)
So basically building my own poetry in a way. For very simple need though, just managing dependencies for a project. That's what I learned is like, poetry's main use cases for people who are publishing libraries
(...)
and we're building an application.
(...)
So it turned out that some of the design decisions that went into poetry don't support application builders.
(...)
Hence a little bit of friction in the community.
(...)
So now we've got it installed.
(...)
Static files, so we'll go to our core settings,
(...)
installed apps,
(...)
Django, Contrib,(...) static files is there.
(...)
And we've got a static URL. URL,(...) show enough we do.
(...)
Then ensure our template setting contains a Django templates backend.
(...)
Sounds good, looks like it, looks like we do.
(...)
Aptirs is set to true and we've got an extra thing here for our, this is an interesting decision, but I'll go with it. Actually I could move it, since common is an app, I could move that templates here to common templates.
(...)
Then I don't need anything here. (keyboard clicking)
(...)
We should still, our base template should still run.
(...)
Yeah,(...) so that's a little minor cleanup while I'm here.
(...)
So all I did here is just, (keyboard clicking)
(...)
reorganize.
(...)
You know,(...) especially since I'm the only contributor here, but I'm gonna just clean that stuff up as I work. But even in my day job, I will try to make little improvements when I see them, but I understand the distinction and the importance of separating out sort of with large pull requests separating out like formatting changes versus refactoring changes versus adding dependencies, I kinda get it. We do practice that.
(...)
But it's not some kind of discipline I need to enforce on myself at this point.
(...)
So debug toolbar.
(...)
Add the URLs.
(...)
And these can go in our core,(...) URLs.
(...)
We already have path imported and it can kinda go,
(...)
here I suppose is not super important, but I think I can put a comma there and a little better. Formatting so I can vertically scan these and see what's going on.
(...)
See what's going on there too.
(...)
I think that's just a long line.
(...)
So that's kind of why, especially since I'm usually live coding, but even reviewing on GitHub, I kinda wanna have short columns and I know it's not a,(...) this is less than 80 columns, I kind of like this.
(...)
So we add debug URLs to middleware now.
(...)
Back in our settings.
(...)
Middleware and the order of middleware is important. You should include the debug toolbar middleware as early as possible in the list, however it must come after any other middleware that encodes the responses context such as gzip.
(...)
All right, encodes the responses context.
(...)
What here encodes security? So look for gzip first, CSRF.
(...)
Session is gonna modify the context.
(...)
locale modifies context.
(...)
CSRF pops that into context.
(...)
Messages go into context. So I think,(...) clickjacking.
(...)
I really don't know, I'll just put it at the end.
(...)
But it says early as possible.
(...)
I don't know if this is a thing chatgbt would know about.
(...)
(soft music) Give it the givens.
(...)
(keyboard keys clacking)
(...)
Given our middleware definition and the following con, it's our statement. The order of middleware is important. You should include the debug toolbar middleware as early as possible in the list. However, it must come after any middleware that encodes
(...)
the responses context. Encoding is different than modifying, I suppose.
(...)
Where should I put the debug toolbar middleware?
(...)
Moved up.
(...)
To correctly position the Django debug toolbar middleware in your middleware list, you need to identify any middleware
(...)
before it encodes the response context. Looking at your current list,(...) none of the specific middlewares are known for encoding responses context content like gzip. Therefore you can place a debug middleware
(...)
as early as possible in the list. Here's how you can adjust it.
(...)
It's at the end.
(...)
All right, well, I get the idea.
(...)
I trust it about 80%.
(...)
I think this part is the part I trust. This part was an error.
(...)
This places the debug after the middleware that does not modify the content, but still as early as possible.
(...)
(keyboard clicking)
(...)
Now just ask for clarification. Shouldn't we replace it before the middleware that does not modify the content encoding? If so, I suppose we could get at the beginning of the list. Yes, you're correct. The Django, the debug toolbar middleware should be placed before any middleware does not modify the content encoding. Since none of the middleware in your list is known to modify the content encoding like gzip would, you can indeed place a debug middleware at the beginning of the list. This position allows it to capture and debug
(...)
as much of the processing pipeline as possible.
(...)
I'm just gonna put this note here.
(...)
(keyboard clicking)
(...)
(keyboard clicking)
(...)
As a friendly reminder and in the link to the end.
(...)
(keyboard clicking)
(...)
That.
(...)
Now we need to configure the internal IPs.
(...)
We're doing good.
(...)
Oh, that's here. (keyboard clicking) So internal IPs is not defined. I'll put it up near the CSRF and the loud hosts.
(...)
Sort of like that. And I'll put it pretty early near the debug in fact.
(...)
And from what I know,
(...)
it's an IP so it won't be like local host, what I understand.
(...)
You can change the logic determining whether or not the debug toolbar should be shown with the show toolbar callback option. If debug warning if using Docker the following, we'll see your internal IPs correctly in debug mode.
(...)
All right, so I think we're actually good to go. However,
(...)
(keyboard clicking) I didn't see anything about debug is true. So maybe it's just doing that for me now. Let's see if it appears. There it is.
(...)
And if I just manually,
(...)
specify debug as false.
(...)
(keyboard clicking)
(...)
So yeah, there's that.
(...)
(keyboard clicking)
(...)
Hmm.
(...)
(keyboard clicking)
(...)
Maybe there's the environment variable set.
(...)
Yeah, that fixed it. All right, so we're good to go.
(...)
That's it, debug two bars installed.
(...)
And it's not too invasive. Now what I'm gonna do is just,
(...)
make some fake data,(...) create a super user,
(...)
take a quick look, see how fast that was? That was really fast.
(...)
(keyboard clicking)
(...)
I think we'll need a custom user model because I don't believe we're gonna be using the username fields. So I'll just create a list for that.
(...)
(keyboard clicking)
(...)
(keyboard clicking)
(...)
It's mainly a note to self, but I will
(...)
label it. And that's a good first issue help one. And I think it's relatively simple.
(...)
All right, so whoa.
(...)
Now that we've got some fake data in the super user,
(...)
I can like go to the homes page
(...)
after the server is running.
(...)
And login.
(...)
So now we have a home page with some data on there. I think I can start to get to know this.
(...)
SQL 27 queries quite a lot.
(...)
(soft music) And part of the problem is our data model.
(...)
So essentially it's a relational data model. It's not an analytical data model.
(...)
It's a semi analytical data model.
(...)
But nonetheless is fairly performant.
(...)
Here's a little bit slower. So we're loading the page. There's some optimizations we'll need to do here. Multiple queries. And this is where I think an initial step is just switching to H2MX. And sort of lazy loading these charts in. That'll be the first optimization.
(...)
I don't wanna, I kinda wanna stick with SQLite as long as I can. And even in this Postgres,
(...)
I don't wanna go to an old app database or some kind of really complicated requirement and kind of keeping data models in sync and all that stuff.
(...)
So I wanna keep things really simple as long as I can in the development environment and in our production environment.
(...)
The latency is not horrible. We're not suffering.(...) And when we do have severe problems, we'll know more acutely where the problem resides.
(...)
Then we can look at specific answers. But here we have 42 queries that power this page.
(...)
Some of them are kind of slow. So there's an opportunity.
(...)
Just checking out what else is here. So it takes about two and a half seconds to load this page.
(...)
I forgot to add that button there.
(...)
Just gonna fix that right now. Just while I'm here. Such a small bug. I'm just gonna fix it.
(...)
So basically on the home page, I have residence. We need a button here to view the residence.
(...)
Essentially if you click anywhere in that row, it should more or less take you to that resident page. So home template,(...) home detail has a table here.
(...)
So we have a little chart up there and in here our current residence.
(...)
And we have the name column. Let's name call them.
(...)
(typing) Let me think here for a little bit longer. Okay, so.
(...)
(typing)
(...)
So there's just a column here. This is the column header so of course.
(...)
This is a TH and not a TR.
(...)
So that's gonna mess up our table a little bit but there we are. We just shove everything over there, no problem.
(...)
Open our TD button.
(...)
A-A-H-F. There's a new resident URL, yeah, I didn't buy it.
(...)
Let's see what that looks like even.
(...)
Wow.
(...)
Got it right.
(...)
Now this page is slower. That's what I was trying to illustrate.
(...)
Well, almost three seconds. So it's not unbearably slow but again, if we just present the empty page really fast, Django can render that. And then in this area where the chart renders, there will be an HTML call back.
(...)
I think I would like this to be a bootstrap button if it's not too much. (keyboard clicking)
(...)
It's exactly what I was doing, but in small outline primary.
(...)
I guess it's all at the same.
(...)
There's a little wrapping. (soft music) This is not a non-breaking space so that space can break and wrap to another line.
(...)
(soft music)
(...)
(keyboard clicking)
(...)
And we don't actually collect the whole last name, just the last initial for privacy reasons. All right, so that cleaned that up a bit.
(...)
Not bad, not bad.
(...)
(soft music) (keyboard clicking) And if I stretch this link, it'll only stretch to that table cell so it's not really that useful. All right.
(...)
(keyboard clicking)
(...)
So yeah, mixing a few things into the same commit, but in the same pull request.
(...)
But not every change needs a whole git issue to track.
(...)
Essentially it will say configure finger debug toolbar.
(...)
That was a pretty good one.
(...)
So yeah, just testing some stuff out, testing out a new layout on the stream.(...) And when we get some chatters in here, it'll make more sense.
(...)
Then I have room now at the bottom of the stream to place some interesting things. I don't know what.
(...)
It looks like we have a background video.
(...)
(soft music)
(...)
(keyboard clicking)
(...)
There we go.
(...)
Little things.
(...)
Got some nice music in the background, GitHub link.(...) I'll put a little GitHub logo and maybe a solid background in it or the text so it doesn't get, it's not hard to read.
(...)
Cool, let's publish the branch.
(...)
And what am I working on?
(...)
I don't even remember.
(...)
Change, I mean, which issue?
(...)
Debug toolbar, assign to myself.
(...)
Okay, create pull request number 93.
(...)
(keyboard clicking)
(...)
So that's basically it, day in the life.
(...)
Open source,(...) development.
(...)
So now it should appear over here without refreshing, but somehow GitHub's not working right there. Wait for the CI run, this is a new edition and I don't have any unit tests on the home residence table layout. So nothing will be detected here by our test runners.
(...)
(keyboard clicking) I don't suspect the middleware would interfere with any of our other tests, but it can't hurt to let this run all the way through.
(...)
So yeah, one hour session, not bad, not bad.
(...)
Couple of pull requests,(...) couple issues open.
(...)
A little help from tragedy T.
(...)
I'll go ahead and merge this off stream. So, do you have to wait and watch this little yellow dot?
(...)
This has been another open source live code hangout.(...) If you'd like to check out the project in progress, you can stop by github.com slash Jerry life slash caregiving.
(...)
There we go, we got our green CI pipeline.
(...)
And we have been adding issues, some of them fairly good first issues with either code that you can kind of copy and paste and work with, or maybe they're fairly conventional and don't require much knowledge about how our project works, they're just regular Django things.
(...)
Yeah, so check it out on github.
(...)
Have a great day and hope you're doing well. See ya.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment