1
00:00:00,179 --> 00:00:04,380
Hey welcome to this new lecture and I
hope you had an easy time trying to

2
00:00:04,380 --> 00:00:10,860
build the geocoding app. I know that
should have been tough but if they have

3
00:00:10,860 --> 00:00:15,389
gone through to a certain point,
that's great too. In this lecture now

4
00:00:15,389 --> 00:00:20,730
you'll get two things. The first thing is
you'll find the attachment in the resources

5
00:00:20,730 --> 00:00:25,859
of this lecture. There you'll find all
the files that contain the code for this

6
00:00:25,859 --> 00:00:31,859
web app. Specifically you'll find four
directories so static templates uploads

7
00:00:31,859 --> 00:00:39,300
and visual and also an app.py file.
Now here I happen to have four app

8
00:00:39,300 --> 00:00:45,210
files but basically the last one is the
final version so this is very basic

9
00:00:45,210 --> 00:00:50,850
version one where I just add a couple of
functions in a Python script and then I

10
00:00:50,850 --> 00:00:55,379
added some more to these functions and
then some more, and then I added, and then

11
00:00:55,379 --> 00:01:00,390
I eventually add some more code that
completed the applicationS. o this is

12
00:01:00,390 --> 00:01:07,770
what you get and you'll find this in a
zip file, so please download that!

13
00:01:07,770 --> 00:01:11,700
So that's the first thing you'll get in this
lecture, the zip file of the solution

14
00:01:11,700 --> 00:01:16,409
code and the second thing is I'll go
ahead now and explain how I approach

15
00:01:16,409 --> 00:01:20,670
this problem and I'll show you the code
and what I built first and second and

16
00:01:20,670 --> 00:01:28,409
third and so on. So these are the four
versions. I have version 1 when I

17
00:01:28,409 --> 00:01:34,799
added some code, 2, 3 and 4.
So let's ignore this for a moment because

18
00:01:34,799 --> 00:01:40,680
the first thing I want to explain is the
user interface so we'll start from the

19
00:01:40,680 --> 00:01:46,290
front end first. Now the first thing I
did though was creating a directory

20
00:01:46,290 --> 00:01:51,509
structure so I created an empty static
folder, templates, and uploads, and virtual.

21
00:01:51,509 --> 00:01:57,600
So static and templates are standard for
a Flask application and the uploads folder

22
00:01:57,600 --> 00:02:03,750
was just a folder where I generate these
intermediate files that the application

23
00:02:03,750 --> 00:02:08,479
makes available for download for the users.
You'll see that in just a bit.

24
00:02:08,479 --> 00:02:13,349
I also created this virtual folder there
which is actually the

25
00:02:13,349 --> 00:02:19,400
directory of the virtual environment so I
made that with Python with the n flag

26
00:02:19,400 --> 00:02:25,889
virtual env and virtual for the name of the
directory so if you execute that you'll get

27
00:02:25,889 --> 00:02:32,189
to this visual directory with a fresh
installation of Python and pip and

28
00:02:32,189 --> 00:02:38,549
other built in libraries and then I went ahead
and installed Flask and I installed

29
00:02:38,549 --> 00:02:43,139
Pandas because you will need Pandas to
read the data that the user is

30
00:02:43,139 --> 00:02:49,530
submitting and you want to calculate
some columns there and you also need geopy

31
00:02:49,530 --> 00:02:55,379
to geocode those values from the
pandas dataframe and yeah those are the

32
00:02:55,379 --> 00:03:00,569
three third-party libraries that you
need to install and once I created these

33
00:03:00,569 --> 00:03:07,319
empty directories, then I, the second
step was to create the user interface so

34
00:03:07,319 --> 00:03:14,060
what I did was I created an index dot
HTML template in the templates folder.

35
00:03:14,060 --> 00:03:21,599
So at first that was quite simple so it
didn't contain this much code. That

36
00:03:21,599 --> 00:03:31,620
simply contained like a total and some
headings there and also a basic form and

37
00:03:31,620 --> 00:03:36,870
initially I didn't put anything in the
action so when the user submits I had

38
00:03:36,870 --> 00:03:43,799
this submit button and I also have this
file type of input in there so if you

39
00:03:43,799 --> 00:03:50,340
can remember it file, this is the form
and we have this file input and the

40
00:03:50,340 --> 00:03:56,719
submit button, so these two and I also
restricted file submission to CSV only.

