Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d0f67bf

Browse files
committed
# Conflicts: # .gitignore # .idea/100web-course.iml
2 parents d9680c7 + e1699f6 commit d0f67bf

File tree

12 files changed

+223
-21
lines changed

12 files changed

+223
-21
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,4 @@ days/013-016-css-basics/demos/selectorville/.idea/selectorville.iml
174174
days/041-044-react/**node_modules
175175
.idea/100web-course.iml
176176
.idea/ruff.xml
177+
ruff.xml

.idea/100web-course.iml

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/ruff.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

days/001-004-flask-intro/code/demo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from program import app
1+
from program import app # noqa: F401
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from flask import Flask
2+
from program import routes # noqa: F401
23

34
app = Flask(__name__)
45

5-
from program import routes
6+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
click
2+
Flask
3+
itsdangerous
4+
Jinja2
5+
MarkupSafe
6+
python-dotenv
7+
werkzeug
Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,33 @@
1-
click==6.7
2-
Flask==1.0.2
3-
itsdangerous==0.24
4-
Jinja2>=2.10.1
5-
MarkupSafe==1.0
6-
python-dotenv==0.9.1
7-
werkzeug>=0.15.3
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.11
3+
# by the following command:
4+
#
5+
# pip-compile requirements.piptools
6+
#
7+
blinker==1.7.0
8+
# via flask
9+
click==8.1.7
10+
# via
11+
# -r requirements.piptools
12+
# flask
13+
flask==3.0.0
14+
# via -r requirements.piptools
15+
itsdangerous==2.1.2
16+
# via
17+
# -r requirements.piptools
18+
# flask
19+
jinja2==3.1.2
20+
# via
21+
# -r requirements.piptools
22+
# flask
23+
markupsafe==2.1.3
24+
# via
25+
# -r requirements.piptools
26+
# jinja2
27+
# werkzeug
28+
python-dotenv==1.0.0
29+
# via -r requirements.piptools
30+
werkzeug==3.0.1
31+
# via
32+
# -r requirements.piptools
33+
# flask

days/005-008-html5/demos/yahoo_clone/.idea/dictionaries/mkennedy.xml

Lines changed: 0 additions & 8 deletions
This file was deleted.

days/005-008-html5/demos/yahoo_clone/.idea/encodings.xml

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from typing import Optional
2+
3+
import fastapi
4+
import uvicorn
5+
6+
api = fastapi.FastAPI()
7+
8+
9+
@api.get('/')
10+
def index():
11+
body = "<html>" \
12+
"<body style='padding: 10px;'>" \
13+
"<h1>Welcome to the API</h1>" \
14+
"<div>" \
15+
"Try it: <a href='/api/calculate?x=7&y=11'>/api/calculate?x=7&y=11</a>" \
16+
"</div>" \
17+
"</body>" \
18+
"</html>"
19+
20+
return fastapi.responses.HTMLResponse(content=body)
21+
22+
23+
@api.get('/api/calculate')
24+
def calculate(x: int, y: int, z: Optional[int] = None):
25+
if z == 0:
26+
return fastapi.responses.JSONResponse(
27+
content={"error": "ERROR: Z cannot be zero."},
28+
status_code=400)
29+
30+
value = x + y
31+
32+
if z is not None:
33+
value /= z
34+
35+
return {
36+
'x': x,
37+
'y': y,
38+
'z': z,
39+
'value': value
40+
}
41+
42+
43+
# uvicorn was updated, and it's type definitions don't match FastAPI,
44+
# but the server and code still work fine. So ignore PyCharm's warning:
45+
# noinspection PyTypeChecker
46+
uvicorn.run(api, port=8000, host="127.0.0.1")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fastapi
2+
uvicorn
3+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Days 09-12 Building APIs with FastAPI
2+
3+
This exercise section is going to have you laughing, no doubt. You're going to use FastAPI to create an API that will return a random programming-related joke.
4+
5+
---
6+
7+
## Days 1-3: Watch the video lessons
8+
9+
The first segment of this 4-day block is to watch the videos and study FastAPI. Consider downloading and trying out the [code sample developed during the course](https://github.com/talkpython/100daysofweb-with-python-course/tree/master/days/009-012-modern-apis-with-fastapi/demo).
10+
11+
## Day 4: Funny Business
12+
13+
Now you have seen the videos from this chapter, you're ready to build an API using FastAPI!
14+
15+
We are going to use the [pyjokes](https://pyjok.es) package. This is usually marketed as a CLI tool to get a joke in your terminal. But it also [has an API](https://pyjok.es/api/). It's this API that we can use to build a joke API.
16+
17+
### Foundations
18+
19+
Before we talk about the details of your journey, let me give you a couple of foundational concepts from FastAPI so that you don't need to search the web *too* much (programming always involves some searching or AI-asking).
20+
21+
**FastAPI Starter Structure**
22+
23+
Simple FastAPI apps usually look something like this:
24+
25+
```python
26+
import fastapi
27+
import uvicorn
28+
29+
api = fastapi.FastAPI()
30+
31+
@api.get('/')
32+
def some_action():
33+
return {"message": "Hello"}
34+
35+
if __name__ == '__main__':
36+
uvicorn.run(api, port=8001, host="127.0.0.1")
37+
```
38+
39+
Incredible how simple these web apps are these days in their bare form.
40+
41+
**Passing data to actions**
42+
43+
The above api endpoint `some_action` is fun, but takes no data. If we wanted to pass a number, say `start_index`, we could do it like this using the `{}` wrappers in the URL:
44+
45+
```python
46+
@api.get('/{start_index}')
47+
def some_action(start_index):
48+
```
49+
50+
But this is a string and index implies an integer. We could parse it ourselves, but FastAPI does that for us with validation by simply specifying the type in code, some_action(start_index: **int**):
51+
52+
```python
53+
@api.get('/{start_index}')
54+
def some_action(start_index: int):
55+
```
56+
57+
**Constrained enums and string values**
58+
59+
Finally, in this exercise, you'll work with a small set of valid string values. For example, the pyjokes methods take a `category` of **neutral**, **all**, or **chuck** (as in Norris). We can express that way better with an enum (StrEnum specifically). Note: This type is only available in Python 3.11 or higher.
60+
61+
```python
62+
class JokeCategory(enum.StrEnum):
63+
all = 'all'
64+
chuck_norris = 'chuck'
65+
neutral = 'neutral'
66+
```
67+
68+
It's preferable to use this as the type in FastAPI because FastAPI will automatically reject all inputs that are not one of those three string values.
69+
70+
### Your Joke API
71+
72+
Use what we've given you above along with `pyjokes`, which you'll need to install as a dependency along with fastapi and uvicorn, to build a FastAPI that will listen at the URLs:
73+
74+
- `http://127.0.0.1:8001/api/laugh/chuck/en`
75+
- `http://127.0.0.1:8001/api/laugh/neutral/en`
76+
- `http://127.0.0.1:8001/api/laugh/chuck/es`
77+
78+
Passing in both the category and language (again see [the pyjokes API](https://pyjok.es/api/) for how to use it and valid inputs).
79+
80+
The response should be a JSON value such as:
81+
82+
```json
83+
{
84+
"category": "chuck",
85+
"language": "en",
86+
"joke": "Every SQL statement that Chuck Norris codes has an implicit 'COMMIT' in its end."
87+
}
88+
```
89+
90+
Be creative, explore and have fun. Remember: _the learning is in the practice_.
91+
92+
### Time to share what you've accomplished!
93+
94+
Be sure to share your last couple of days work on Twitter or Facebook. Use the hashtag **#100DaysOfWeb**.
95+
96+
Here are [some examples](https://twitter.com/search?q=%23100DaysOfCode) to inspire you. Consider including [@talkpython](https://twitter.com/talkpython) and [@pybites](https://twitter.com/pybites) in your tweets.
97+
98+
*See a mistake in these instructions? Please [submit a new issue](https://github.com/talkpython/100daysofweb-with-python-course/issues) or fix it and [submit a PR](https://github.com/talkpython/100daysofweb-with-python-course/pulls).*

0 commit comments

Comments
 (0)