WEBVTT

1
00:00:00.360 --> 00:00:01.950
<v ->Hi guys and welcome back.</v>

2
00:00:01.950 --> 00:00:04.530
In this video we are going to be separating our code

3
00:00:04.530 --> 00:00:08.400
into models so that we can code more easily.

4
00:00:08.400 --> 00:00:10.520
Basically we're going to be creating classes

5
00:00:10.520 --> 00:00:14.060
out of the entities that our code deals in

6
00:00:14.060 --> 00:00:17.080
so that when we are dealing with those things in our code

7
00:00:17.080 --> 00:00:18.050
it becomes a little bit easier.

8
00:00:18.050 --> 00:00:20.482
We're gonna explain everything that goes on with that

9
00:00:20.482 --> 00:00:21.650
throughout the video.

10
00:00:21.650 --> 00:00:22.903
So, let's get to it.

11
00:00:24.900 --> 00:00:28.460
At the moment, we have our app.py

12
00:00:28.460 --> 00:00:31.910
dealing with certain things.

13
00:00:31.910 --> 00:00:34.910
Those things are, for example, polls

14
00:00:34.910 --> 00:00:39.080
options, votes, potentially even users.

15
00:00:39.080 --> 00:00:40.850
And often, in programming,

16
00:00:40.850 --> 00:00:43.250
when we're dealing with entities,

17
00:00:43.250 --> 00:00:44.560
as we call them,

18
00:00:44.560 --> 00:00:47.370
it can be helpful to create classes for them

19
00:00:47.370 --> 00:00:49.710
so that thinking about those things

20
00:00:49.710 --> 00:00:52.863
as individual entities can become a little bit easier.

21
00:00:53.730 --> 00:00:58.070
So, models are things that our programme deals with internally

22
00:00:58.070 --> 00:01:00.084
and the purpose of them is to make it easier

23
00:01:00.084 --> 00:01:02.920
for different parts of our application to communicate

24
00:01:02.920 --> 00:01:05.750
and also to make it easier for us to read

25
00:01:05.750 --> 00:01:07.880
and reason about the code.

26
00:01:07.880 --> 00:01:09.250
At the moment,

27
00:01:09.250 --> 00:01:10.980
this poll's variable for example,

28
00:01:10.980 --> 00:01:13.160
the database.get polls,

29
00:01:13.160 --> 00:01:17.750
is a list of tuples, it's not a list of objects

30
00:01:17.750 --> 00:01:19.520
that we can interact with

31
00:01:19.520 --> 00:01:22.420
and potentially ask them to do stuff for us

32
00:01:22.420 --> 00:01:24.250
by running methods and stuff like that.

33
00:01:24.250 --> 00:01:27.270
So, that's what we're going to do throughout this video.

34
00:01:27.270 --> 00:01:28.540
In my code I'm going to create

35
00:01:28.540 --> 00:01:31.390
model classes for poll and option.

36
00:01:31.390 --> 00:01:33.970
I consider votes to be sufficiently simple

37
00:01:33.970 --> 00:01:35.840
and encapsulated within options

38
00:01:35.840 --> 00:01:37.670
that they don't need their own class

39
00:01:37.670 --> 00:01:39.760
and our use of users at the moment

40
00:01:39.760 --> 00:01:41.530
is reserved to the username string

41
00:01:41.530 --> 00:01:42.620
attached to a vote

42
00:01:42.620 --> 00:01:45.330
and we're not gonna create a model class for that either.

43
00:01:45.330 --> 00:01:48.310
If we were storing more information about users or votes

44
00:01:48.310 --> 00:01:50.350
and we wanted to do a few more things with them

45
00:01:50.350 --> 00:01:52.130
then we might reconsider this.

46
00:01:52.130 --> 00:01:55.690
But for now, let's go ahead and create our models.

47
00:01:55.690 --> 00:01:57.240
Python directory.

48
00:01:57.240 --> 00:01:59.153
We're gonna call it models.

49
00:02:00.130 --> 00:02:05.130
And in here we're going to create our poll.py Python file.

50
00:02:05.340 --> 00:02:06.683
So we'll do poll.

51
00:02:08.570 --> 00:02:10.560
So let's begin writing a class

52
00:02:10.560 --> 00:02:13.570
to represent everything that our application

53
00:02:13.570 --> 00:02:15.130
wants to do with polls,

54
00:02:15.130 --> 00:02:18.000
including the data stored by a poll.

55
00:02:18.000 --> 00:02:20.130
I'll create the poll class,

56
00:02:20.130 --> 00:02:22.530
and by the way let me just hide away this project there.

