WEBVTT

1
00:00:00.120 --> 00:00:03.000
<v Speaker 1>You know it is wild to think about, but uh,

2
00:00:03.520 --> 00:00:06.240
<v Speaker 1>every time you open up Instagram on your phone, oh yeah,

3
00:00:06.280 --> 00:00:08.800
<v Speaker 1>like every single time you scroll through that endless feed

4
00:00:08.880 --> 00:00:11.560
<v Speaker 1>or double tap a photo or watch a story, you

5
00:00:11.679 --> 00:00:15.080
<v Speaker 1>are interacting with the largest Djengo website on the planet.

6
00:00:15.199 --> 00:00:17.199
<v Speaker 2>It really is staggering when you think about.

7
00:00:16.960 --> 00:00:21.480
<v Speaker 1>It, right, millions of requests, just unbelievable amounts of data

8
00:00:21.920 --> 00:00:24.440
<v Speaker 1>and it's all being handled by the exact same web

9
00:00:24.480 --> 00:00:27.000
<v Speaker 1>framework you can you know, install on your laptop in

10
00:00:27.039 --> 00:00:28.399
<v Speaker 1>about five seconds exactly.

11
00:00:28.559 --> 00:00:30.440
<v Speaker 2>Yeah, I mean it really puts things into a different

12
00:00:30.480 --> 00:00:33.240
<v Speaker 2>perspective because we tend to think of Python and Django

13
00:00:33.280 --> 00:00:39.520
<v Speaker 2>as these highly accessible tools, yeah, like starter tools almost right,

14
00:00:39.719 --> 00:00:42.920
<v Speaker 2>great for building a quick blog or a local business directory,

15
00:00:42.960 --> 00:00:46.240
<v Speaker 2>maybe a minimum viable product. But underneath the hood of

16
00:00:46.280 --> 00:00:49.479
<v Speaker 2>one of the most massive, high traffic platforms in the world,

17
00:00:49.759 --> 00:00:53.399
<v Speaker 2>the core architecture relies heavily on Django.

18
00:00:53.200 --> 00:00:56.280
<v Speaker 1>And that completely shatters the illusion that this framework is

19
00:00:56.399 --> 00:00:59.039
<v Speaker 1>just you know, a set of training wheels. Oh absolutely,

20
00:00:59.119 --> 00:01:01.399
<v Speaker 1>but I feel like it all so highlights this massive

21
00:01:01.719 --> 00:01:06.239
<v Speaker 1>intimidating gulf that exists in software development because there is

22
00:01:06.239 --> 00:01:09.760
<v Speaker 1>a universe of difference between quickly hacking together a simple

23
00:01:10.120 --> 00:01:13.319
<v Speaker 1>toy app on your MacBook over a long weekend, and

24
00:01:13.599 --> 00:01:17.400
<v Speaker 1>engineering a robust, production ready web application that can actually

25
00:01:17.480 --> 00:01:17.959
<v Speaker 1>scale up.

26
00:01:18.040 --> 00:01:20.879
<v Speaker 2>Yeah, an app that survives contact with millions of real

27
00:01:20.879 --> 00:01:21.480
<v Speaker 2>world users.

28
00:01:21.560 --> 00:01:24.560
<v Speaker 1>Gay, And that is the crucial pivot every developer has

29
00:01:24.599 --> 00:01:27.760
<v Speaker 1>to make. So bridging that specific gap is what we

30
00:01:27.799 --> 00:01:28.760
<v Speaker 1>are focusing on today.

31
00:01:28.840 --> 00:01:33.200
<v Speaker 2>Yeah, we are pulling the essential pro level blueprints from

32
00:01:33.200 --> 00:01:37.359
<v Speaker 2>a phenomenal resource today. It's called Jango for professionals production

33
00:01:37.439 --> 00:01:40.159
<v Speaker 2>websites with Python and Django by William S Fncent.

34
00:01:40.400 --> 00:01:42.680
<v Speaker 1>It's such a good guide. So whether you are an

35
00:01:42.719 --> 00:01:46.280
<v Speaker 1>aspiring developer hoping to build the next tech Unicorn, or

36
00:01:46.319 --> 00:01:49.079
<v Speaker 1>an engineer catching up on modern web architecture, or.

37
00:01:49.079 --> 00:01:52.280
<v Speaker 2>Honestly just insanely curious about how the Internet actually functions behind.

38
00:01:52.040 --> 00:01:55.120
<v Speaker 1>The scenes, exactly, this deep dive is your shortcut. We

39
00:01:55.159 --> 00:01:58.000
<v Speaker 1>are going to distill what it actually takes to build

40
00:01:58.079 --> 00:02:02.000
<v Speaker 1>professional grade software. So, okay, let's unpack this. Let's do it,

41
00:02:02.120 --> 00:02:05.400
<v Speaker 1>because before we can even think about handling a million users,

42
00:02:05.680 --> 00:02:08.840
<v Speaker 1>we have to start by solving literally the oldest, most

43
00:02:08.840 --> 00:02:11.599
<v Speaker 1>infuriating problem in software development.

44
00:02:11.400 --> 00:02:14.439
<v Speaker 2>Getting your code to run reliably on someone else's computer.

45
00:02:14.879 --> 00:02:18.599
<v Speaker 1>Yes, the infamous it works on my machine syndrome.

46
00:02:19.159 --> 00:02:22.599
<v Speaker 2>It is a classic for a reason. I mean, for decades,

47
00:02:22.639 --> 00:02:27.000
<v Speaker 2>the fundamental struggle was creating a consistent environment. Traditionally, Python

48
00:02:27.039 --> 00:02:30.479
<v Speaker 2>developers use something called a virtual environment. And you know,

49
00:02:30.599 --> 00:02:34.879
<v Speaker 2>while virtual environments are excellent for basic isolation, they have

50
00:02:34.919 --> 00:02:37.759
<v Speaker 2>a fatal flaw when it comes to production grade architecture,

51
00:02:37.800 --> 00:02:41.479
<v Speaker 2>which is they only sandbox your Python packages. Oh, they

52
00:02:41.520 --> 00:02:44.439
<v Speaker 2>do absolutely nothing to isolate the rest of the software

53
00:02:44.439 --> 00:02:46.560
<v Speaker 2>that your application desperately relies on.

54
00:02:46.800 --> 00:02:50.159
<v Speaker 1>So if my app needs like a specific version of

55
00:02:50.240 --> 00:02:54.360
<v Speaker 1>a database, or relies on some background image processing library

56
00:02:54.360 --> 00:02:56.039
<v Speaker 1>that lives at the operating system level.

57
00:02:55.919 --> 00:02:58.000
<v Speaker 2>The Python virtual environment doesn't protect you at all.

58
00:02:58.199 --> 00:03:02.000
<v Speaker 1>It just blindly relies on whatever random system level configuration

59
00:03:02.039 --> 00:03:03.919
<v Speaker 1>I happen to have installed on my personal.

60
00:03:03.639 --> 00:03:06.360
<v Speaker 2>Laptop exactly, and the moment you push that code to

61
00:03:06.400 --> 00:03:09.159
<v Speaker 2>a Linux production server, the whole thing catches fire.

