1
00:00:00,328 --> 00:00:02,099
- [Narrator] Hi and
welcome back to the course.

2
00:00:02,099 --> 00:00:03,315
In this video we're going to do

3
00:00:03,315 --> 00:00:06,507
what we did in the last,
but with the UserModel.

4
00:00:06,507 --> 00:00:08,867
We're going to be using the
SQLAlchemy methods there

5
00:00:08,867 --> 00:00:11,523
to make things a bit simpler.

6
00:00:11,523 --> 00:00:14,690
Let's start by going to the UserModel.

7
00:00:15,971 --> 00:00:20,298
Now, as we now know, there
are a lot better ways

8
00:00:20,298 --> 00:00:22,483
of doing this sort of stuff

9
00:00:22,483 --> 00:00:24,566
than what we've got here.

10
00:00:27,235 --> 00:00:29,947
How would you change this code

11
00:00:29,947 --> 00:00:32,371
to return the user that matches

12
00:00:32,371 --> 00:00:35,371
the username passing as an argument?

13
00:00:40,602 --> 00:00:42,227
Hopefully you got that.

14
00:00:42,227 --> 00:00:44,403
And if not, do pause the
video and give it a go.

15
00:00:44,403 --> 00:00:47,526
Look at the last video, and
it will give you a hint.

16
00:00:47,526 --> 00:00:49,819
But, it's really a lot simpler

17
00:00:49,819 --> 00:00:52,819
with SQLAlchemy than it is manually.

18
00:00:53,707 --> 00:00:56,659
We're going to return cls.query,

19
00:00:56,659 --> 00:00:59,706
and that's going to return
us the query builder

20
00:00:59,706 --> 00:01:03,706
that essentially returns
Select star From users.

21
00:01:04,843 --> 00:01:07,010
Which isn't a valid thing.

22
00:01:08,003 --> 00:01:12,011
We cannot do that because
that's just a query builder.

23
00:01:12,011 --> 00:01:14,587
And the query builder is an object,

24
00:01:14,587 --> 00:01:16,987
which allows us to build queries.

25
00:01:16,987 --> 00:01:18,867
And, the first part of this query

26
00:01:18,867 --> 00:01:21,155
is going to be filter_by.

27
00:01:21,155 --> 00:01:23,587
Username is username.

28
00:01:23,587 --> 00:01:26,979
This username here is the table name

29
00:01:26,979 --> 00:01:29,339
by which we are filtering.

30
00:01:29,339 --> 00:01:32,539
And this username there is the argument.

31
00:01:32,539 --> 00:01:33,622
It's rather confusing in Atom

32
00:01:33,622 --> 00:01:35,734
because these two are the same colour.

33
00:01:35,734 --> 00:01:38,806
But nevertheless, this one is this one.

34
00:01:38,806 --> 00:01:40,307
Now that we've filtered,

35
00:01:40,307 --> 00:01:42,532
we have to retrieve the one value

36
00:01:42,532 --> 00:01:43,923
that we should have returned.

37
00:01:43,923 --> 00:01:46,419
There shouldn't be two users
with the same username,

38
00:01:46,419 --> 00:01:48,075
so we know there's only gonna be one.

39
00:01:48,075 --> 00:01:51,003
So we're gonna get the
first item returned.

40
00:01:51,003 --> 00:01:54,667
The first row returned, and
that gets the first row,

41
00:01:54,667 --> 00:01:58,834
and SQLAlchemy then converts
it to a UserModel object.

42
00:02:00,011 --> 00:02:02,435
Similarly with find_by_id,

43
00:02:02,435 --> 00:02:05,852
we're going to do exactly the same thing.

44
00:02:07,579 --> 00:02:09,467
But in here we're filtering by id,

45
00:02:09,467 --> 00:02:12,667
which is the column name,
and the value is _id,

46
00:02:12,667 --> 00:02:14,947
which is the argument name.

47
00:02:14,947 --> 00:02:18,554
Now remember mentioning, I
don't like calling things id,

48
00:02:18,554 --> 00:02:21,971
because that is a built in Python method.

49
00:02:23,274 --> 00:02:25,842
And in the case of SQLAlchemy
there's no real way

50
00:02:25,842 --> 00:02:27,218
of avoiding it.

51
00:02:27,218 --> 00:02:29,322
We could call the column _id,