57
00:02:22.530 --> 00:02:24.840
I'll create a poll class and then we're gonna add

58
00:02:24.840 --> 00:02:26.150
the init method in it

59
00:02:27.070 --> 00:02:29.350
and the polls have three properties:

60
00:02:29.350 --> 00:02:31.660
a title, which is a string,

61
00:02:31.660 --> 00:02:33.268
an owner, which is a string as well,

62
00:02:33.268 --> 00:02:36.720
and potentially they have an ID property.

63
00:02:36.720 --> 00:02:39.360
I'm gonna call it underscore ID, which is an integer

64
00:02:39.360 --> 00:02:41.000
and defaults to none.

65
00:02:41.000 --> 00:02:42.350
The reason it defaults to none

66
00:02:42.350 --> 00:02:44.920
is that if it doesn't get passed in

67
00:02:44.920 --> 00:02:47.150
when we create a poll object,

68
00:02:47.150 --> 00:02:49.510
we're going to assume that this poll

69
00:02:49.510 --> 00:02:51.880
hasn't been saved to the database yet

70
00:02:51.880 --> 00:02:53.640
and we're still waiting for the database

71
00:02:53.640 --> 00:02:56.690
to generate the ID for us.

72
00:02:56.690 --> 00:02:58.870
So we'll do self.id equals underscore ID,

73
00:02:58.870 --> 00:03:02.880
self.title equals title, self.owner equals owner.

74
00:03:02.880 --> 00:03:04.000
Often for these classes

75
00:03:04.000 --> 00:03:06.920
we want to create a repr dunder method

76
00:03:06.920 --> 00:03:08.650
so that when we are debugging

77
00:03:08.650 --> 00:03:09.970
and when we're printing stuff out

78
00:03:09.970 --> 00:03:11.330
it's a little bit easier to see

79
00:03:11.330 --> 00:03:13.920
what the object that we create represents.

80
00:03:13.920 --> 00:03:15.630
So we'll do a repr,

81
00:03:15.630 --> 00:03:17.490
and what this is gonna return is an f string

82
00:03:17.490 --> 00:03:19.980
with the poll and then the self.name.

83
00:03:19.980 --> 00:03:20.900
And what I'm gonna do here

84
00:03:20.900 --> 00:03:22.980
is I'm gonna put an exclamation mark r

85
00:03:22.980 --> 00:03:25.340
and that is gong to print out self.name

86
00:03:25.340 --> 00:03:28.500
but it's gonna make sure that it looks like

87
00:03:28.500 --> 00:03:30.570
what it would have to look like

88
00:03:30.570 --> 00:03:33.760
for the string to be valid in Python code.

89
00:03:33.760 --> 00:03:34.780
Basically, it's gonna put

90
00:03:34.780 --> 00:03:37.093
the quotation marks around it as well.

91
00:03:37.950 --> 00:03:39.620
Then we'll do self.owner.

92
00:03:39.620 --> 00:03:42.550
And by the way that should be self.title, not self.name

93
00:03:42.550 --> 00:03:43.860
so I will fix that in a moment.

94
00:03:43.860 --> 00:03:44.940
And self.id.

95
00:03:46.653 --> 00:03:50.620
(drawn out) self dot ID and r

96
00:03:50.620 --> 00:03:52.760
There we go, just like that.

97
00:03:52.760 --> 00:03:54.960
This should be self.title.

98
00:03:54.960 --> 00:03:57.100
Now what this is gonna print out essentially

99
00:03:57.100 --> 00:04:02.100
is poll and then the title, the owner, and the ID,

100
00:04:02.920 --> 00:04:05.400
which may be like, I don't know, one.

101
00:04:05.400 --> 00:04:07.430
And you can see that this here,

102
00:04:07.430 --> 00:04:11.240
we can use to recreate any poll object,

103
00:04:11.240 --> 00:04:14.620
and that is the purpose of the repr method.

104
00:04:14.620 --> 00:04:16.210
It should return a string

105
00:04:16.210 --> 00:04:20.010
that can be used to recreate the object it represents.

106
00:04:20.010 --> 00:04:22.530
Next up, we're gonna add the methods for the main things

107
00:04:22.530 --> 00:04:24.540
that we want to do with a poll.

108
00:04:24.540 --> 00:04:26.130
And one of those things might be

109
00:04:26.130 --> 00:04:28.270
to save it to the database.

110
00:04:28.270 --> 00:04:30.040
So we'll do save

111
00:04:30.040 --> 00:04:32.330
and then we're gonna do connection equal