62
00:03:09.240 --> 00:03:13.039
<v Speaker 1>It's a nightmare. So that is the exact point of failure,

63
00:03:13.759 --> 00:03:17.280
<v Speaker 1>which brings us to the industry standard solution, which is Docker.

64
00:03:17.520 --> 00:03:22.639
<v Speaker 2>Right Docker, And to truly understand why Docker revolutionized software engineering,

65
00:03:22.879 --> 00:03:25.319
<v Speaker 2>we really have to compare it to the old brute

66
00:03:25.360 --> 00:03:26.639
<v Speaker 2>force method of isolation.

67
00:03:26.840 --> 00:03:28.560
<v Speaker 1>The virtual machine or VM.

68
00:03:28.639 --> 00:03:32.960
<v Speaker 2>Yeah, the VM, and the author introduces a brilliant analogy here.

69
00:03:33.680 --> 00:03:37.879
<v Speaker 2>Imagine virtual machines as standalone houses. Okay, if you want

70
00:03:37.919 --> 00:03:41.520
<v Speaker 2>to run three different applications securely, you build three completely

71
00:03:41.520 --> 00:03:42.199
<v Speaker 2>separate houses.

72
00:03:42.240 --> 00:03:45.800
<v Speaker 1>Okay, standalone houses, meaning each one has its own completely

73
00:03:45.840 --> 00:03:50.199
<v Speaker 1>redundant plumbing, a separate concrete foundation, taking up a massive

74
00:03:50.199 --> 00:03:51.240
<v Speaker 1>footprint on the server.

75
00:03:51.439 --> 00:03:54.879
<v Speaker 2>Exactly. In computing terms, you're booting up a massive, heavy,

76
00:03:54.919 --> 00:03:57.400
<v Speaker 2>guest operating system for every single app.

77
00:03:57.240 --> 00:04:00.599
<v Speaker 1>Right, which takes massive amounts of memory and CPU resources

78
00:04:00.599 --> 00:04:01.400
<v Speaker 1>just to keep the lights on.

79
00:04:01.560 --> 00:04:05.840
<v Speaker 2>Exactly. But Donker, on the other hand, utilizes Linux containers. Okay,

80
00:04:06.039 --> 00:04:08.080
<v Speaker 2>a Docker container is more like an apartment in a

81
00:04:08.120 --> 00:04:08.879
<v Speaker 2>high rise building.

82
00:04:09.080 --> 00:04:09.280
<v Speaker 1>Oh.

83
00:04:09.319 --> 00:04:12.039
<v Speaker 2>I like that, right. All the apartments share the exact

84
00:04:12.080 --> 00:04:15.719
<v Speaker 2>same underlying foundation and the same central plumbing, which is

85
00:04:15.800 --> 00:04:19.000
<v Speaker 2>the host operating system's kernel. But the inside of the

86
00:04:19.040 --> 00:04:23.360
<v Speaker 2>apartment is perfectly customized and isolated because they share that

87
00:04:23.439 --> 00:04:27.000
<v Speaker 2>underlying foundation rather than duplicating it. Containers start up in

88
00:04:27.040 --> 00:04:30.120
<v Speaker 2>milliseconds and they use a tiny fraction of the memory.

89
00:04:30.319 --> 00:04:33.560
<v Speaker 1>I really love that analogy because it perfectly illustrates the efficiency.

90
00:04:34.040 --> 00:04:36.519
<v Speaker 1>But I have to push back on the workflow here

91
00:04:36.519 --> 00:04:36.759
<v Speaker 1>a bit.

92
00:04:36.759 --> 00:04:36.959
<v Speaker 2>Sure.

93
00:04:37.240 --> 00:04:40.720
<v Speaker 1>If Docker is essentially this sealed off apartment, how do

94
00:04:40.800 --> 00:04:43.240
<v Speaker 1>I actually work on my code? Like? If I have

95
00:04:43.279 --> 00:04:46.720
<v Speaker 1>to move my furniture, meaning rebuild the entire Docker image

96
00:04:46.759 --> 00:04:48.720
<v Speaker 1>from scratch every single time I change a line of

97
00:04:48.800 --> 00:04:51.040
<v Speaker 1>code or fix the typo, I'm never going to use

98
00:04:51.079 --> 00:04:52.040
<v Speaker 1>it for local development.

99
00:04:52.160 --> 00:04:55.120
<v Speaker 2>Oh yeah, now that sounds exhausting and it would be terrible. Yeah,

100
00:04:55.160 --> 00:04:58.000
<v Speaker 2>rebuilding an image takes time, and doing that for every

101
00:04:58.040 --> 00:05:02.600
<v Speaker 2>typo would completely ruin your develop velocity. But the mechanism

102
00:05:02.600 --> 00:05:05.600
<v Speaker 2>that solves this is called a Docker volume. Okay, in

103
00:05:05.639 --> 00:05:09.360
<v Speaker 2>your project, you'll use a Docker dash composed dot imll file.

104
00:05:10.319 --> 00:05:13.399
<v Speaker 2>This isn't just some basic settings file. It's a powerful

105
00:05:13.480 --> 00:05:14.639
<v Speaker 2>orchestration blueprint.

106
00:05:14.759 --> 00:05:16.920
<v Speaker 1>It tells Docker how to build and connect all the

107
00:05:16.920 --> 00:05:18.480
<v Speaker 1>different containers right exactly.

108
00:05:18.720 --> 00:05:22.279
<v Speaker 2>And inside that blueprint you specify a volume mount. And

109
00:05:22.399 --> 00:05:25.000
<v Speaker 2>rather than being some kind of magic, a volume acts

110
00:05:25.160 --> 00:05:28.519
<v Speaker 2>like a two way mirror or like a shared drop

111
00:05:28.560 --> 00:05:31.279
<v Speaker 2>box between your local computer and the container.

112
00:05:31.399 --> 00:05:33.639
<v Speaker 1>Wait, really, so I don't have to ssh into the

113
00:05:33.639 --> 00:05:35.800
<v Speaker 1>container or rebuild the image at all, Not at all.

114
00:05:35.879 --> 00:05:38.680
<v Speaker 1>It's literally just watching the folder on my Mac and

115
00:05:38.720 --> 00:05:41.279
<v Speaker 1>mirroring it inside the Linux container in real time.

116
00:05:41.399 --> 00:05:44.399
<v Speaker 2>That is exactly the mechanism. The container and your host

117
00:05:44.399 --> 00:05:47.560
<v Speaker 2>operating system are simply looking at the exact same physical

118
00:05:47.600 --> 00:05:49.560
<v Speaker 2>sector of your hard drive simultaneously.

119
00:05:49.639 --> 00:05:50.720
<v Speaker 1>That is wild.

120
00:05:50.839 --> 00:05:52.920
<v Speaker 2>So you open your regular code editor on your Mac,

121
00:05:53.040 --> 00:05:55.920
<v Speaker 2>you type print hello, you hit save, and the Python

122
00:05:55.959 --> 00:05:59.920
<v Speaker 2>interpreter running inside that sealed Docker apartment instantly sees that