41
00:03:56,719 --> 00:04:03,359
And yeah, that's the form. I didn't
have this over the beginning so I won't

42
00:04:03,359 --> 00:04:06,409
go and explain this for now. I'll go
through this later.

43
00:04:06,409 --> 00:04:11,489
And yeah that was the interface.
Later I went and created this main

44
00:04:11,489 --> 00:04:19,799
dot CSS file, so here you'll find the
CSS styling for the web page. I won't go

45
00:04:19,799 --> 00:04:25,970
into this table this is quite self
explanatory so we have those CSS earlier

46
00:04:25,970 --> 00:04:30,890
in the course and this file is also included in the
resources among the other files, but I

47
00:04:30,890 --> 00:04:36,500
never expect that you have the same
styling so you may have some different

48
00:04:36,500 --> 00:04:43,280
things colors, or sizing and so on.
Then you go ahead and reference

49
00:04:43,280 --> 00:04:49,820
the CSS file to these head tags, yeah
basically that's what I did in that

50
00:04:49,820 --> 00:04:55,550
second step so first step creating a
directory and second step creating the basic

51
00:04:55,550 --> 00:05:01,220
interface and adding the CSS styling to
that. If you'll simply created the HTML

52
00:05:01,220 --> 00:05:05,960
code and then later when you finish our
application you create the CSS file

53
00:05:05,960 --> 00:05:10,250
that's perfectly okay too. Or even if you
started with a Python file directory,

54
00:05:10,250 --> 00:05:15,980
that's also fine. Some developers
start from the front and some start

55
00:05:15,980 --> 00:05:21,560
from the backend. That's perfectly okay.
Once I had the interface then I

56
00:05:21,560 --> 00:05:30,680
went ahead and created an app file
so an app.py file. These four

57
00:05:30,680 --> 00:05:35,840
versions are just for demonstration for
for this video so I made it for a

58
00:05:35,840 --> 00:05:40,430
different file to show you the stages
that I went through to build my final

59
00:05:40,430 --> 00:05:43,430
code.
So version 1. This is what I did

60
00:05:43,430 --> 00:05:50,750
basically. I imported these libraries so
from Flask I go to the usual Flask class

61
00:05:50,750 --> 00:05:58,310
and normally a render template method to
return HTML templates and I knew that in

62
00:05:58,310 --> 00:06:03,890
my application involves some user
submission so some post requests,

63
00:06:03,890 --> 00:06:09,200
therefore I included the request method
there as well and then the send

64
00:06:09,200 --> 00:06:17,060
file method which is used to send a file
to the browser for downloading. And yeah

65
00:06:17,060 --> 00:06:23,000
that's about Flask and then we want to
geocode data, right? So I uploaded from geopy

66
00:06:23,000 --> 00:06:28,580
geocoders I imported nominatiom and also
Pandas and once I imported the

67
00:06:28,580 --> 00:06:35,720
dependencies then I went ahead and created a
Flask instance just here and then three

68
00:06:35,720 --> 00:06:39,350
functions which for now they don't do
anything.

69
00:06:39,350 --> 00:06:44,240
So the first would be the homepage as
here with this backslash and I named

70
00:06:44,240 --> 00:06:51,350
that index, the function and I simply
return render template and of course

71
00:06:51,350 --> 00:06:57,530
here goes index dot HTML, so this will
render the home page which is index dot

72
00:06:57,530 --> 00:07:03,380
HTML and then the next thing that you might
expect is you know the user is in the

73
00:07:03,380 --> 00:07:08,510
web page and once the user presses the
choose fall button and they select

74
00:07:08,510 --> 00:07:13,730
a file and then they press submit, what you
want to do when they press the submit

75
00:07:13,730 --> 00:07:20,300
button is you want now to load that file
in Python and you want to read that as a

76
00:07:20,300 --> 00:07:26,330
Panda's data frame and you want to calculate
a coordinates column where you calculate

77
00:07:26,330 --> 00:07:30,860
the latitude along longitude from the
address column using geopy

78
00:07:30,860 --> 00:07:35,360
and then out of coordinates column you
want to calculate latitude and longitude.

79
00:07:35,360 --> 00:07:41,300
So we have done this previously in the
course, in the Pandas section and then

80
00:07:41,300 --> 00:07:45,620
eventually you want to return a data
frame and you want to send that data

81
00:07:45,620 --> 00:07:52,040
frame via a render template method, you
want to send that data frame here, down