52
00:02:29,322 --> 00:02:30,378
but that would be a bit weird

53
00:02:30,378 --> 00:02:33,250
when it comes to looking
at your SQL database.

54
00:02:33,250 --> 00:02:34,875
So it doesn't, it's not a problem

55
00:02:34,875 --> 00:02:36,594
if you use it like that,

56
00:02:36,594 --> 00:02:39,761
because we're not using the id method,

57
00:02:41,194 --> 00:02:43,170
the built in method anywhere else.

58
00:02:43,170 --> 00:02:47,778
But if we did, then there
would be some confusion there.

59
00:02:47,778 --> 00:02:49,695
Okay? But this is fine.

60
00:02:50,536 --> 00:02:53,304
And now we've got the filtering there.

61
00:02:53,304 --> 00:02:56,736
Notice that this is going
to be a bit strange,

62
00:02:56,736 --> 00:02:59,569
but this UserModel here is an API.

63
00:03:03,760 --> 00:03:06,593
Now, some eyebrow raising moments.

64
00:03:07,864 --> 00:03:09,114
This is an API.

65
00:03:09,992 --> 00:03:13,840
It's not a rest API, but it is an API.

66
00:03:13,840 --> 00:03:18,536
And this API exposes at
the moment two endpoints.

67
00:03:18,536 --> 00:03:20,304
Two methods.

68
00:03:20,304 --> 00:03:21,536
The find_by_username method,

69
00:03:21,536 --> 00:03:23,736
and the find_by_id method.

70
00:03:23,736 --> 00:03:26,952
This API, these two methods there,

71
00:03:26,952 --> 00:03:30,952
are an interface for other
parts of our programme,

72
00:03:31,833 --> 00:03:34,500
to interact with the user thing.

73
00:03:36,112 --> 00:03:38,192
And that includes writing it to a database

74
00:03:38,192 --> 00:03:41,025
and retrieving it from a database.

75
00:03:42,344 --> 00:03:45,488
As long as we don't change the API,

76
00:03:45,488 --> 00:03:48,160
we don't have to worry about the impact

77
00:03:48,160 --> 00:03:51,456
of our changes anywhere else in the code.

78
00:03:51,456 --> 00:03:52,289
And what I mean with that is

79
00:03:52,289 --> 00:03:55,496
we are using this API,
find_by_username and find_by_id,

80
00:03:55,496 --> 00:03:59,336
in the security file,
here at the UserModel.

81
00:03:59,336 --> 00:04:02,593
Now we've changed the
implementation of our API,

82
00:04:02,593 --> 00:04:05,328
but security.py doesn't care.

83
00:04:05,328 --> 00:04:06,744
Because it's just calling the methods,

84
00:04:06,744 --> 00:04:09,816
and as long as the methods
return the same thing,

85
00:04:09,816 --> 00:04:11,399
everything is fine.

86
00:04:12,672 --> 00:04:14,648
So as you can see, our API,

87
00:04:14,648 --> 00:04:17,289
our rest APIs are the same.

88
00:04:17,289 --> 00:04:21,088
We have our endpoints, and
the web or mobile application

89
00:04:21,088 --> 00:04:22,288
interacting with those endpoints

90
00:04:22,288 --> 00:04:26,288
doesn't care if it's written
in Python or in Ruby.

91
00:04:26,288 --> 00:04:28,816
All it cares is that it's
getting the data back

92
00:04:28,816 --> 00:04:32,985
that it requested, in the
same formats that it expects.

93
00:04:32,985 --> 00:04:33,818
And this is the same thing.

94
00:04:33,818 --> 00:04:35,728
This is also an API.

95
00:04:35,728 --> 00:04:38,232
It's an Application Programming Interface.

96
00:04:38,232 --> 00:04:41,376
And the security.py uses
this interface to communicate

97
00:04:41,376 --> 00:04:44,424
with the user and the database.

98
00:04:44,424 --> 00:04:46,152
In the case of mobile and web apps,

99
00:04:46,152 --> 00:04:48,088
they may use our rest API

100
00:04:48,088 --> 00:04:52,736
to communicate with a database
and store items and users.

101
00:04:52,736 --> 00:04:55,480
So as you can see, the same layout

102
00:04:55,480 --> 00:04:58,512
of programming concepts
applies pretty much everywhere,