123
00:06:00.160 --> 00:06:00.959
<v Speaker 2>change in reloads.

124
00:06:01.040 --> 00:06:03.839
<v Speaker 1>Okay, that is incredibly slick. You get the industrial strength

125
00:06:03.920 --> 00:06:06.959
<v Speaker 1>isolation of the container, but the pure convenience of your

126
00:06:07.000 --> 00:06:08.439
<v Speaker 1>local desktop exactly.

127
00:06:08.480 --> 00:06:12.240
<v Speaker 2>And this isolation naturally brings us to how we handle dependencies.

128
00:06:13.040 --> 00:06:16.720
<v Speaker 2>The source material really emphasizes deterministic builds.

129
00:06:16.600 --> 00:06:20.040
<v Speaker 1>Right, deterministic builds, meaning we aren't just using a basic

130
00:06:20.120 --> 00:06:22.480
<v Speaker 1>requirements dot txt file anymore.

131
00:06:22.079 --> 00:06:24.360
<v Speaker 2>Absolutely not. We are stepping up to lock files, yes,

132
00:06:24.439 --> 00:06:27.319
<v Speaker 2>specifically pitfile dot lock in this architecture.

133
00:06:27.519 --> 00:06:30.720
<v Speaker 1>Okay, because a standard requirements file might just say install

134
00:06:30.800 --> 00:06:32.000
<v Speaker 1>this package.

135
00:06:31.519 --> 00:06:35.480
<v Speaker 2>But it completely ignores the dozens of subdependencies that package needs.

136
00:06:35.879 --> 00:06:40.879
<v Speaker 2>A lock file maps out the exact resolved dependency.

137
00:06:40.199 --> 00:06:44.160
<v Speaker 1>Tree, right, pinning down the highly specific version numbers and

138
00:06:44.199 --> 00:06:49.079
<v Speaker 1>cryptographic hashes for every single piece of code your app requires.

139
00:06:49.199 --> 00:06:51.279
<v Speaker 2>Yeah, but the trick the author points out, is that

140
00:06:51.319 --> 00:06:54.800
<v Speaker 2>we have to generate that lock file inside the Docker container,

141
00:06:54.920 --> 00:06:56.319
<v Speaker 2>not on our local machine.

142
00:06:56.360 --> 00:06:59.199
<v Speaker 1>Oh right, Because if I run the install command natively

143
00:06:59.199 --> 00:07:01.879
<v Speaker 1>on my Mac, the lock file gets generated with Mac

144
00:07:01.959 --> 00:07:04.160
<v Speaker 1>specific compiled binaries exactly.

145
00:07:04.519 --> 00:07:07.000
<v Speaker 2>And when you hand that Mac flavored lock file to

146
00:07:07.079 --> 00:07:09.800
<v Speaker 2>your Linux production server, it panics, it crashes.

147
00:07:09.959 --> 00:07:13.639
<v Speaker 1>But by running the installation through Docker, your entire team

148
00:07:13.720 --> 00:07:16.519
<v Speaker 1>is guaranteed to have the exact same Linux based dependency

149
00:07:16.519 --> 00:07:17.480
<v Speaker 1>trade it.

150
00:07:17.399 --> 00:07:20.240
<v Speaker 2>Works on my machine. Excuse is officially eradicated.

151
00:07:20.399 --> 00:07:25.560
<v Speaker 1>Amazing. So we have built a bullet proof containerized environment.

152
00:07:26.240 --> 00:07:29.319
<v Speaker 1>But an application isn't just code, right, it's data.

153
00:07:30.279 --> 00:07:30.720
<v Speaker 2>Very true.

154
00:07:30.759 --> 00:07:33.000
<v Speaker 1>We need to talk about the database because when you

155
00:07:33.079 --> 00:07:37.439
<v Speaker 1>run Django Edmunds Start project, the framework automatically hands you

156
00:07:37.519 --> 00:07:39.639
<v Speaker 1>a Squilight database out of the box.

157
00:07:39.759 --> 00:07:42.759
<v Speaker 2>And Squily is a marvel of software engineering.

158
00:07:42.399 --> 00:07:45.800
<v Speaker 1>It really is. It's incredibly fast, it requires zero configuration,

159
00:07:45.959 --> 00:07:48.160
<v Speaker 1>and it just lives in a single file on your computer.

160
00:07:48.360 --> 00:07:51.360
<v Speaker 2>It's wonderful for prototyping. But and this is a big

161
00:07:51.800 --> 00:07:53.600
<v Speaker 2>it is a massive trap if you are building a

162
00:07:53.600 --> 00:07:54.480
<v Speaker 2>production application.

163
00:07:54.600 --> 00:07:54.920
<v Speaker 1>Oh soo.

164
00:07:55.639 --> 00:08:01.560
<v Speaker 2>Squilight handles simultaneous right request poorly compared to heavy relational databases,

165
00:08:01.959 --> 00:08:04.199
<v Speaker 2>you will rarely, if ever see it use as the

166
00:08:04.199 --> 00:08:06.959
<v Speaker 2>primary data store for eye high traffic web application.

167
00:08:07.240 --> 00:08:10.439
<v Speaker 1>Right the industry standard in the Jango community is Postgres School.

168
00:08:10.839 --> 00:08:13.319
<v Speaker 1>But this brings up a massive temptation for developers.

169
00:08:13.360 --> 00:08:14.319
<v Speaker 2>Oh, I know where you're going with this.

170
00:08:14.480 --> 00:08:16.519
<v Speaker 1>If I am just building the app on my laptop,

171
00:08:16.639 --> 00:08:19.079
<v Speaker 1>why can't I just stick with Skilight locally for the

172
00:08:19.120 --> 00:08:22.199
<v Speaker 1>speed and convenience and only swap to Postgress School when

173
00:08:22.199 --> 00:08:24.240
<v Speaker 1>I finally launched the code to the real world.

174
00:08:24.480 --> 00:08:29.000
<v Speaker 2>Because doing so violates a core tenet of professional software engineering,

175
00:08:29.199 --> 00:08:33.240
<v Speaker 2>which is total parity. Parity meaning you must mimic your

176
00:08:33.279 --> 00:08:38.480
<v Speaker 2>production environment locally period. If you rely on a lightweight

177
00:08:38.600 --> 00:08:42.399
<v Speaker 2>file based database on your laptop but a complex, strictly

178
00:08:42.480 --> 00:08:46.799
<v Speaker 2>typed relational database on your server, you are basically inviting

179
00:08:46.879 --> 00:08:48.720
<v Speaker 2>catastrophic edge case.

180
00:08:48.480 --> 00:08:52.320
<v Speaker 1>Bugs ah like the production server might enforce certain string

181
00:08:52.399 --> 00:08:56.720
<v Speaker 1>lengths or handle daytime objects entirely differently than the local

182
00:08:56.720 --> 00:08:57.799
<v Speaker 1>setup exactly.

183
00:08:58.279 --> 00:09:00.639
<v Speaker 2>The ultimate goal of parity is that if your production

184
00:09:00.720 --> 00:09:02.440
<v Speaker 2>server is going to sweat under the weight of a