112
00:04:32.330 --> 00:04:33.700
and we're gonna have a function

113
00:04:33.700 --> 00:04:35.200
called create connection here,

114
00:04:35.200 --> 00:04:37.150
I'll code it in just a moment.

115
00:04:37.150 --> 00:04:41.950
The new poll ID is gonna be database.create poll

116
00:04:41.950 --> 00:04:45.770
we're gonna pass in this connection self.title, self.owner

117
00:04:46.800 --> 00:04:48.882
then we're gonna close this connection

118
00:04:48.882 --> 00:04:53.100
and we're gonna set self ID to be equal to the new poll ID

119
00:04:53.100 --> 00:04:54.250
that we get from the database.

120
00:04:54.250 --> 00:04:57.030
Of course we have to import database,

121
00:04:57.030 --> 00:04:59.370
and we're also gonna have to

122
00:04:59.370 --> 00:05:01.800
import this create connection function,

123
00:05:01.800 --> 00:05:03.410
but we're gonna look at that in just a moment.

124
00:05:03.410 --> 00:05:06.120
For now, just assume that it connects to psycopg2

125
00:05:06.120 --> 00:05:08.040
and it gives us a connection back

126
00:05:08.040 --> 00:05:09.040
and at the end we close it.

127
00:05:09.040 --> 00:05:10.930
So we're gonna be using this function

128
00:05:10.930 --> 00:05:12.130
in a few different places here

129
00:05:12.130 --> 00:05:14.510
to create new connections as we need them.

130
00:05:14.510 --> 00:05:17.110
Whenever working with polls, polls have options

131
00:05:17.110 --> 00:05:20.200
so therefore it's possible to add options to a poll.

132
00:05:20.200 --> 00:05:24.190
That is why we're gonna have a method called add option

133
00:05:24.190 --> 00:05:26.910
that takes in an option text, which is a string.

134
00:05:26.910 --> 00:05:28.740
And all this does is it creates

135
00:05:28.740 --> 00:05:32.750
an option model class or object as in the option text,

136
00:05:32.750 --> 00:05:37.320
and the poll ID, and also calls save on it.

137
00:05:37.320 --> 00:05:39.990
The option model class is gonna be pretty similar

138
00:05:39.990 --> 00:05:41.480
to the poll model class.

139
00:05:41.480 --> 00:05:44.507
So, by calling .save in the option object

140
00:05:44.507 --> 00:05:46.570
then that will save it to the database

141
00:05:46.570 --> 00:05:49.010
in a similar way to what the poll does.

142
00:05:49.010 --> 00:05:50.720
As well as adding options,

143
00:05:50.720 --> 00:05:53.940
we also have to have a way of retrieving options.

144
00:05:53.940 --> 00:05:55.040
So what we're gonna do here

145
00:05:55.040 --> 00:05:57.840
is we're gonna define an options method here

146
00:05:57.840 --> 00:06:00.740
that returns a list of option models

147
00:06:00.740 --> 00:06:04.590
and this, again, is going to be the same class

148
00:06:04.590 --> 00:06:05.530
as we're using there,

149
00:06:05.530 --> 00:06:06.470
we haven't written it yet

150
00:06:06.470 --> 00:06:07.930
but we're gonna write it in a moment.

151
00:06:07.930 --> 00:06:09.460
This comes from the typing module,

152
00:06:09.460 --> 00:06:12.650
so we're gonna do from typing, import list.

153
00:06:12.650 --> 00:06:16.180
We'll also do from models, import option.

154
00:06:16.180 --> 00:06:17.260
Which at the moment doesn't exist,

155
00:06:17.260 --> 00:06:19.990
but it does get rid of these red underlines down there.

156
00:06:19.990 --> 00:06:22.540
What this has to do is, again, create a connection

157
00:06:22.540 --> 00:06:25.890
so we're gonna do connection equal create connection,

158
00:06:25.890 --> 00:06:27.780
then grab the options from the database

159
00:06:27.780 --> 00:06:31.720
so we'll do options equal database.get poll options,

160
00:06:31.720 --> 00:06:35.760
passing the connection and passing self.id.

161
00:06:35.760 --> 00:06:37.360
By the way, misspelt that.

162
00:06:37.360 --> 00:06:39.390
Self.id is the ID of the poll

163
00:06:39.390 --> 00:06:40.680
that we're currently working with

164
00:06:40.680 --> 00:06:43.470
so, this will give us the poll options.

165
00:06:43.470 --> 00:06:45.780
Notice that in this database call here,

166
00:06:45.780 --> 00:06:49.410
we're just gonna get the options for a poll.