103
00:04:58,512 --> 00:05:00,552
everywhere you look.

104
00:05:00,552 --> 00:05:02,832
Now that we're here, I'm also going to add

105
00:05:02,832 --> 00:05:07,313
the save_to_db method, and
you know how this goes.

106
00:05:07,313 --> 00:05:10,312
So I would encourage you to
do this on your own first.

107
00:05:10,312 --> 00:05:14,479
As always, just to make sure
to reinforce the concepts.

108
00:05:17,176 --> 00:05:18,056
And I'm sure you got it.

109
00:05:18,056 --> 00:05:19,723
Db.session.add self.

110
00:05:21,216 --> 00:05:23,800
And db.session.commit.

111
00:05:23,800 --> 00:05:26,088
As a refresher, if you
want to remove something

112
00:05:26,088 --> 00:05:28,008
from the database instead of add it,

113
00:05:28,008 --> 00:05:30,672
you would just put delete there.

114
00:05:30,672 --> 00:05:31,800
Okay?

115
00:05:31,800 --> 00:05:34,616
Now let's go over to the User Resource,

116
00:05:34,616 --> 00:05:37,368
and we're going to make
a couple of changes here,

117
00:05:37,368 --> 00:05:40,618
that are gonna make things a bit nicer.

118
00:05:41,528 --> 00:05:43,328
The parser is not gonna change,

119
00:05:43,328 --> 00:05:46,144
because that's part of flask-restful,

120
00:05:46,144 --> 00:05:48,520
and this resource is concerned

121
00:05:48,520 --> 00:05:51,504
with getting the data
correctly from the request.

122
00:05:51,504 --> 00:05:53,216
So that's not going to change.

123
00:05:53,216 --> 00:05:54,776
This here, isn't gonna change,

124
00:05:54,776 --> 00:05:57,880
because we've changed
the way find_by_username

125
00:05:57,880 --> 00:05:59,825
is implemented as I just mentioned,

126
00:05:59,825 --> 00:06:03,184
but it still returns a
user object, or none.

127
00:06:03,184 --> 00:06:06,328
So, the User Resource doesn't care

128
00:06:06,328 --> 00:06:08,592
how it was implemented.

129
00:06:08,592 --> 00:06:10,232
But what is gonna change is all this here,

130
00:06:10,232 --> 00:06:13,096
because we've now given the UserModel

131
00:06:13,096 --> 00:06:15,346
and extra power in our API.

132
00:06:18,104 --> 00:06:20,768
So we can say user equals UserModel.

133
00:06:20,768 --> 00:06:22,184
And then we can create the UserModel

134
00:06:22,184 --> 00:06:26,101
from the data, with our
username data password.

135
00:06:28,768 --> 00:06:31,272
And then we can just
save it to the database,

136
00:06:31,272 --> 00:06:32,689
save_to_db there.

137
00:06:34,312 --> 00:06:35,736
And that's it.

138
00:06:35,736 --> 00:06:38,136
Do remember, now that we're here as well,

139
00:06:38,136 --> 00:06:42,303
as a recap, that you could
simplify this line there.

140
00:06:45,568 --> 00:06:47,376
Take a moment to think about how you

141
00:06:47,376 --> 00:06:49,959
could simplify this line there.

142
00:06:54,256 --> 00:06:58,080
Well, the UserModel should take a username

143
00:06:58,080 --> 00:06:59,330
and a password.

144
00:07:00,576 --> 00:07:02,344
Let me check that it does.

145
00:07:02,344 --> 00:07:04,248
Okay, the UserModel right
now takes an id as well,

146
00:07:04,248 --> 00:07:06,552
but we don't need that.

147
00:07:06,552 --> 00:07:07,608
Apologies.

148
00:07:07,608 --> 00:07:12,200
The UserModel takes in a
username and a password.

149
00:07:12,200 --> 00:07:14,240
So, we could simplify this because

150
00:07:14,240 --> 00:07:16,848
this is a dictionary with a key username

151
00:07:16,848 --> 00:07:20,352
and a key password, and each
one has their own value.

152
00:07:20,352 --> 00:07:24,352
So we could unpack this,
and pass it in as data.

153
00:07:25,688 --> 00:07:26,704
And what that does is that

154
00:07:26,704 --> 00:07:28,920
that essentially does the same thing.