185
00:09:02.480 --> 00:09:05.919
<v Speaker 2>complex query, your laptop needs to sweat under that exact

186
00:09:05.960 --> 00:09:07.360
<v Speaker 2>same query during development.

187
00:09:07.559 --> 00:09:10.919
<v Speaker 1>That makes perfect sense, so we have to run postgrescool locally,

188
00:09:11.120 --> 00:09:13.759
<v Speaker 1>and thanks to our Docker dash composed dot iml file,

189
00:09:13.960 --> 00:09:16.279
<v Speaker 1>we don't have to install Postgres directly onto our Mac

190
00:09:16.360 --> 00:09:17.240
<v Speaker 1>or Windows machines.

191
00:09:17.399 --> 00:09:18.120
<v Speaker 2>Thank goodness.

192
00:09:18.240 --> 00:09:19.759
<v Speaker 1>Right, we just write a few lines of code to

193
00:09:19.799 --> 00:09:22.960
<v Speaker 1>spin up a second Docker container, a dedicated database service

194
00:09:23.039 --> 00:09:25.759
<v Speaker 1>running right alongside our web server container. But here is

195
00:09:25.759 --> 00:09:28.840
<v Speaker 1>the technical hurdle for people. Django is written in Python,

196
00:09:29.440 --> 00:09:33.919
<v Speaker 1>postgrescool is a completely separate technology written in C. How

197
00:09:33.960 --> 00:09:37.600
<v Speaker 1>do they actually communicate across two different Docker containers?

198
00:09:38.080 --> 00:09:42.360
<v Speaker 2>Right? Well, Django utilizes an ARM, an object relational mapper.

199
00:09:42.879 --> 00:09:46.480
<v Speaker 2>You write standard Python code and the OARM translates that

200
00:09:46.639 --> 00:09:50.120
<v Speaker 2>logic into the SQL queries that the database actually understands.

201
00:09:50.440 --> 00:09:53.639
<v Speaker 1>Okay, but for that translated sequel to physically travel over

202
00:09:53.679 --> 00:09:56.799
<v Speaker 1>the network from the web container to the database container, you.

203
00:09:56.759 --> 00:10:00.679
<v Speaker 2>Need a highly specific database adapter. And in the Python ecosystem,

204
00:10:00.759 --> 00:10:03.559
<v Speaker 2>that bridge is a library called psychup g two.

205
00:10:03.720 --> 00:10:07.080
<v Speaker 1>Oh, psych up g two, which is notoriously difficult to

206
00:10:07.120 --> 00:10:10.960
<v Speaker 1>install on local machines because it requires system level C compilers.

207
00:10:11.120 --> 00:10:13.679
<v Speaker 1>Oh it's the worst, which perfectly illustrates why we are

208
00:10:13.759 --> 00:10:16.480
<v Speaker 1>using Docker in the first place. We can just define

209
00:10:16.519 --> 00:10:19.039
<v Speaker 1>the required Linux C libraries in our docer file and

210
00:10:19.080 --> 00:10:20.039
<v Speaker 1>never worry about it again.

211
00:10:20.120 --> 00:10:23.240
<v Speaker 2>Yep, it's solved permanently. Now, there is one quirk about

212
00:10:23.279 --> 00:10:25.960
<v Speaker 2>running a heavy duty database in Docker that the author

213
00:10:26.000 --> 00:10:28.799
<v Speaker 2>warns us about. What's that When we run our database container,

214
00:10:28.919 --> 00:10:31.559
<v Speaker 2>we typically run it in detached mode using the red

215
00:10:31.639 --> 00:10:32.200
<v Speaker 2>d flag.

216
00:10:32.519 --> 00:10:35.480
<v Speaker 1>Okay, so the container runs quietly in the background without

217
00:10:35.519 --> 00:10:36.559
<v Speaker 1>locking up our terminal.

218
00:10:36.759 --> 00:10:40.879
<v Speaker 2>Right, but Docker containers are inherently ephemeral because postgrad school

219
00:10:40.919 --> 00:10:44.080
<v Speaker 2>isn't just a simple file like skibide. It writes its

220
00:10:44.159 --> 00:10:47.440
<v Speaker 2>data to the internal file system of that specific container.

221
00:10:47.600 --> 00:10:50.240
<v Speaker 2>Uh oh yeah. If you spin down that container to

222
00:10:50.320 --> 00:10:53.679
<v Speaker 2>update your system, anything written to that internal file system

223
00:10:53.960 --> 00:10:56.559
<v Speaker 2>is completely obliterated. Poof, it's gone.

224
00:10:56.919 --> 00:11:01.120
<v Speaker 1>So you spend three hours meticulously setting up test users

225
00:11:01.159 --> 00:11:04.480
<v Speaker 1>and mock data. You restart your computer and the database

226
00:11:04.559 --> 00:11:05.600
<v Speaker 1>is completely empty.

227
00:11:06.000 --> 00:11:08.600
<v Speaker 2>It is a painful rite of passage for every developer.

228
00:11:08.679 --> 00:11:09.840
<v Speaker 1>So how do we avoid that?

229
00:11:09.960 --> 00:11:13.639
<v Speaker 2>The architectural fix is incredibly elegant. Just like we use

230
00:11:13.679 --> 00:11:16.039
<v Speaker 2>a docer volume to mirror our code from our local

231
00:11:16.080 --> 00:11:18.240
<v Speaker 2>hard drive into the web container.

232
00:11:18.000 --> 00:11:21.519
<v Speaker 1>We utilize a persistent volume mount, specifically for the database's

233
00:11:21.559 --> 00:11:22.960
<v Speaker 1>internal storage directory.

234
00:11:23.240 --> 00:11:26.559
<v Speaker 2>Exactly. We tell doctor, Hey, take all the internal data

235
00:11:26.600 --> 00:11:30.559
<v Speaker 2>POSTGRESSWOL was generating and stored safely on a dedicated, persistent

236
00:11:30.600 --> 00:11:32.759
<v Speaker 2>slice of the host machin's hard drive.

237
00:11:32.919 --> 00:11:35.159
<v Speaker 1>So even when the container shuts down and the internal

238
00:11:35.159 --> 00:11:38.320
<v Speaker 1>filesystem is wiped, your actual data is preserved.

239
00:11:38.159 --> 00:11:40.840
<v Speaker 2>Waiting to be instantly reattached the next time the container

240
00:11:40.879 --> 00:11:41.360
<v Speaker 2>boots up.

241
00:11:41.440 --> 00:11:44.919
<v Speaker 1>Okay, so we have a rock solid isolated apartment for

242
00:11:45.000 --> 00:11:48.159
<v Speaker 1>our code and an industrial strength database running in parallel.

243
00:11:48.399 --> 00:11:50.279
<v Speaker 1>We are finally ready to write some features.

244
00:11:50.879 --> 00:11:54.360
<v Speaker 2>Actually, no, no, the source material throws a massive stop

245
00:11:54.399 --> 00:11:56.919
<v Speaker 2>sign in front of us here. Before you build a

246
00:11:56.960 --> 00:11:59.679
<v Speaker 2>single feature, before you even think about running your very