167
00:06:49.410 --> 00:06:52.220
So we're not going to get the poll rows,

168
00:06:52.220 --> 00:06:55.490
as well as the options rows, as we have now with a join,

169
00:06:55.490 --> 00:06:58.210
we're just concerned here with the options themselves.

170
00:06:58.210 --> 00:07:00.450
So that's something that we have to code as well.

171
00:07:00.450 --> 00:07:03.120
Then we'll close the connection

172
00:07:03.120 --> 00:07:06.640
and we are going to return the option object.

173
00:07:06.640 --> 00:07:11.640
So we'll do option one, option two, option zero

174
00:07:12.050 --> 00:07:14.330
for option in options.

175
00:07:14.330 --> 00:07:16.850
The reason why we're passing these arguments

176
00:07:16.850 --> 00:07:18.710
to the option constructor,

177
00:07:18.710 --> 00:07:21.360
is because if you look at database.py,

178
00:07:21.360 --> 00:07:23.860
go to the top here for create options,

179
00:07:23.860 --> 00:07:26.660
an option has three values.

180
00:07:26.660 --> 00:07:28.880
The ID, the option text, and the poll ID

181
00:07:28.880 --> 00:07:32.210
those are gonna come back from our database.

182
00:07:32.210 --> 00:07:35.440
So here we're gonna pass them into the option constructor

183
00:07:35.440 --> 00:07:37.364
so that we can use those values from the database

184
00:07:37.364 --> 00:07:39.760
to create new objects.

185
00:07:39.760 --> 00:07:42.510
Next up, the three class methods that we're gonna need

186
00:07:42.510 --> 00:07:45.450
to get a specific poll by ID,

187
00:07:45.450 --> 00:07:47.260
we need that from app.py.

188
00:07:47.260 --> 00:07:50.960
Here we are getting specific poll information

189
00:07:50.960 --> 00:07:53.860
then we need one to get all the polls,

190
00:07:53.860 --> 00:07:55.920
for example we need that when we are trying

191
00:07:55.920 --> 00:07:58.320
to display the open polls.

192
00:07:58.320 --> 00:08:00.910
And we need one to get the latest poll,

193
00:08:00.910 --> 00:08:02.400
because we'll need that as well.

194
00:08:02.400 --> 00:08:06.503
So, we're gonna go over to poll.py and create those.

195
00:08:07.960 --> 00:08:08.820
If I leave them here,

196
00:08:08.820 --> 00:08:11.790
all of these do the same thing essentially.

197
00:08:11.790 --> 00:08:14.830
The get method takes in a poll ID

198
00:08:14.830 --> 00:08:17.350
and goes into the database and finds it.

199
00:08:17.350 --> 00:08:19.180
Notice that get poll doesn't exist yet

200
00:08:19.180 --> 00:08:20.110
but we're gonna create it.

201
00:08:20.110 --> 00:08:23.670
It essentially just retrieves a poll with that ID

202
00:08:23.670 --> 00:08:26.940
and then uses the CLS parameter,

203
00:08:26.940 --> 00:08:29.160
which is specific to class methods,

204
00:08:29.160 --> 00:08:31.970
to call the poll class,

205
00:08:31.970 --> 00:08:34.620
and it creates a new poll object

206
00:08:34.620 --> 00:08:37.030
passing in this information from the database.

207
00:08:37.030 --> 00:08:41.540
So the return type of this method is actually a poll object.

208
00:08:41.540 --> 00:08:43.390
And because we can't do this,

209
00:08:43.390 --> 00:08:46.349
we can't annotate a method of a class

210
00:08:46.349 --> 00:08:49.220
with the same class that it returns

211
00:08:49.220 --> 00:08:50.800
because by this point in time,

212
00:08:50.800 --> 00:08:52.070
when this actually runs,

213
00:08:52.070 --> 00:08:54.330
the class hasn't finished evaluating yet.

214
00:08:54.330 --> 00:08:56.320
So this is actually invalid in Python,

215
00:08:56.320 --> 00:08:58.060
we just put it as a string

216
00:08:58.060 --> 00:09:01.100
and Python knows to evaluate this return type

217
00:09:01.100 --> 00:09:04.020
after the class has finished processing.

218
00:09:04.020 --> 00:09:06.770
So that is what this returns - a poll object.

219
00:09:06.770 --> 00:09:09.560
The all method returns a list of polls

220
00:09:09.560 --> 00:09:11.960
and once again goes in and does database.get polls,

221
00:09:11.960 --> 00:09:14.120
which at the moment does exist.