82
00:07:52,040 --> 00:07:56,630
here so what we're talking here is
we're talking about creating a function

83
00:07:56,630 --> 00:08:02,090
that does all this so it reads the csv file
and processes it with Pandas and then it

84
00:08:02,090 --> 00:08:08,330
displays the table. The data frame is a
table. I created the such a function

85
00:08:08,330 --> 00:08:14,900
and call it success table. If you
remember that has to be, has to have

86
00:08:14,900 --> 00:08:20,980
these methods parameter equal to post
because we are expecting a post request

87
00:08:20,980 --> 00:08:28,730
and then we have yet another function.
I call this download file so that's the URL

88
00:08:28,730 --> 00:08:36,710
success dash table and this is a function
name. Then we have yet another URL and

89
00:08:36,710 --> 00:08:42,099
another function attached to that URL so
I call this download. Again as I said

90
00:08:42,099 --> 00:08:48,440
every time the user does something you
want to create a decorator and a function

91
00:08:48,440 --> 00:08:52,529
attached to that. So first the user will do
a submission and you want

92
00:08:52,529 --> 00:08:58,319
capture that in this function, the
success table and the next thing that

93
00:08:58,319 --> 00:09:02,639
the user will do is it will press the
download button that will be displayed

94
00:09:02,639 --> 00:09:08,430
down here and that has to trigger
another function in Python and that

95
00:09:08,430 --> 00:09:13,920
has to trigger the send file method
in Python so that we send the file to

96
00:09:13,920 --> 00:09:19,680
the user. That means we need another
function here called download at least

97
00:09:19,680 --> 00:09:25,879
that's how I named it. And yeah, let's go
to version 2 now so see the difference

98
00:09:25,879 --> 00:09:32,329
here and here the index function remains
the same so that's all we do for index.

99
00:09:32,329 --> 00:09:38,160
It's quite simple we simply return the
initial index of this HTML template and then

100
00:09:38,160 --> 00:09:44,189
here I've added quite a lot of code and
basically what we have is we check for

101
00:09:44,189 --> 00:09:50,309
the requests. If we got a post requests
then I get the file using request dot

102
00:09:50,309 --> 00:10:01,379
files and file here is the name of the input
in here. So yeah what happens is that

103
00:10:01,379 --> 00:10:07,259
when the user presses the submit button,
this one here, the URL is triggered and

104
00:10:07,259 --> 00:10:16,050
that URL is URL for the success
underscore table function. See this

105
00:10:16,050 --> 00:10:22,199
function here. That means this function
will be executed and then we create a

106
00:10:22,199 --> 00:10:28,350
data frame there which will read the
file, this file that we're getting from

107
00:10:28,350 --> 00:10:35,160
the user, from the user form and then we
do this Nominatim and we create a data

108
00:10:35,160 --> 00:10:42,240
frame column there. You know this from
the Pandas section. We use the apply method

109
00:10:42,240 --> 00:10:48,449
and then apply the geo code to the
address column and then out of the

110
00:10:48,449 --> 00:10:56,910
coordinates column I get a latitude
column and I use a lambda function to

111
00:10:56,910 --> 00:11:03,209
extra the latitude from each of
coordinates rows. I also count for non

112
00:11:03,209 --> 00:11:06,490
values there.
And then I don't need this coordinates

113
00:11:06,490 --> 00:11:13,120
column so I just drop that using the
drop method and then I convert this to a

114
00:11:13,120 --> 00:11:19,300
CSV so here I'm generating a CSV file
this is the output that we want to

115
00:11:19,300 --> 00:11:24,490
give to the user and I'm storing this in
the uploads folder so you just need to

116
00:11:24,490 --> 00:11:30,190
pass the path there, the relative path
uploads slash geocoded. That's how I'm

117
00:11:30,190 --> 00:11:34,990
naming this at the moment. Later I'll do
something more advanced.

118
00:11:34,990 --> 00:11:41,769
so let's name it geocoded for
now dot csv. Then what this will do

119
00:11:41,769 --> 00:11:48,730
it will return a template so it will
return the index.html template, but then

120
00:11:48,730 --> 00:11:57,850
if you look here, let me open this to
another view. Yeah, here we have a division.

121
00:11:57,850 --> 00:12:03,940
Note the jinja2 syntax that I'm using there.
so I'm including the BTN variable, I'm