247
00:11:59.720 --> 00:12:05.039
<v Speaker 2>first database migration, there is one critical architectural step you

248
00:12:05.120 --> 00:12:05.600
<v Speaker 2>must take.

249
00:12:06.360 --> 00:12:07.679
<v Speaker 1>The golden rule of Jengo.

250
00:12:07.759 --> 00:12:12.759
<v Speaker 2>The golden rule You must implement a custom user model immediately.

251
00:12:13.039 --> 00:12:16.240
<v Speaker 1>Yeah, the official Jengo documentation does not mince words here.

252
00:12:16.519 --> 00:12:19.360
<v Speaker 1>They highly recommend setting up a custom user model from

253
00:12:19.360 --> 00:12:20.559
<v Speaker 1>the very first commit.

254
00:12:20.600 --> 00:12:21.120
<v Speaker 2>They really do.

255
00:12:21.360 --> 00:12:23.559
<v Speaker 1>But why is this so critical? I mean, Django gives

256
00:12:23.600 --> 00:12:26.519
<v Speaker 1>us a perfectly functional user model out of the box.

257
00:12:26.279 --> 00:12:28.679
<v Speaker 2>Right, it does, But it all comes down to technical

258
00:12:28.759 --> 00:12:32.759
<v Speaker 2>debt and how deeply interwoven that default user model is

259
00:12:32.799 --> 00:12:37.039
<v Speaker 2>into the framework's internal architecture. Okay, to understand the risk,

260
00:12:37.639 --> 00:12:39.360
<v Speaker 2>you need a tangible horror story.

261
00:12:39.480 --> 00:12:39.960
<v Speaker 1>Let's hear it.

262
00:12:40.159 --> 00:12:44.080
<v Speaker 2>Imagine you ignore the warning, you use the default user model.

263
00:12:44.519 --> 00:12:47.600
<v Speaker 2>Six months from now, your application is scaling and the

264
00:12:47.600 --> 00:12:49.960
<v Speaker 2>marketing team decides they want users to log in with

265
00:12:50.000 --> 00:12:53.360
<v Speaker 2>an email address instead of a user name, and they

266
00:12:53.360 --> 00:12:55.120
<v Speaker 2>want add a profile picture field.

267
00:12:55.240 --> 00:12:57.279
<v Speaker 1>I mean that sounds like a standard future request. You

268
00:12:57.360 --> 00:13:00.120
<v Speaker 1>just alter the database table right at a column.

269
00:13:00.240 --> 00:13:02.840
<v Speaker 2>If you are using the default model, trying to alter

270
00:13:02.919 --> 00:13:07.279
<v Speaker 2>it mid project will completely break Django's internal migration system.

271
00:13:07.360 --> 00:13:10.080
<v Speaker 1>Wait, really break it completely completely.

272
00:13:10.320 --> 00:13:12.879
<v Speaker 2>Dozens of foreign keys across your entire database, like the

273
00:13:12.919 --> 00:13:16.600
<v Speaker 2>built in Django animin log table, are deeply tied to

274
00:13:16.639 --> 00:13:19.840
<v Speaker 2>the specific structure of that deese bowl table. Oh wow,

275
00:13:20.080 --> 00:13:22.159
<v Speaker 2>So when you try to swap it out, the migration

276
00:13:22.240 --> 00:13:25.799
<v Speaker 2>system panics. Foreign keys suddenly point to tables that don't

277
00:13:25.799 --> 00:13:28.320
<v Speaker 2>match or just don't exist. You end up having to

278
00:13:28.320 --> 00:13:31.399
<v Speaker 2>manually edit complex equal files. Oh that sounds awful, or

279
00:13:31.440 --> 00:13:33.799
<v Speaker 2>in the worst case scenarios, developers literally have to dump

280
00:13:33.840 --> 00:13:37.840
<v Speaker 2>their entire database, wipe their migration history, and start from scratch.

281
00:13:38.799 --> 00:13:39.679
<v Speaker 2>It is a nightmare.

282
00:13:39.799 --> 00:13:42.159
<v Speaker 1>So how do we lay the right foundation on day

283
00:13:42.240 --> 00:13:44.000
<v Speaker 1>one to avoid that disaster?

284
00:13:44.480 --> 00:13:46.440
<v Speaker 2>You take the time up front to build a custom

285
00:13:46.559 --> 00:13:50.120
<v Speaker 2>user model. You create a dedicated application within your project,

286
00:13:50.279 --> 00:13:53.759
<v Speaker 2>usually called users. Then you write a custom user class

287
00:13:53.799 --> 00:13:56.960
<v Speaker 2>that inherits from a built in Django class called abstract user.

288
00:13:57.279 --> 00:14:00.440
<v Speaker 1>Okay, so by extending abstract user or essentially being the

289
00:14:00.480 --> 00:14:04.120
<v Speaker 1>exact blueprint of the default user, right exactly, keeping all

290
00:14:04.159 --> 00:14:07.840
<v Speaker 1>the complex vital security features like password hashing, session management,

291
00:14:07.879 --> 00:14:11.559
<v Speaker 1>and permissions, but we are placing all of that power

292
00:14:11.759 --> 00:14:15.639
<v Speaker 1>inside a Python class that we actually own and control precisely.

293
00:14:16.120 --> 00:14:19.480
<v Speaker 2>Then you simply update a configuration setting called athuser model

294
00:14:19.759 --> 00:14:23.360
<v Speaker 2>to tell the entire framework, Hey, ignore your hard coded

295
00:14:23.360 --> 00:14:26.919
<v Speaker 2>default user and route all authentication logic through my custom

296
00:14:27.000 --> 00:14:30.080
<v Speaker 2>model instead. That's brilliant, right, And from that moment on,

297
00:14:30.519 --> 00:14:33.039
<v Speaker 2>the foundation is yours. You want to add a new

298
00:14:33.080 --> 00:14:35.000
<v Speaker 2>field three years from now, you just add it to

299
00:14:35.039 --> 00:14:36.759
<v Speaker 2>your class and run a standard migration.

300
00:14:36.960 --> 00:14:40.120
<v Speaker 1>What I find so impressive is how the surrounding ecosystem

301
00:14:40.320 --> 00:14:41.559
<v Speaker 1>reacts to this change.

302
00:14:41.679 --> 00:14:45.799
<v Speaker 2>What's fascinating here is the seamless adoption by Django's built

303
00:14:45.840 --> 00:14:49.960
<v Speaker 2>in administrative tools. The framework comes with this heavily engineered

304
00:14:50.000 --> 00:14:53.000
<v Speaker 2>admin panel out of the box. Once you point the

305
00:14:53.039 --> 00:14:56.200
<v Speaker 2>athuser model setting to your custom class and update the

306
00:14:56.240 --> 00:14:59.840
<v Speaker 2>internal form classes used for user creation, the admin panel

307
00:15:00.039 --> 00:15:04.120
<v Speaker 2>dynamically rebuilds itself to accommodate your custom feels without a

308
00:15:04.159 --> 00:15:04.879
<v Speaker 2>single hiccup.

309
00:15:04.960 --> 00:15:07.759
<v Speaker 1>It really is a masterclass in extensible software design.