222
00:09:14.120 --> 00:09:16.810
It just selects all the polls.

223
00:09:16.810 --> 00:09:20.290
And then what it does is it creates a poll object

224
00:09:20.290 --> 00:09:22.630
for each poll returned by the database

225
00:09:22.630 --> 00:09:25.270
and we end up with a list of poll objects.

226
00:09:25.270 --> 00:09:27.830
Finally, the latest method does the same thing

227
00:09:27.830 --> 00:09:29.860
but it just gets the latest poll.

228
00:09:29.860 --> 00:09:32.220
And I forgot to pass in the connection there

229
00:09:32.220 --> 00:09:34.160
so that's something that we need to pass in,

230
00:09:34.160 --> 00:09:38.020
and then simply gets the CLS return type there

231
00:09:38.020 --> 00:09:39.960
with the poll information.

232
00:09:39.960 --> 00:09:41.480
We're gonna have to change something in here

233
00:09:41.480 --> 00:09:42.410
afterwards anyway,

234
00:09:42.410 --> 00:09:45.570
because this at the moment returns a poll with option list

235
00:09:45.570 --> 00:09:48.560
and now we just want to get a single poll.

236
00:09:48.560 --> 00:09:50.040
So we do have to make those changes,

237
00:09:50.040 --> 00:09:51.680
but you can see that with the type hinting

238
00:09:51.680 --> 00:09:54.180
Python actually tells us this is probably not

239
00:09:54.180 --> 00:09:56.900
what we wanted to do with the current data types,

240
00:09:56.900 --> 00:09:59.210
but we're gonna change them in a moment.

241
00:09:59.210 --> 00:10:01.709
All right, so a lot of things new here.

242
00:10:01.709 --> 00:10:04.230
But essentially what we've done is we've created

243
00:10:04.230 --> 00:10:08.210
a class whose objects we can use

244
00:10:08.210 --> 00:10:12.810
to interact with the system in a bit of an easier way.

245
00:10:12.810 --> 00:10:15.620
Now we'll be able to, for example, create poll objects.

246
00:10:15.620 --> 00:10:17.210
I'm gonna just put it up here as an example.

247
00:10:17.210 --> 00:10:21.790
But we can say poll equal poll Flask versus Django,

248
00:10:21.790 --> 00:10:23.130
the owner can be Jose,

249
00:10:23.130 --> 00:10:25.860
and the ID let's say comes from the database and it's three,

250
00:10:25.860 --> 00:10:29.200
we can do things like poll.add option to add a new option.

251
00:10:29.200 --> 00:10:33.260
We can say Flask, and that is actually gonna go and save

252
00:10:33.260 --> 00:10:34.770
the option to the database

253
00:10:34.770 --> 00:10:37.190
without us having to do that ourselves.

254
00:10:37.190 --> 00:10:39.851
We can print poll.options for example

255
00:10:39.851 --> 00:10:41.220
and that is going to get us

256
00:10:41.220 --> 00:10:42.686
all the options from the database.

257
00:10:42.686 --> 00:10:45.900
And this is actually gonna be a list of option objects

258
00:10:45.900 --> 00:10:47.650
that we can then further interact with.

259
00:10:47.650 --> 00:10:48.790
Essentially, it allows us to be

260
00:10:48.790 --> 00:10:50.450
a little more flexible with how we're

261
00:10:50.450 --> 00:10:52.350
interacting with our system.

262
00:10:52.350 --> 00:10:55.870
By the way, I might actually make this a property,

263
00:10:55.870 --> 00:11:00.870
a decorator there, just so we can access poll.options

264
00:11:01.460 --> 00:11:04.080
instead of poll.options with the brackets.

265
00:11:04.080 --> 00:11:05.580
That's all that this allows.

266
00:11:05.580 --> 00:11:07.580
If you're not familiar with the property decorator,

267
00:11:07.580 --> 00:11:08.520
then I will leave a link

268
00:11:08.520 --> 00:11:10.680
in the resources section of this lecture.

269
00:11:10.680 --> 00:11:11.780
This is what I had in my notes,

270
00:11:11.780 --> 00:11:13.950
but I forgot to add it in earlier.

271
00:11:13.950 --> 00:11:16.530
All right, before moving on to adding the option class

272
00:11:16.530 --> 00:11:18.730
we're gonna cut it here and do this in the next video

273
00:11:18.730 --> 00:11:19.860
because this is getting a bit long.

274
00:11:19.860 --> 00:11:21.450
So, thank you guys for watching this video.

275
00:11:21.450 --> 00:11:22.973
I'll see you in the next one.

