-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflask.html
865 lines (732 loc) · 60.8 KB
/
flask.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>Flask</title>
<meta content="" name="description">
<meta content="" name="keywords">
<!-- Favicons -->
<link href="assets/img/Favicon-1.png" rel="icon">
<link href="assets/img/Favicon-1.png" rel="apple-touch-icon">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Raleway:300,300i,400,400i,500,500i,600,600i,700,700i|Poppins:300,300i,400,400i,500,500i,600,600i,700,700i" rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="assets/vendor/aos/aos.css" rel="stylesheet">
<link href="assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
<link href="assets/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
<link href="assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
<link href="assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
<!-- Creating a python code section-->
<link rel="stylesheet" href="assets/css/prism.css">
<script src="assets/js/prism.js"></script>
<!-- Template Main CSS File -->
<link href="assets/css/style.css" rel="stylesheet">
<!-- To set the icon, visit https://fontawesome.com/account-->
<script src="https://kit.fontawesome.com/5d25c1efd3.js" crossorigin="anonymous"></script>
<!-- end of icon-->
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<!-- =======================================================
* Template Name: iPortfolio
* Updated: Sep 18 2023 with Bootstrap v5.3.2
* Template URL: https://bootstrapmade.com/iportfolio-bootstrap-portfolio-websites-template/
* Author: BootstrapMade.com
* License: https://bootstrapmade.com/license/
======================================================== -->
</head>
<body>
<!-- ======= Mobile nav toggle button ======= -->
<i class="bi bi-list mobile-nav-toggle d-xl-none"></i>
<!-- ======= Header ======= -->
<header id="header">
<div class="d-flex flex-column">
<div class="profile">
<img src="assets/img/myphoto.jpeg" alt="" class="img-fluid rounded-circle">
<h1 class="text-light"><a href="index.html">Arun</a></h1>
<div class="social-links mt-3 text-center">
<a href="https://www.linkedin.com/in/arunp77/" target="_blank" class="linkedin"><i class="bx bxl-linkedin"></i></a>
<a href="https://github.com/arunp77" target="_blank" class="github"><i class="bx bxl-github"></i></a>
<a href="https://twitter.com/arunp77_" target="_blank" class="twitter"><i class="bx bxl-twitter"></i></a>
<a href="https://www.instagram.com/arunp77/" target="_blank" class="instagram"><i class="bx bxl-instagram"></i></a>
<a href="https://arunp77.medium.com/" target="_blank" class="medium"><i class="bx bxl-medium"></i></a>
</div>
</div>
<nav id="navbar" class="nav-menu navbar">
<ul>
<li><a href="index.html#hero" class="nav-link scrollto active"><i class="bx bx-home"></i> <span>Home</span></a></li>
<li><a href="index.html#about" class="nav-link scrollto"><i class="bx bx-user"></i> <span>About</span></a></li>
<li><a href="index.html#resume" class="nav-link scrollto"><i class="bx bx-file-blank"></i> <span>Resume</span></a></li>
<li><a href="index.html#portfolio" class="nav-link scrollto"><i class="bx bx-book-content"></i> <span>Portfolio</span></a></li>
<li><a href="index.html#skills-and-tools" class="nav-link scrollto"><i class="bx bx-wrench"></i> <span>Skills and Tools</span></a></li>
<li><a href="index.html#language" class="nav-link scrollto"><i class="bi bi-menu-up"></i> <span>Languages</span></a></li>
<li><a href="index.html#awards" class="nav-link scrollto"><i class="bi bi-award-fill"></i> <span>Awards</span></a></li>
<li><a href="index.html#professionalcourses" class="nav-link scrollto"><i class="bx bx-book-alt"></i> <span>Professional Certification</span></a></li>
<li><a href="index.html#publications" class="nav-link scrollto"><i class="bx bx-news"></i> <span>Publications</span></a></li>
<li><a href="index.html#extra-curricular" class="nav-link scrollto"><i class="bx bx-rocket"></i> <span>Extra-Curricular Activities</span></a></li>
<!-- <li><a href="#contact" class="nav-link scrollto"><i class="bx bx-envelope"></i> <span>Contact</span></a></li> -->
</ul>
</nav><!-- .nav-menu -->
</div>
</header><!-- End Header -->
<main id="main">
<!-- ======= Breadcrumbs ======= -->
<section id="breadcrumbs" class="breadcrumbs">
<div class="container">
<div class="d-flex justify-content-between align-items-center">
<h2>Data Engineering</h2><iframe src="https://github.com/sponsors/arunp77/button" title="Sponsor arunp77" height="32" width="114" style="border: 0; border-radius: 6px;"></iframe>
<ol>
<li><a href="Data-engineering.html" class="clickable-box">Content section</a></li>
<li><a href="index.html#portfolio" class="clickable-box">Portfolio section</a></li>
</ol>
</div>
</div>
</section><!-- End Breadcrumbs -->
<!------ right dropdown menue ------->
<div class="right-side-list">
<div class="dropdown">
<button class="dropbtn"><strong>Shortcuts:</strong></button>
<div class="dropdown-content">
<ul>
<li><a href="cloud-compute.html"><i class="fas fa-cloud"></i> Cloud</a></li>
<li><a href="AWS-GCP.html"><i class="fas fa-cloud"></i> AWS-GCP</a></li>
<li><a href="amazon-s3.html"><i class="fas fa-cloud"></i> AWS S3</a></li>
<li><a href="ec2-confi.html"><i class="fas fa-server"></i> EC2</a></li>
<li><a href="Docker-Container.html"><i class="fab fa-docker" style="color: rgb(29, 27, 27);"></i> Docker</a></li>
<li><a href="Jupyter-nifi.html"><i class="fab fa-python" style="color: rgb(34, 32, 32);"></i> Jupyter-nifi</a></li>
<li><a href="snowflake-task-stream.html"><i class="fas fa-snowflake"></i> Snowflake</a></li>
<li><a href="data-model.html"><i class="fas fa-database"></i> Data modeling</a></li>
<li><a href="sql-basics.html"><i class="fas fa-table"></i> QL</a></li>
<li><a href="sql-basic-details.html"><i class="fas fa-database"></i> SQL</a></li>
<li><a href="Bigquerry-sql.html"><i class="fas fa-database"></i> Bigquerry</a></li>
<li><a href="scd.html"><i class="fas fa-archive"></i> SCD</a></li>
<li><a href="sql-project.html"><i class="fas fa-database"></i> SQL project</a></li>
<!-- Add more subsections as needed -->
</ul>
</div>
</div>
</div>
<!-- ======= Portfolio Details Section ======= -->
<section id="portfolio-details" class="portfolio-details">
<div class="container">
<div class="row gy-4">
<h1>Flask: web development</h1>
<div class="col-lg-8">
<div class="portfolio-details-slider swiper">
<div class="swiper-wrapper align-items-center">
<figure>
<img src="assets/img/data-engineering/flask1.png" alt="" style="max-width: 50%; max-height: auto;">
<figcaption></figcaption>
</figure>
</div>
</div>
</div>
<div class="col-lg-4 grey-box">
<div class="section-title">
<h3>Table of Contents</h3>
<ol>
<li><a href="#introduction">Introduction to Apache Spark</a></li>
<li><a href="#how-it-works">How does Spark work?</a></li>
<ul>
<li><a href="#difference">Difference between Hadoop and Apache Spark</a></li>
<li><a href="#key-concept">Some key concepts of Apache Spark</a></li>
<li><a href="#key-features">Key Features</a></li>
</ul>
<li><a href="#Components">Components of Apache Spark</a></li>
<li><a href="#reference">Reference</a></li>
</ol>
</div>
</div>
</div>
<section>
<h3 id="introduction">Getting started with Flask</h3>
<a href="https://flask.palletsprojects.com/en/2.0.x/" target="_blank">Flask</a> is a famous Python framework for building web applications. Released in 2011, Flask has established itself as a reference for creating an API on Python. It stands out from <a href="https://www.djangoproject.com/" target="_blank">Django</a>, another famous framework used in Python, because of its lightness. Indeed, Flask is considered as a micro framework, you do not have to define the databases to use or the formatting. However with Flask, you create the core of your web application, then according to your need you add different services. That's why, in a few lines, we can easily display a Hello World on a web page without using an HTML file. (For more details on the flask, please checkout the repostiroy: <a href="https://github.com/arunp77/Data-engineering-tools/tree/main/Flask-application" target="_blank">Flask repository</a>.)
<!--------------->
<h4 id="steps">Flask application</h4>
<ol>
<li><strong>Installation of Flask:</strong> To install Flask, you just have to go through pip.
<pre><code class="language-bash">pip install Flask</code></pre>
</li>
<li><strong>Creating first flask application:</strong> Copy the following lines into a file <code>first_app.py</code>:
<pre><code class="language-python">
from flask import Flask
# Now create a instance of the FLask class, which will be the WGSI
# (WGSI: Web server Gateway interface) application
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World !"
if __name__=="__main__":
app.run(debug=True)
</code></pre>
where the directory structure of the project is:
<pre class="language-python">
Flask_app/
│
├── first_app.py
└── .env
</pre>
<p>Let's see in detail what we have done here. First, we instantiated an object of the Flask class. Then, with this object named app, we use it in the decorator <code>@app.route("/")</code>, to create a route (endpoint). Going to <code>/</code>, we get the result of the <code>hello</code> function, which simply returns a <code>Hello World !</code>. Thus, we can create several routes using the `<code>app</code>' variable.</p>
<p>Then set the environment variable FLASK_APP with the name of your python file : <code>export FLASK_APP=first_app.py </code> or you can also save the environment variables in <code>.env</code> file and Load the environment variables from <code>.env</code> file using: <code>load_dotenv()</code> (For better understanding, you can see my <a href="https://github.com/arunp77/Data-engineering-tools/tree/main/FLask" target="_blank">github repo</a>). To run the application, use following command in your terminal:</p>
<pre><code class="language-bash">flask run --host=0.0.0.0</code></pre>
On a web browser go to the address <code>ip_address:5000</code> (localhost:5000 if you are using your home machine), you should see a <code>"Hello World !"</code> message. Port <code>5000</code> is used by default on Flask, you can change the port via the <code>--port</code> flag when using <code>flask run</code>.
</li>
<li><strong>The DEBUG mode and the sent data format: </strong>It is to be noted here that upto this point, whenever, we change something in our <code>first_app.py</code>, the changes will not be refelcted even though we refresh the browser. So to see the changes, we need to stop the process everytime and restart the API everytime you modify the python file. To overcome the issue, we use <code>DEBUG</code> mode. Once, you have modified and saved your python script, by refreshing the web page, you get the desired change. To enable this mode, you need to set the <code>FLASK_ENV</code> environment variable to development. Also, once this mode is enabled, if your API encounters an error, the thrown Python exception will be displayed on the web page. Below, a quotation mark was missing in the string returned by the function and Flask informs us of this.
<figure>
<img src="assets/img/data-engineering/flask-error.png" alt="" style="max-width: 70%; max-height: auto;">
<figcaption></figcaption>
</figure>
To do this, we can again add following script to <code>.env</code> file:
<code>FLASK_ENV=development</code>
<figure>
<img src="assets/img/data-engineering/flask-env.png" alt="" style="max-width: 70%; max-height: auto;">
<figcaption></figcaption>
</figure>
Now we can run the following command to run the fast app script:
<code>python first_app.py</code>.
You can now find your web application as before. After that it is recommended to use flask run for the deployment of your application but also because the DEBUG mode is optimized there.
</li>
</ol>
<h4 id="types-functions">Types of the Flask functions</h4>
Flask is a lightweight and flexible web framework for Python, designed to make building web applications quick and easy. It follows the <a href="https://wsgi.tutorial.codepoint.net/intro" target="_blank">WSGI toolkit</a> and <a href="https://jinja.palletsprojects.com/en/3.1.x/" target="_blank">Jinja2</a> templating engine, providing developers with the tools needed to create web applications in a simple and elegant manner.
<ul>
<li><strong>Route Functions:</strong> These are the heart of a Flask application, handling incoming HTTP requests and returning appropriate responses. Route functions are decorated with <code>@app.route()</code> and are responsible for defining the behavior of specific URLs in the application.</li>
<pre><code class="language-python">
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello, World!'
@app.route('/about')
def about():
return 'About page'
if __name__ == '__main__':
app.run()
</code></pre>
<li><strong>View Functions:</strong> View functions are similar to route functions but are not tied to specific URLs. They encapsulate the logic for generating a particular piece of content or performing a specific action within the application. View functions are often called by route functions to generate responses.</li>
<pre><code class="language-python">
from flask import Flask, render_template
app = Flask(__name__)
def generate_content():
# Logic to generate content
return 'Dynamic content generated here.'
@app.route('/')
def index():
content = generate_content()
return render_template('index.html', content=content)
if __name__ == '__main__':
app.run()
</code></pre>
<li><strong>Error Handler Functions:</strong> Error handler functions handle exceptions or errors that occur during the processing of a request. Flask provides decorators such as <code>@app.errorhandler()</code> to define error handlers for specific HTTP status codes or exception types. These functions return customized error responses to the client.</li>
<pre><code class="language-python">
from flask import Flask, jsonify
app = Flask(__name__)
@app.errorhandler(404)
def page_not_found(error):
return jsonify({'error': 'Page not found'}), 404
if __name__ == '__main__':
app.run()
</code></pre>
<li><strong>Before and After Request Functions:</strong> Flask allows developers to execute code before and after each request. Functions decorated with <code>@app.before_request</code> are executed before any request is processed, while functions decorated with <code>@app.after_request</code> are executed after a response has been generated. These functions are commonly used for tasks such as setting up database connections or cleaning up resources.
<pre class="language-python"><code>
from flask import Flask, g
app = Flask(__name__)
@app.before_request
def before_request():
g.user = 'John' # Example: set up user authentication or database connection
@app.route('/')
def index():
user = g.user # Access user variable set in before_request
return f'Hello, {user}!'
if __name__ == '__main__':
app.run()
</code></pre>
</li>
<li><strong>Context Processor Functions:</strong> Context processor functions allow developers to inject additional variables into the context of template rendering. These functions are decorated with <code>@app.context_processor</code> and can provide dynamic data that is accessible to all templates rendered during a request.
<pre class="language-python"><code>
from flask import Flask, render_template, g
app = Flask(__name__)
@app.context_processor
def inject_user():
user = g.user if 'user' in g else None
return dict(user=user)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run()
</code></pre>
</li>
<li><strong>CLI Commands:</strong> Flask supports writing custom command-line interface (CLI) commands using the Flask-Script or Flask-CLI extensions. CLI commands are defined as functions decorated with <code>@app.cli.command()</code> and can be used to perform administrative tasks, database migrations, or other operations from the command line.
<pre class="language-python"><code>
from flask import Flask
import click
app = Flask(__name__)
@app.cli.command()
def hello():
click.echo('Hello, CLI!')
if __name__ == '__main__':
app.run()
</code></pre>
</li>
</ul>
<!---------------------->
<h4 id="http-requests">How to send the different HTTP requests with Flask?</h4>
HTTP (Hypertext Transfer Protocol) requests are used to communicate between a client and a server. In Python, Flask provides various methods to handle different types of HTTP requests. Here are the main methods related to HTTP requests in Flask:
<ol>
<li><strong>GET:</strong>The GET method is used to request data from a specified resource. It is the default method used by browsers when you click a link or type a URL into the browser's address bar. <strong>Example in Flask:</strong></li>
<pre class="language-python"><code>
from flask import Flask, request
app = Flask(__name__)
@app.route('/hello', methods=['GET'])
def hello():
name = request.args.get('name')
return f'Hello, {name}!'
if __name__ == '__main__':
app.run()
</code></pre>
So to get the output: <code>Hello Arun!</code>, you need to provide the 'name' in the request url: <code>http://localhost:5000/hello?name=Arun</code>. Similarly with the cURL tool, <code>curl -X GET "http://localhost:5000/hello?name=Arun"</code>
<li><strong>POST:</strong>The POST method is used to submit data to be processed to a specified resource. It is often used when submitting forms on web pages.<strong>Example in Flask:</strong></li>
<pre class="language-python"><code>
from flask import Flask, request
app = Flask(__name__)
@app.route("/hello_post", methods=["POST"])
def hello_post():
data = request.get_json()
return f"Hello {data['name']}!"
if __name__ == '__main__':
app.run()
</code></pre>
Unlike the GET method, the other methods do not offer the ability to send information from the provided address to your web browser. You are forced to use the curl command. So to send the dictionary <code>{"name" : "Daniel"}</code> to the <code>/hello_post</code> endpoint via <code>curl</code>:
<pre class="language-bash"><code>curl localhost:5000/hello_post -d '{"name": "Daniel"}' -H 'Content-Type: application/json' -X POST</code></pre>
It is common that the same route is accessible from several methods, so we can give an array of methods and define the route according to the chosen method. To do this, we use request again.
<pre class="language-python"><code>
from flask import Flask, request
app = Flask(__name__)
@app.route("/hello_post", methods=["POST", "GET"])
def hello_post_get():
if request.method == "POST":
data = request.get_json()
return f"Hello {data['name']}!"
if __name__ == '__main__':
app.run()
</code></pre>
<li><strong>PUT:</strong>The PUT method is used to update an existing resource or create a new resource if it does not exist. <strong>Example in Flask:</strong></li>
<pre class="language-python"><code>
from flask import Flask, request
app = Flask(__name__)
@app.route('/update', methods=['PUT'])
def update():
# Process update logic
return 'Resource updated successfully!'
if __name__ == '__main__':
app.run()
</code></pre>
<li><strong>DELETE</strong> The DELETE method is used to delete a specified resource. <strong>Example in Flask:</strong></li>
<pre class="language-python"><code>
from flask import Flask
app = Flask(__name__)
@app.route('/delete', methods=['DELETE'])
def delete():
# Process delete logic
return 'Resource deleted successfully!'
if __name__ == '__main__':
app.run()
</code></pre>
</ol>
<h5 id="example">Example:</h5>
Lets consider a example, where we want to show how to:
<ul>
<li>PUT <code>/add/users</code> will add the user with its data to the database.</li>
<li>POST <code>/update/users</code> will modify the data of an already existing user, otherwise the user will be added to the database.</li>
<li>GET <code>/users/<id></code> will give the information associated with the id user.</li>
<li>DELETE <code>/delete/<id></code> will delete the information associated with the id user</li>
</ul>
<pre class="line-numbers language-python" id="code-45" tabindex="0"><code class="language-python">
<span class="token keyword">from</span> flask <span class="token keyword">import</span> Flask
<span class="token keyword">from</span> flask <span class="token keyword">import</span> request
app <span class="token operator">=</span> Flask<span class="token punctuation">(</span>__name__<span class="token punctuation">)</span>
user <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">"/users/<id>"</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">get_user</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token keyword">return</span> user<span class="token punctuation">[</span><span class="token builtin">id</span><span class="token punctuation">]</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">"/add"</span><span class="token punctuation">,</span>methods<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">"PUT"</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">add_user</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
data <span class="token operator">=</span> request<span class="token punctuation">.</span>get_json<span class="token punctuation">(</span><span class="token punctuation">)</span>
user<span class="token punctuation">[</span><span class="token builtin">str</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token operator">=</span>data
<span class="token keyword">return</span> <span class="token string">"User {} has been added to the database."</span><span class="token punctuation">.</span><span class="token builtin">format</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">"/update/<id>"</span><span class="token punctuation">,</span>methods<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">"POST"</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">update_user</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token keyword">if</span> <span class="token builtin">id</span> <span class="token keyword">in</span> user<span class="token punctuation">:</span>
user<span class="token punctuation">[</span><span class="token builtin">id</span><span class="token punctuation">]</span> <span class="token operator">=</span> request<span class="token punctuation">.</span>get_json<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token string">"User {} has been modified"</span><span class="token punctuation">.</span><span class="token builtin">format</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token string">"User {} is missing from the database"</span><span class="token punctuation">.</span><span class="token builtin">format</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">"/delete/<id>"</span><span class="token punctuation">,</span>methods<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">"DELETE"</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">delete_user</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token keyword">if</span> <span class="token builtin">id</span> <span class="token keyword">in</span> user<span class="token punctuation">:</span>
<span class="token keyword">del</span> user<span class="token punctuation">[</span><span class="token builtin">id</span><span class="token punctuation">]</span>
<span class="token keyword">return</span> <span class="token string">"User {} has been deleted"</span><span class="token punctuation">.</span><span class="token builtin">format</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token string">"The user {} is absent from the database"</span><span class="token punctuation">.</span><span class="token builtin">format</span><span class="token punctuation">(</span><span class="token builtin">id</span><span class="token punctuation">)</span>
<span aria-hidden="true" class="line-numbers-rows"></code></pre>
<p>This Flask application defines routes to perform CRUD (Create, Read, Update, Delete) operations on a user database. Here are the commands you can use to interact with each route and see the output:</p>
<ul>
<li><strong>/users/<id> Route (Retrieve a User):</strong>
<pre class="language-python"><code>curl localhost:5000/users/1</code></pre>
Replace 1 with the ID of the user you want to retrieve.
</li>
<li><strong>/add Route (Add a User):</strong>
<pre class="language-python"><code>curl -X PUT "http://localhost:5000/add" -d '{"name": "John", "age": 30}' -H 'Content-Type: application/json'</code></pre>
This command adds a new user with the provided data. Replace {"name": "John", "age": 30} with the user data you want to add.
</li>
<li><strong>/update/<id> Route (Update a User):</strong>
<pre class="language-python"><code>curl -X POST "http://localhost:5000/update/1" -d '{"name": "Updated User", "age": 40}' -H 'Content-Type: application/json'</code></pre>
This command updates the user with the specified ID. Replace 1 with the ID of the user you want to update, and {"name": "Updated User", "age": 40} with the new data for the user.
</li>
<li><strong>/delete/<id> Route (Delete a User):</strong>
<pre class="language-python"><code>curl -X DELETE "http://localhost:5000/delete/1"</code></pre>
This command deletes the user with the specified ID. Replace 1 with the ID of the user you want to delete.
</li>
</ul>
</section>
<!----------------------->
<h3 id="passing-data">Passing data to an API</h3>
We saw how to create access points to our Flask API with the many HTTP methods. All we had to do was use the <code>route</code> decorator, and then define what the API does when it gets to the endpoint.
<ul>
<li><strong>Dynamic Route: </strong>We saw this first way of sending data:
<pre class="language-python"><code>
from flask import Flask
app = Flask(__name__)
@app.route("/hello/<name>")
def hello(name):
return "Hello {}".format(name)
# Do not consider this line </name>
</code></pre>
To run this <code>curl -X GET http://localhost:5000/hello/Arun</code>. However, it has not been named, this is what we call, a dynamic route. Indeed, unlike our first route where we always displayed Hello World, here we display Hello name with name the first name we indicate from the URI.
</li>
<li><strong>Data types:</strong> Moreover, we can specify the type of data we want.
<pre class="language-python"><code>
@app.route("/age/<int:age>")
def hello_age(age):
return "Hello, I am {} years old".format(age)
</code></pre>
<code>curl -X GET http://localhost:5000/age/12</code> can be used to see the port output on the endpoint.
<p>The types to characterize a data are the following:</p>
<table border="1">
<tr>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td>string</td>
<td>Type by default, accepts any text without /</td>
</tr>
<tr>
<td>int</td>
<td>Accepts natural numbers</td>
</tr>
<tr>
<td>float</td>
<td>Accepts positive numbers</td>
</tr>
<tr>
<td>path</td>
<td>Like the type string but accepts the /</td>
</tr>
<tr>
<td>uuid</td>
<td>Accepts strings UUID</td>
</tr>
</table>
</li>
<li><strong>Query string: </strong>As you know, the <code>GET</code> method has a specificity to send data, it is a query string (query parameters). Indeed, at the end of the URI and using a <code>?</code>, you can characterize a set of <strong>value keys</strong>. To execute this type of query, you need to use <code>Flask-Pydantic</code>, downloadable from <code>pip</code>:
<pre class="language-bash"><code>pip install Flask-Pydantic</code></pre>
</li>
<li><strong>Create the Class, and then validate the function:</strong>
<pre class="language-python"><code>
from flask import Flask
from pydantic import BaseModel
from flask_pydantic import validate
class Query(BaseModel):
name:str
age:int
app = Flask(__name__)
@app.route("/intro")
@validate()
def intro(query:Query):
return f"Hello, my name is {query.name} and I am {query.age} years old"
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True)
</code></pre>
When you go to <code>http://localhost:5000/intro?name=Arun&age=30</code>, you should see the sentence "Hello, my name is Arun and I am 30 years old". As in the previous section, this is a page that is modified according to the data transmitted in the URI.
<ul>
<li>To achieve this result, we can identify the new features. The first is the creation of a class inheriting from <code>BaseModel</code>. We have called it <code>Query</code> here, but you can name it anything you like. The attributes of the class correspond to what we want to send by query string. Flask does a type check, because if you put a string in <code>age</code>, you would get a <code>400</code> code error.</li>
<li>After defining your class, you need to add the <code>@validate</code> decorator after the route decorator. Without this decorator, you will get a Python error.</li>
<li>Finally, the function you linked with the decorators must take as argument an object of the class inherited by <code>BaseModel</code>, called <code>query</code> (a name other than query is problematic). From this <code>query</code> variable, you get the query parameters.</li>
</ul>
<strong>Example:</strong> Create a route that displays, in JSON format, that Damian Lillard is a point guard from Portland, born in 1990 using a query string
<pre class="language-python"><code>
from flask import Flask
from pydantic import BaseModel
from flask_pydantic import validate
class Player(BaseModel):
name:str
position:str
team:str
birth_year:int
app = Flask(__name__)
@app.route("/info")
@validate()
def info(query:Player):
return query.dict()
</code></pre>
Query following: <code>curl -X GET -i "localhost:5000/info?name=Damian%20Lillard&position=PG&team=Portland&birth_year=1990" </code> gives:
<figure>
<img src="assets/img/data-engineering/flask-query-basemodel.png" alt="" style="max-width: 70%; max-height: auto;">
<figcaption></figcaption>
</figure>
</li>
<li><strong>Request body:</strong> The idea is the same as before, make a new class inheriting from BaseModel, add the @validate decorator and get the information from the object. The only difference is that we do not use the GET method and we have to name the variable body instead of query.
You'll have to configure the class according to what you want to send via the POST method and specify in the route decorator that we send a POST method.
<pre class="language-python"><code>
from flask import Flask
from pydantic import BaseModel
from flask_pydantic import validate
class Player(BaseModel):
name:str
position:str
team:str
birth_year:int
app = Flask(__name__)
@app.route("/info",methods=["POST"])
@validate()
def info(body:Player):
return body.dict()
</code></pre>
Now if we use the: <code>curl -X 'POST' -i 'http://127.0.0.1:5000/info_post' -H 'Content-Type: application/json' -d '{ "birth_year": 1990, "name": "Damian Lillard", "position": "PG", "team":"Portland"}'</code>
<figure>
<img src="assets/img/data-engineering/flask-query-basemodel1.png" alt="" style="max-width: 70%; max-height: auto;">
<figcaption></figcaption>
</figure>
</li>
<li><strong>Header: </strong>
Data is present on the response header. Sometimes you need to retrieve this information. To do this, you need to go through the <code>request</code> object which has many attributes related to this header, such as <code>User_agent</code> accessible by the <code>user_agent</code> attribute. The list of attributes is available <a href="https://tedboy.github.io/flask/generated/generated/flask.Request.html#attributes" target="_blank">here</a>.
<p>If you do not want to go through the attributes of <code>request</code>, you can simply use the <code>headers</code> attribute of <code>request</code>, which will tell you the <code>User-Agent</code> as follows <code>request.headers["User-Agent"]</code>.</p>
<p>Even though the <code>headers</code> attribute behaves like a dictionary, its type is not, it is <code>werkzeug.datastructures.EnvironHeaders</code>. You can see this by creating a route that displays the type of <code>request.headers</code> and using curl.</p>
<pre class="language-python"><code>
from flask import request
@app.route("/head")
def head():
if request.headers.get("username"):
return "Hello {}".format(request.headers.get("username"))
elif request.headers.get("enterprise"):
return "Hello {}".format(request.headers.get("enterprise"))
else:
return "Hello World !"
</code></pre>
With the
<ul>
<li><code>curl -i localhost:5000/head -H 'enterprise: VisionAnalytica'</code> statement, you will get a <code>Hello VisionAnalytica</code>,</li>
<li>while with <code>curl -i localhost:5000/head -H 'username: Arun'</code>, we will get a <code>Hello Arun</code></li>
</ul>
</li>
</ul>
<!---------------------->
<h3 id="erros">Error and response handling</h3>
<ul>
<li>We have seen that the <code>DEBUG</code> mode displays the error encountered in the Python script, but this does not help the lambda user. You have to adapt the error message so that the user uses your API correctly. For example, let's say you have implemented an API for a Machine Learning model. A variable in your model expects a value between 0 and 10, but the user enters a value of 1000, your Machine Learning model will not work. You have to send a response adapted to the user so that the user puts a value between 0 and 10.</li>
<li>Similarly, we encountered an error code 404 when we wrote in a GET method that expected a natural integer instead of a string. However, we had to send a BadRequest error message of code 400.</li>
<li>That's why, when you create an API, you have to do some error handling too.</li>
<li>There are two ways to act when an error occurs:
<ol>
<li><strong>First method: </strong>The first way is to use the decorator <code>@app.errorhandler()</code>. You put it in front of your function as with the <code>@app.route()</code> decorator. All you have to do is specify the error code or the name of the error class imported from <code>werkzeug.exceptions</code> as an argument to the <code>errorhandler</code> decorator.
<pre class="language-python"><code>
from flask import request
@app.route("/head")
from flask import Flask
from werkzeug.exceptions import NotFound
app = Flask(__name__)
@app.route("/hello")
def hello():
return "Hello World"
@app.errorhandler(NotFound)
def handler_error404(err):
return "You have encountered an error of 404",404
</code></pre>
<ul>
<li>Now go to an address that returns a <code>404</code> error, for example the address <code>localhost:5000/helloname</code>. You will get the message from the <code>errorhandler</code> decorator function, and in the terminal's request history, you will get a 404 error (if you do not specify this code, the request will be coded 200). You can make a better page to indicate the error.</li>
<li>The <code>err</code> variable comes from the <code>NotFound</code> class, so you can make a better response through this variable.</li>
</ul>
</li>
<li><strong>Second method: </strong>The second way is to use the <code>register_error_handler()</code> method which takes two arguments. The first argument takes the error code or class name while the second argument takes the function that should be called on the error. The method must be called on the <code>app</code> variable.
<div class="important-box">Remove the <code>errorhandler</code> decorator and use the <code>register_error_handler()</code> function instead.
<pre class="language-python"><code>
def handler_error404(err):
return "You have encountered an error of 404",404
app.register_error_handler(404,handler_error404)
</code></pre>
Here we removed the decorator and added this snippet to the original python file.
</div>
Now let's take a example:
<pre class="language-python"><code>
@app.route("/age/<int: val>")
def age(val):
return f"Hello, I am {val} years old."
# Do not consider this line </int:>
</code></pre>
When we write a string after <code>/age/</code>, we get a <code>404</code> error instead of a Bad Request error representing that the user got the syntax wrong. There are several ways to return this error, the first is to send a tuple consisting of an error message and the code associated with our HTTP error. In this case, it is 400. With the route below, you can :
<pre class="language-python"><code>
@app.route("/age/<val>")
def age(val):
try:
return "Hello, I am {} years old".format(int(val))
except ValueError:
return "You did not enter an integer",400
# Do not consider this line </val>
</code></pre>
We can also import exceptions corresponding to HTTP errors from <code>werkzeug.exceptions</code>. Here we need to get the <code>BadRequest</code> exception and throw it using <code>raise</code>.
<pre class="language-python"><code>
from werkzeug.exceptions import BadRequest
@app.route("/age/<val>")
def age(val):
try:
return "Hello, I am {} years old".format(int(val))
except ValueError:
raise BadRequest("You did not enter an integer")
# Do not consider this line </val>
</code></pre>
Finally, we can simply use the <code>abort</code> function of flask and fill in the error message via the <code>description</code> argument of <code>abort</code>.
<pre class="language-python"><code>
from flask import abort
@app.route("/age/<val>")
def hello(val):
try:
return f"Hello, I am {int(val)} years old."
except ValueError:
abort(400,description="You did not enter an integer")
# Do not consider this line </val>
</code></pre>
</li>
</ol>
</li>
<li>Now let's take a example. Create a route "/random" that will return a random number between 0 and an integer end, but access is restricted to the user who will send by POST "name": "Daniel", but also the value of end. So you have to send the HTTP exception for bad authentication but also the exception for an incorrect value for end.</li>
<pre class="language-python"><code>
from flask import Flask, request
import random as ran
from werkzeug.exceptions import BadRequest, Unauthorized
app = Flask(__name__)
@app.route("/random", methods=["POST"])
def random():
data = request.get_json()
if data["name"] == "Daniel":
try:
return f"Your lucky number is {ran.randint(0, int(data['end']) + 1)}.\n"
except ValueError:
raise BadRequest("You did not enter an integer")
else:
raise Unauthorized("The user is not Daniel")
if __name__ == "__main__":
app.run(debug=True)
</code></pre>
To run the script, save this to a file <code>app.py</code> and then run in the command prompt using <code>python app.py</code>. Go to the Postman application to see the output.Follow the steps as follows:
<ol>
<li><strong>Create a POST Request: </strong>
<ul>
<li>In Postman, select the HTTP method as POST.</li>
<li>Enter the URL where your Flask application is running. By default, it should be <span style="color: blue;">http://localhost:5000/random</span>.</li>
<li>Click on the "Body" tab.</li>
<li>Select the "raw" option and set the format to JSON (application/json).</li>
<li>Enter the JSON payload in the request body. For example:</li>
<pre class="language-json"><code>
{
"name": "Daniel",
"end": 10
}
</code></pre>
</ul>
</li>
<li><strong>Send the Request:</strong> Click on the "Send" button to send the POST request to your Flask application.</li>
<li><strong>View the Response: </strong>You should receive a response from the Flask application in the Postman interface. If the conditions in the endpoint are met, you will see a response containing the lucky number. If not, you will receive an appropriate error message.</li>
<li><strong>Verify Output: </strong>Check the response body in Postman to see the output returned by the Flask application.</li>
</ol>
</ul>
<h3 id="response">Creating your responses</h3>
We have seen that the accepted formats of a function associated with a route are dictionaries, strings and tuples, but in fact Flask converts its types into a Flask specific format which is the <code>Response</code> class. To use this class, it is common to use the <code>make_response</code> function.
<pre class="language-python"><code>
from flask import make_response
from flask import Flask, render_template, request, abort
import os
# Get the current directory
current_directory = os.path.dirname(os.path.abspath(__file__))
app = Flask(__name__, template_folder=os.path.join(current_directory))
@app.route("/test")
def test():
return make_response("I use the function 'make_response'.")
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True)
</code></pre>
When compiled, this gave following message: <strong>I use the function 'make_response'.</strong> at route: <span style="color: blue;">http://127.0.0.1:5000/test</span>.
<div class="box">dsodso</div>
<!-------Reference ------->
<section id="reference">
<h2>References</h2>
<ol>
<li><a href="https://spark.apache.org/documentation.html" target="_blank"> Official Documentation</a></li>
<li><a href="https://www.databricks.com/learn/training/login" target="_blank">Databricks Learning Academy</a></li>
<li><a href="https://sparkbyexamples.com/" target="_blank">Spark by Examples</a></li>
<li><a href="https://www.datacamp.com/tutorial/pyspark-tutorial-getting-started-with-pyspark" target="_blank">Datacamp tutorial</a>.</li>
<li>For databricks, you can look at tutorial videos on youtube at <a href="https://www.youtube.com/watch?v=ChISx0-cMpU" target="_blank">youtube video by Bryan Cafferky</a>,
writer of the book "Master Azure Databricks". A great playlist for someone who just want to learn about the big data analytics at Databricks Azure cloud platform.</li>
<li>See the video for <a href="https://www.youtube.com/watch?v=_C8kWso4ne4" target="_blank">pyspark basics by Krish Naik</a>. Great video for starter.</li>
<li><a href="https://www.youtube.com/watch?v=QLGrLFOzMRw" target="_blank">Great youtube on Apache spark</a> one premise working.</li>
</ol>
</section>
<hr>
<div style="background-color: #f0f0f0; padding: 15px; border-radius: 5px;">
<h3>Some other interesting things to know:</h3>
<ul style="list-style-type: disc; margin-left: 30px;">
<li>Visit my website on <a href="sql-project.html">For Data, Big Data, Data-modeling, Datawarehouse, SQL, cloud-compute.</a></li>
<li>Visit my website on <a href="Data-engineering.html">Data engineering</a></li>
</ul>
</div>
<p></p>
<div class="navigation">
<a href="index.html#portfolio" class="clickable-box">
<span class="arrow-left">Portfolio section</span>
</a>
<a href="Data-engineering.html" class="clickable-box">
<span class="arrow-right">Content</span>
</a>
</div>
</div>
</section><!-- End Portfolio Details Section -->
</main><!-- End #main --
<!-- ======= Footer ======= -->
<footer id="footer">
<div class="container">
<div class="copyright">
© Copyright <strong><span>Arun</span></strong>
</div>
</div>
</footer><!-- End Footer -->
<a href="#" class="back-to-top d-flex align-items-center justify-content-center"><i class="bi bi-arrow-up-short"></i></a>
<!-- Vendor JS Files -->
<script src="assets/vendor/purecounter/purecounter_vanilla.js"></script>
<script src="assets/vendor/aos/aos.js"></script>
<script src="assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="assets/vendor/glightbox/js/glightbox.min.js"></script>
<script src="assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="assets/vendor/swiper/swiper-bundle.min.js"></script>
<script src="assets/vendor/typed.js/typed.umd.js"></script>
<script src="assets/vendor/waypoints/noframework.waypoints.js"></script>
<script src="assets/vendor/php-email-form/validate.js"></script>
<!-- Template Main JS File -->
<script src="assets/js/main.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
hljs.initHighlightingOnLoad();
});
</script>
</body>
</html>