310
00:15:07.840 --> 00:15:08.360
<v Speaker 2>It really is.

311
00:15:08.799 --> 00:15:11.600
<v Speaker 1>So We've spent all this time building a bulletproof foundation

312
00:15:11.720 --> 00:15:14.720
<v Speaker 1>for the code, the database, and the architecture of our users.

313
00:15:15.120 --> 00:15:18.279
<v Speaker 1>But an app is useless without people. Very true, and

314
00:15:18.559 --> 00:15:22.000
<v Speaker 1>the second you invite actual human beings into your application,

315
00:15:22.320 --> 00:15:23.440
<v Speaker 1>you introduce chaos.

316
00:15:23.600 --> 00:15:24.759
<v Speaker 2>Oh absolute chaos.

317
00:15:24.799 --> 00:15:28.000
<v Speaker 1>They need to be able to securely sign up, log in,

318
00:15:28.399 --> 00:15:32.200
<v Speaker 1>and view private data. Now, for beginners, Jango's built in

319
00:15:32.279 --> 00:15:35.960
<v Speaker 1>authentication system feels like pure magic. You literally just type

320
00:15:35.960 --> 00:15:39.080
<v Speaker 1>a URL tag for login in an HTML template and

321
00:15:39.120 --> 00:15:42.000
<v Speaker 1>it instantly generates a perfectly routed login system.

322
00:15:42.120 --> 00:15:44.480
<v Speaker 2>It does feel like a magic trick, but the author

323
00:15:44.480 --> 00:15:48.039
<v Speaker 2>makes a foundational point here that separates junior developers from professionals,

324
00:15:48.240 --> 00:15:51.000
<v Speaker 2>which is you cannot rely on magic. Magic is just

325
00:15:51.120 --> 00:15:53.120
<v Speaker 2>code you haven't taken the time to read yet.

326
00:15:53.440 --> 00:15:56.799
<v Speaker 1>I love that phrase, and the source material encourages us

327
00:15:56.840 --> 00:16:00.440
<v Speaker 1>to literally go to GitHub, open the Jango reposit and

328
00:16:00.600 --> 00:16:02.000
<v Speaker 1>look at the actual source code.

329
00:16:02.120 --> 00:16:03.440
<v Speaker 2>Yes, dive right into it.

330
00:16:03.480 --> 00:16:07.679
<v Speaker 1>You can navigate the folders to djangocontrabotherols, do piy and

331
00:16:07.720 --> 00:16:10.039
<v Speaker 1>see the raw Python code where the login view and

332
00:16:10.080 --> 00:16:12.120
<v Speaker 1>log our view are actually defined exactly.

333
00:16:12.159 --> 00:16:16.000
<v Speaker 2>It's not a spell. It's just highly optimized object oriented

334
00:16:16.000 --> 00:16:19.879
<v Speaker 2>programming written by other engineers. Demystifying your tools is a

335
00:16:19.879 --> 00:16:23.840
<v Speaker 2>hallmark of senior engineering, right because when you understand exactly

336
00:16:23.879 --> 00:16:27.440
<v Speaker 2>how Jango process is an incoming log in post request,

337
00:16:28.240 --> 00:16:32.159
<v Speaker 2>you understand how to customize that flow, and far more importantly,

338
00:16:32.240 --> 00:16:33.480
<v Speaker 2>you understand how to secure it.

339
00:16:34.120 --> 00:16:37.159
<v Speaker 1>Speaking of security, there's a vital, tiny detail in the

340
00:16:37.200 --> 00:16:40.320
<v Speaker 1>source material regarding these login forms. Whenever you create an

341
00:16:40.440 --> 00:16:43.200
<v Speaker 1>HTML form that a user submits, you have to include

342
00:16:43.240 --> 00:16:46.559
<v Speaker 1>a specific template tag, the CSRF token.

343
00:16:46.720 --> 00:16:50.200
<v Speaker 2>Yes, that stands for Cross site Requests Forgery and understanding

344
00:16:50.200 --> 00:16:53.240
<v Speaker 2>the mechanism behind it is critical for building production apps.

345
00:16:53.440 --> 00:16:56.039
<v Speaker 1>What exactly is that token doing behind the scenes.

346
00:16:56.240 --> 00:17:00.279
<v Speaker 2>It is actively protecting your users from malicious session hijacking. Okay,

347
00:17:00.279 --> 00:17:03.200
<v Speaker 2>how so, imagine you are logged into your bank account

348
00:17:03.200 --> 00:17:07.160
<v Speaker 2>in one browser tab. Your browser is storing an authenticated

349
00:17:07.160 --> 00:17:08.319
<v Speaker 2>session cookie.

350
00:17:08.039 --> 00:17:10.240
<v Speaker 1>Right, so the bank knows it's me exactly.

351
00:17:10.640 --> 00:17:13.759
<v Speaker 2>But in another tab, you accidentally click a malicious link.

352
00:17:14.160 --> 00:17:18.759
<v Speaker 2>Without CSRF protection, that shady website could silently trigger an

353
00:17:18.759 --> 00:17:23.440
<v Speaker 2>invisible form submission to your bank's servers. Say a request

354
00:17:23.440 --> 00:17:27.079
<v Speaker 2>to transfer one thousand dollars wow, And because your browser

355
00:17:27.079 --> 00:17:30.559
<v Speaker 2>automatically sends your valid session cookie with that request, the

356
00:17:30.599 --> 00:17:33.000
<v Speaker 2>bank server thinks you authorize the transfer.

357
00:17:33.480 --> 00:17:37.599
<v Speaker 1>That is terrifying. How does one little tag stop that?

358
00:17:37.759 --> 00:17:41.839
<v Speaker 2>When you include that CSRF tag, Django dynamically injects a

359
00:17:41.920 --> 00:17:45.319
<v Speaker 2>hidden input field into your HTML form containing a highly

360
00:17:45.319 --> 00:17:47.039
<v Speaker 2>secure randomized string of characters.

361
00:17:47.160 --> 00:17:47.279
<v Speaker 1>Ok.

362
00:17:47.519 --> 00:17:50.240
<v Speaker 2>When the user hits submit, a dedicated piece of Jango

363
00:17:50.319 --> 00:17:54.000
<v Speaker 2>middleware intercepts the incoming request. It looks the hidden token

364
00:17:54.039 --> 00:17:56.240
<v Speaker 2>submitted with a form and compares it against the secure

365
00:17:56.279 --> 00:17:57.839
<v Speaker 2>cookie stored in the user's browser.

366
00:17:57.960 --> 00:17:58.160
<v Speaker 1>Ah.

367
00:17:58.200 --> 00:18:00.279
<v Speaker 2>I see, so if a malicious site tries to admit

368
00:18:00.319 --> 00:18:02.759
<v Speaker 2>a form on your behalf from another tab, they won't

369
00:18:02.799 --> 00:18:06.839
<v Speaker 2>have access to that hidden randomized token. The middleware sees

370
00:18:06.839 --> 00:18:10.519
<v Speaker 2>the mismatch, flags it as a forgery, and instantly blocks