155
00:07:28,920 --> 00:07:32,016
This says, for each of the keys in data,

156
00:07:32,016 --> 00:07:34,464
say username equals the value,

157
00:07:34,464 --> 00:07:36,328
password equals the value, and so on.

158
00:07:36,328 --> 00:07:38,704
And because we're using a parser,

159
00:07:38,704 --> 00:07:42,376
we know that it always is gonna
have username and password.

160
00:07:42,376 --> 00:07:44,936
It's never gonna have anything else,

161
00:07:44,936 --> 00:07:46,697
or anything less.

162
00:07:46,697 --> 00:07:48,312
So it's always gonna have those two.

163
00:07:48,312 --> 00:07:49,448
Now let's go back to the UserModel

164
00:07:49,448 --> 00:07:52,504
and I'll quickly explain why
I got rid of the id there.

165
00:07:52,504 --> 00:07:55,312
The id is a primary
key as defined up here,

166
00:07:55,312 --> 00:07:57,792
which means it is auto incrementing.

167
00:07:57,792 --> 00:08:01,688
Whenever we insert a new
row into the database,

168
00:08:01,688 --> 00:08:05,048
the SQL engine we use, SQLite in our case,

169
00:08:05,048 --> 00:08:07,592
but it could be Postgres, or MySQL,

170
00:08:07,592 --> 00:08:10,640
will automatically assign an id for us.

171
00:08:10,640 --> 00:08:12,944
So, we don't have to do it ourselves.

172
00:08:12,944 --> 00:08:17,432
And when we create the
object through SQLAlchemy,

173
00:08:17,432 --> 00:08:19,932
the id is given to us as well.

174
00:08:20,952 --> 00:08:23,864
So SQLAlchemy would give us self.id,

175
00:08:23,864 --> 00:08:25,976
but when we create the object,

176
00:08:25,976 --> 00:08:28,272
we don't have to specify an id,

177
00:08:28,272 --> 00:08:30,217
because it is automatically generated.

178
00:08:30,217 --> 00:08:34,184
So it doesn't make sense
for us to give an id there.

179
00:08:34,184 --> 00:08:37,000
If we didn't want the id
to be auto incrementing,

180
00:08:37,000 --> 00:08:39,040
we could assign an id.

181
00:08:39,040 --> 00:08:41,736
And then that would be
used as the id value.

182
00:08:41,736 --> 00:08:44,712
For example, if you guys
are familiar with UUIDs,

183
00:08:44,712 --> 00:08:46,392
Universally Unique Identifiers,

184
00:08:46,392 --> 00:08:49,504
we could use those as ids instead

185
00:08:49,504 --> 00:08:52,048
of the automatically generated ids.

186
00:08:52,048 --> 00:08:54,680
If you're not familiar
with what an UUID is,

187
00:08:54,680 --> 00:08:55,672
don't worry.

188
00:08:55,672 --> 00:08:57,360
Just know that you could
put in your value there

189
00:08:57,360 --> 00:09:01,696
if you wanted, instead of
using the generated one.

190
00:09:01,696 --> 00:09:03,328
And for those of you that are interested,

191
00:09:03,328 --> 00:09:07,008
a UUID is a Universally Unique Identifier.

192
00:09:07,008 --> 00:09:09,296
Essentially a very long list, not a list,

193
00:09:09,296 --> 00:09:13,544
a very long string of numbers
and characters and dashes.

194
00:09:13,544 --> 00:09:15,520
And that is meant to be universally unique

195
00:09:15,520 --> 00:09:17,187
in your application.

196
00:09:18,784 --> 00:09:21,704
Okay, so that's everything for this video.

197
00:09:21,704 --> 00:09:25,760
We have changed the
implementation of our UserModel.

198
00:09:25,760 --> 00:09:29,496
But, our resource
essentially stays the same.

199
00:09:29,496 --> 00:09:31,880
So it's still, postman should work

200
00:09:31,880 --> 00:09:34,952
in exactly the same way, so
you can go ahead an try that.

201
00:09:34,952 --> 00:09:37,073
And nothing else should have changed.

202
00:09:37,073 --> 00:09:38,528
So that's everything for this video.

203
00:09:38,528 --> 00:09:39,832
Hope you enjoyed that,

204
00:09:39,832 --> 00:09:41,981
and I'll see you in the next one.