122
00:12:03,940 --> 00:12:09,399
ignoring where that is missing. Now this
is different from here up here. Here I am

123
00:12:09,399 --> 00:12:17,290
returning a HTML as a string and here I'm
returning an HTML template, so the syntax

124
00:12:17,290 --> 00:12:23,079
is different and this is also different
from when we use extent so when we're

125
00:12:23,079 --> 00:12:28,420
extending a layout. You have send a
layout when you want that as soon as

126
00:12:28,420 --> 00:12:33,790
user visits let's say the index dot HTML
template, the index dot HTML template

127
00:12:33,790 --> 00:12:39,459
will display other HTML templates so it
will extend as the as soon as user with

128
00:12:39,459 --> 00:12:44,860
that index dot HTML page, so the home
page. This is different because we don't

129
00:12:44,860 --> 00:12:49,569
want this to be displayed right away.
That's why you're saying ignore missing

130
00:12:49,569 --> 00:12:55,930
So ignore that when it's missing and
included only when the user is visiting

131
00:12:55,930 --> 00:13:01,329
this success
dash table URL and when the user

132
00:13:01,329 --> 00:13:07,000
visits that so when the user press submit
after having submitted a file, then you

133
00:13:07,000 --> 00:13:12,310
want to render this dot HTML
template so what this contains is a

134
00:13:12,310 --> 00:13:17,620
button here. You want to generate a
button there

135
00:13:17,620 --> 00:13:25,680
which would be you know just file and submit
so you get this download file in there

136
00:13:30,940 --> 00:13:37,870
and you also get the HTML table so the
data frame as an HTML table, so the first

137
00:13:37,870 --> 00:13:46,120
row, the second row. The first row, the second
row and yeah that bottom now is

138
00:13:46,120 --> 00:13:51,700
attached to a reference which suggests
that when the user presses download

139
00:13:51,700 --> 00:14:01,690
the URL for the Python download function
will be visited so we go here and this URL

140
00:14:01,690 --> 00:14:08,020
or the download function will be visited.
And now what we want to do when the user

141
00:14:08,020 --> 00:14:16,620
visits this URL is and we want to return
a sent file method. Actually this should be

142
00:14:16,620 --> 00:14:26,410
uploads geocoded dot csv so we
want to send to the user the file that

143
00:14:26,410 --> 00:14:31,990
we generated up here earlier
in this function. We want to send

144
00:14:31,990 --> 00:14:37,630
that user to the user under the name
your file dot csv and also as

145
00:14:42,070 --> 00:14:47,380
the previous lectures. Yeah, that's about
the download dot HTML template. Yeah,

146
00:14:47,380 --> 00:14:52,180
you're basically done. You can get
away with this version of program and

147
00:14:52,180 --> 00:14:58,540
it'll be almost excellent if you went this
far, however we may have some small

148
00:14:58,540 --> 00:15:05,410
problems with this. The problem would be
you know if you choose a file, a csv file

149
00:15:05,410 --> 00:15:12,850
fall that doesn't have an address column
inside so a column named address then

150
00:15:12,850 --> 00:15:19,330
what would happen is you'd be able to
load that fall as a data frame and then

151
00:15:19,330 --> 00:15:24,850
when you try to create a new column in
the data frame called coordinates and

152
00:15:24,850 --> 00:15:30,210
then you try to access an existing
column named address in the data frame

153
00:15:30,210 --> 00:15:33,899
Python will
throw an error and it will stop the

154
00:15:33,899 --> 00:15:40,050
application. That means when the user
visits the success table URL they will

155
00:15:40,050 --> 00:15:46,079
be shown an error page and that is not
very user-friendly so what you might

156
00:15:46,079 --> 00:15:51,809
want to do instead is you may add some
functionality here that checks if the

157
00:15:51,809 --> 00:15:56,369
data frame, if the csv file entered by the
users so you want to read the file as a

158
00:15:56,369 --> 00:16:01,739
data frame and then in the data frame
check if you have an address column.

159
00:16:01,739 --> 00:16:05,220
If you have one then you go ahead and do
the calculations, but if you don't then

160
00:16:05,220 --> 00:16:12,360
you return something to the user so
instead of returning DF to HTML you

161
00:16:12,360 --> 00:16:17,160
return a message saying that sorry you
don't have such a column in your

162
00:16:17,160 --> 00:16:21,000
csv file, so yeah I'll show you the code
for that in the next lecture, so see you!