371
00:18:10.559 --> 00:18:13.079
<v Speaker 2>the request with a four to ZHO three forbidden error.

372
00:18:13.119 --> 00:18:16.400
<v Speaker 1>It's basically a bouncer checking the ID against the guest

373
00:18:16.440 --> 00:18:18.279
<v Speaker 1>list on every single form submission.

374
00:18:18.400 --> 00:18:19.559
<v Speaker 2>That's a perfect way to put it.

375
00:18:19.599 --> 00:18:22.480
<v Speaker 1>I love that. Now I want to pivot to the

376
00:18:22.519 --> 00:18:26.440
<v Speaker 1>final major hurdle of professional development, which is automated testing.

377
00:18:26.680 --> 00:18:30.319
<v Speaker 2>Ah. Yes, the vegetables of software development exactly.

378
00:18:30.359 --> 00:18:33.680
<v Speaker 1>The author walks us through building a basic static homepage

379
00:18:34.000 --> 00:18:36.319
<v Speaker 1>and then immediately makes us write an automated test to

380
00:18:36.400 --> 00:18:39.000
<v Speaker 1>ensure it loads properly. I have to admit this is

381
00:18:39.000 --> 00:18:41.680
<v Speaker 1>where a lot of developers roll their eyes. Oh, absolutely, Like,

382
00:18:41.799 --> 00:18:44.519
<v Speaker 1>is it really necessary to write a Python script just

383
00:18:44.599 --> 00:18:47.599
<v Speaker 1>to check if a static homepage returns an HDTP two

384
00:18:47.680 --> 00:18:51.200
<v Speaker 1>hundred status code. It feels like complete overkill when I

385
00:18:51.200 --> 00:18:53.440
<v Speaker 1>can literally just click refresh on my browser.

386
00:18:53.720 --> 00:18:57.880
<v Speaker 2>It is the exact psychological barrier every single developer faces

387
00:18:57.960 --> 00:19:01.079
<v Speaker 2>when they encounter automated testing for the first time. It

388
00:19:01.079 --> 00:19:03.079
<v Speaker 2>feels like eating your vegetables when you just want to

389
00:19:03.079 --> 00:19:08.079
<v Speaker 2>build features right. But there is a famous, uncompromising quote

390
00:19:08.440 --> 00:19:12.839
<v Speaker 2>from Django co founder Jacob Kaplan Moss. He says, code

391
00:19:12.880 --> 00:19:15.480
<v Speaker 2>without tests is broken as designed.

392
00:19:15.279 --> 00:19:18.960
<v Speaker 1>Broken as designed. That is a heavy accusation.

393
00:19:19.279 --> 00:19:22.720
<v Speaker 2>It is heavy, but it is deeply accurate for production systems.

394
00:19:23.079 --> 00:19:26.039
<v Speaker 2>I mean manually refreshing your browser to check if the

395
00:19:26.079 --> 00:19:29.920
<v Speaker 2>homepage lows works perfectly today. Sure, but what happens eighteen

396
00:19:30.000 --> 00:19:32.920
<v Speaker 2>months from now when your project has one hundred different

397
00:19:33.119 --> 00:19:37.799
<v Speaker 2>interconnected views and a junior developer updates a core routing file. Oh,

398
00:19:38.279 --> 00:19:40.440
<v Speaker 2>are you going to manually click through all one hundred

399
00:19:40.440 --> 00:19:43.440
<v Speaker 2>pages on your local machine to verify nothing broke before

400
00:19:43.440 --> 00:19:44.680
<v Speaker 2>you deploy to the live server.

401
00:19:44.880 --> 00:19:47.799
<v Speaker 1>I mean, realistically, no, nobody has time for.

402
00:19:47.759 --> 00:19:51.079
<v Speaker 2>That, and that is exactly when catastrophic regressions slip into production.

403
00:19:51.799 --> 00:19:54.599
<v Speaker 2>Testing isn't about proving your code works in the present moment.

404
00:19:54.920 --> 00:19:58.000
<v Speaker 2>It is a strict insurance policy for the future. It

405
00:19:58.079 --> 00:20:01.640
<v Speaker 2>guarantees that when you add complex new features tomorrow, you

406
00:20:01.720 --> 00:20:04.440
<v Speaker 2>haven't fundamentally broken the architecture you built yesterday.

407
00:20:04.599 --> 00:20:07.359
<v Speaker 1>Okay, I conceptually understand the value, but actually writing the

408
00:20:07.400 --> 00:20:10.440
<v Speaker 1>tests can be so agonizingly repetitive.

409
00:20:10.559 --> 00:20:12.119
<v Speaker 2>It can be you know, you're.

410
00:20:12.000 --> 00:20:16.000
<v Speaker 1>Constantly writing the exact same setup code, creating test users,

411
00:20:16.240 --> 00:20:21.079
<v Speaker 1>simulating logins, loading pages before you even get to the

412
00:20:21.119 --> 00:20:23.279
<v Speaker 1>actual assertion of the test, which.

413
00:20:23.119 --> 00:20:26.559
<v Speaker 2>Is precisely why professional test suites strictly adhere to the

414
00:20:26.599 --> 00:20:31.359
<v Speaker 2>Droi principle. Don't repeat yourself. The author introduces the setup method. Okay,

415
00:20:31.599 --> 00:20:35.519
<v Speaker 2>Instead of duplicating the preparation logic inside every single test function,

416
00:20:35.920 --> 00:20:39.920
<v Speaker 2>you place it inside setup. The testing framework will automatically

417
00:20:40.039 --> 00:20:43.799
<v Speaker 2>run that setup method before every individual test in that class.

418
00:20:43.839 --> 00:20:46.799
<v Speaker 2>Oh nice, Yeah, you define your URL and load your

419
00:20:46.839 --> 00:20:50.960
<v Speaker 2>simulated user once, and your individual tests remain clean and

420
00:20:51.039 --> 00:20:52.839
<v Speaker 2>focused on just asserting the results.

421
00:20:53.000 --> 00:20:55.319
<v Speaker 1>It dramatically reduces the total lines of code.

422
00:20:55.400 --> 00:20:58.759
<v Speaker 2>It does. But for enterprise scale projects, the author dies

423
00:20:58.799 --> 00:21:02.240
<v Speaker 2>into an even deeper optimization, which is set up test.

424
00:21:02.079 --> 00:21:04.559
<v Speaker 1>Data, setup test data. How is that different?

425
00:21:04.680 --> 00:21:06.880
<v Speaker 2>This is a massive leap in performance. When you use

426
00:21:06.920 --> 00:21:09.759
<v Speaker 2>the basic setup method. The framework hits the database to

427
00:21:09.799 --> 00:21:12.160
<v Speaker 2>create your test rows before every single test and then

428
00:21:12.160 --> 00:21:15.839
<v Speaker 2>destroys them. Hitting the disc for database transactions is the

429
00:21:15.880 --> 00:21:19.039
<v Speaker 2>single most expensive time consuming operation and testing.

430
00:21:19.640 --> 00:21:22.160
<v Speaker 1>So if you have fifty tests, you are creating and

431
00:21:22.200 --> 00:21:26.160
<v Speaker 1>destroying that exact same test user fifty separate times exactly.

432
00:21:26.720 --> 00:21:30.279
<v Speaker 2>But setup test Data executes at the class level. It

433
00:21:30.359 --> 00:21:34.079
<v Speaker 2>hits the database exactly one time, creating the user and

434
00:21:34.119 --> 00:21:38.680
<v Speaker 2>the required data. Okay, Then it utilizes database transaction rollbacks

435
00:21:39.119 --> 00:21:42.160
<v Speaker 2>for every subsequent test. It simply rolls back the state

436
00:21:42.200 --> 00:21:44.519
<v Speaker 2>in memory rather than hitting the physical disc Again.

437
00:21:44.640 --> 00:21:46.240
<v Speaker 1>Wow, that's incredibly efficient.

438
00:21:46.359 --> 00:21:49.279
<v Speaker 2>When you are working on a mature codebase with thousands

439
00:21:49.319 --> 00:21:51.920
<v Speaker 2>of tests. The difference between set up and set up

440
00:21:51.920 --> 00:21:54.440
<v Speaker 2>test data is the difference between a test suite that

441
00:21:54.480 --> 00:21:56.880
<v Speaker 2>takes twenty minutes to run and one that finishes in

442
00:21:56.920 --> 00:21:57.880
<v Speaker 2>forty five seconds.

443
00:21:58.000 --> 00:22:01.319
<v Speaker 1>That is massive. So what is this all? Let's zoom

444
00:22:01.319 --> 00:22:03.640
<v Speaker 1>out and look at the profound leap we have just taken.

445
00:22:03.759 --> 00:22:04.640
<v Speaker 2>Yeah, let's recap.

446
00:22:05.039 --> 00:22:08.519
<v Speaker 1>We started by escaping the chaotic trap of local dependencies

447
00:22:08.839 --> 00:22:13.400
<v Speaker 1>by engineering a containerized, perfectly deterministic environment with Docker. We

448
00:22:13.480 --> 00:22:16.880
<v Speaker 1>ripped off the training wheels and installed production grade post

449
00:22:16.920 --> 00:22:20.880
<v Speaker 1>gresswol database, demanding total parody between our laptops and the

450
00:22:20.920 --> 00:22:21.519
<v Speaker 1>real world.

451
00:22:21.640 --> 00:22:22.079
<v Speaker 2>We did.

452
00:22:22.559 --> 00:22:25.880
<v Speaker 1>We protected our future architecture by adhering to the Golden

453
00:22:25.960 --> 00:22:29.839
<v Speaker 1>rule and implementing a custom user model on day one.

454
00:22:29.880 --> 00:22:33.960
<v Speaker 1>We demystified the magic of authentication, lock down our forms

455
00:22:34.000 --> 00:22:37.640
<v Speaker 1>with CSRF middleware, and ensured our entire code base with

456
00:22:37.680 --> 00:22:40.920
<v Speaker 1>a highly optimized suite of automated.

457
00:22:40.400 --> 00:22:41.400
<v Speaker 2>Tests a lot.

458
00:22:41.519 --> 00:22:44.279
<v Speaker 1>We are no longer just writing Python scripts. We have

459
00:22:44.359 --> 00:22:49.160
<v Speaker 1>successfully engineered the foundational architecture of a highly scalable truly

460
00:22:49.200 --> 00:22:51.319
<v Speaker 1>professional web application, and.

461
00:22:51.480 --> 00:22:54.559
<v Speaker 2>The transition from coding to engineering infrastructure is one of

462
00:22:54.559 --> 00:22:56.920
<v Speaker 2>the most rewarding moments in a developer's career. And if

463
00:22:56.920 --> 00:22:59.880
<v Speaker 2>we connect the specific technologies we covered today to the

464
00:23:00.119 --> 00:23:02.920
<v Speaker 2>broader landscape of the tech industry, yeah, it raises a

465
00:23:02.960 --> 00:23:04.279
<v Speaker 2>truly fascinating question.

466
00:23:04.440 --> 00:23:05.279
<v Speaker 1>Oh what's that?

467
00:23:05.559 --> 00:23:10.799
<v Speaker 2>Well, consider the toolchain we just deployed, Docker, Linux containers, postcresscres, scold,

468
00:23:10.839 --> 00:23:14.720
<v Speaker 2>Jango's robust security manware. These are the exact same architectural

469
00:23:14.759 --> 00:23:18.200
<v Speaker 2>primitives utilized by the largest tech companies on Earth ten

470
00:23:18.279 --> 00:23:22.240
<v Speaker 2>or fifteen years ago. Configuring networking and securing this kind

471
00:23:22.279 --> 00:23:26.559
<v Speaker 2>of scalable infrastructure required a massive, highly paid team of

472
00:23:26.640 --> 00:23:31.839
<v Speaker 2>dedicated systems administrators, database engineers, and security experts. Absolutely, today,

473
00:23:32.119 --> 00:23:34.960
<v Speaker 2>a single developer sitting on the laptop in a coffee

474
00:23:34.960 --> 00:23:39.119
<v Speaker 2>shop can summon and orchestrate that exact same enterprise grade

475
00:23:39.160 --> 00:23:42.880
<v Speaker 2>infrastructure effortlessly through a few configuration files.

476
00:23:42.960 --> 00:23:46.359
<v Speaker 1>The sheer power of massive engineering departments has been completely

477
00:23:46.359 --> 00:23:48.640
<v Speaker 1>democratized and handed directly to the individual.

478
00:23:48.759 --> 00:23:52.079
<v Speaker 2>Exactly so, in a world where one solo developer can

479
00:23:52.119 --> 00:23:55.920
<v Speaker 2>effortlessly wield the architectural capability that used to require millions

480
00:23:55.920 --> 00:23:58.400
<v Speaker 2>of dollars in venture capital. Yeah, are the days of

481
00:23:58.480 --> 00:24:02.240
<v Speaker 2>needing massive bloated in engineering teams to launch a globally

482
00:24:02.279 --> 00:24:04.480
<v Speaker 2>scalable platform finally coming to an end.

483
00:24:04.720 --> 00:24:06.759
<v Speaker 1>Now that is something of mull over. Next time you

484
00:24:06.799 --> 00:24:10.160
<v Speaker 1>write doctor compose up in your terminal. Thank you so

485
00:24:10.279 --> 00:24:12.759
<v Speaker 1>much for joining us on this deep dive into professional

486
00:24:12.799 --> 00:24:18.160
<v Speaker 1>Django architecture. Remember, the complex mechanisms we dissected today make

487
00:24:18.319 --> 00:24:21.240
<v Speaker 1>infinitely more sense when you actually see them running on

488
00:24:21.279 --> 00:24:24.359
<v Speaker 1>your own machine. Absolutely so, the absolute best way to

489
00:24:24.480 --> 00:24:27.400
<v Speaker 1>learn is to dive into the source code yourself, get

490
00:24:27.400 --> 00:24:30.200
<v Speaker 1>your hands dirty, build something that scales, and we will

491
00:24:30.240 --> 00:24:31.559
<v Speaker 1>see you next time.
