Skip to content

Commit 1701703

Browse files
authored
Merge pull request #161 from tecladocode/develop
A few upgrades and fixes!
2 parents d3578a5 + 37e6ff6 commit 1701703

File tree

304 files changed

+10789
-16154
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

304 files changed

+10789
-16154
lines changed

.vscode/settings.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"githubPullRequests.ignoredPullRequestBranches": [
3+
"develop"
4+
]
5+
}

docs/docs/01_course_intro/01_curriculum_overview/README.md

-11
This file was deleted.

docs/docs/01_course_intro/02_how_to_install_python/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: How to install Python
33
description: A brief description of the lecture goes here.
4+
ctslug: how-to-install-python
45
---
56

67
# How to install Python on your computer
@@ -25,7 +26,7 @@ If you have multiple versions of Python installed, such as a version you install
2526
C:\\Users\\yourname\\AppData\\Local\\Programs\\Python\\Python39-32\\python.exe
2627
```
2728

28-
When you use an IDE, such as [Visual Studio Code](../how_to_install_ide), you can use the integrated terminal instead of `cmd.exe`.
29+
When you use an IDE, such as [Visual Studio Code](../how_to_install_ide/), you can use the integrated terminal instead of `cmd.exe`.
2930

3031
## On Mac
3132

docs/docs/01_course_intro/03_how_to_install_ide/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: How to install an IDE
33
description: What IDE should you use? How do you install it? Let me show you in this quick guide.
4+
ctslug: how-to-install-an-ide
45
---
56

67
# How to install an IDE

docs/docs/01_course_intro/04_what_is_rest_api/README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: "What is a REST API?"
33
description: "There's a lot of confusion around what is and isn't a REST API. Let's take a look!"
4+
ctslug: what-is-an-rest-api
45
---
56

67
# What is a REST API?
@@ -151,11 +152,11 @@ We'll deal with user authentication in a later section, but that's what the lock
151152

152153
### Stores
153154

154-
| Method | Endpoint | Description |
155-
| ------ | ------------- | ---------------------------------------- |
156-
| `GET` | `/store` | Get a list of all stores. |
157-
| `POST` | `/store` | Create a store. |
158-
| `GET` | `/store/{id}` | Get a single store, given its unique id. |
155+
| Method | Endpoint | Description |
156+
| -------- | ------------- | ---------------------------------------- |
157+
| `GET` | `/store` | Get a list of all stores. |
158+
| `POST` | `/store` | Create a store. |
159+
| `GET` | `/store/{id}` | Get a single store, given its unique id. |
159160
| `DELETE` | `/store/{id}` | Delete a store, given its unique id. |
160161

161162
### Items

docs/docs/03_first_rest_api/01_project_overview/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Project Overview
33
description: A first look at the project we'll build in this section.
4+
ctslug: overview-of-your-first-rest-api
45
---
56

67
# Overview of your first REST API

docs/docs/03_first_rest_api/02_getting_set_up/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Getting set up
33
description: Set up a Flask project and create the Flask app.
4+
ctslug: getting-set-up
45
---
56

67
# Getting set up

docs/docs/03_first_rest_api/03_first_rest_api_endpoint/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Your First REST API Endpoint
33
description: Learn how to define a REST API endpoint using Flask.
4+
ctslug: your-first-rest-api-endpoint
45
---
56

67
# Your First REST API Endpoint

docs/docs/03_first_rest_api/04_what_is_json/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: "What is JSON?"
33
description: JSON is the way we normally transfer data to and from REST APIs.
4+
ctslug: what-is-json
45
---
56

67
# What is JSON?

docs/docs/03_first_rest_api/05_make_request_to_rest_api/README.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: How to interact with your REST API
33
description: Use Postman and Insomnia REST Client to interact with your REST API.
4+
ctslug: how-to-interact-with-your-rest-api
45
---
56

67
# How to make a request to a REST API
@@ -28,11 +29,11 @@ Start by [downloading Insomnia REST Client](https://insomnia.rest/).
2829

2930
Once you've opened it, create a Project. I would call it "REST APIs with Flask and Python".
3031

31-
![Creating the Project for this course](assets/creating-project.png)
32+
![Creating the Project for this course](https://res.cloudinary.com/teclado/image/upload/v1689180715/courses/rest-apis-flask-python/creating-project_qsyxlg.png)
3233

3334
Then, create a new Request Collection. Call it "Stores REST API".
3435

35-
![Creating the Stores REST API Request Collection](assets/making-request-collection.png)
36+
![Creating the Stores REST API Request Collection](https://res.cloudinary.com/teclado/image/upload/v1689180710/courses/rest-apis-flask-python/making-request-collection_lcthlv.png)
3637

3738
In the Request Collection, we can now add requests! Each request has a few parts:
3839

@@ -45,19 +46,19 @@ Let's create our first request, `GET /store`.
4546

4647
Make a new request using the Insomnia interface. First, use the dropdown to start:
4748

48-
![How to make a request using the Insomnia interface](assets/making-request.png)
49+
![How to make a request using the Insomnia interface](https://res.cloudinary.com/teclado/image/upload/v1689180711/courses/rest-apis-flask-python/making-request_hmiptl.png)
4950

5051
Then enter the request name. Leave the method as `GET`:
5152

52-
![Enter the request name and method](assets/set-request-name-and-method.png)
53+
![Enter the request name and method](https://res.cloudinary.com/teclado/image/upload/v1689180712/courses/rest-apis-flask-python/set-request-name-and-method_bc6smy.png)
5354

5455
Once you're done, you will see your request in the collection:
5556

56-
![The request is shown in the collection](assets/before-setting-url.png)
57+
![The request is shown in the collection](https://res.cloudinary.com/teclado/image/upload/v1689180711/courses/rest-apis-flask-python/before-setting-url_qjxvyr.png)
5758

5859
Next up, enter the URL for your request. Here we will be requesting the `/store` endpoint. Remember to include your Base URL as well:
5960

60-
![Entering the full URL for the request in Insomnia](assets/url-set.png)
61+
![Entering the full URL for the request in Insomnia](https://res.cloudinary.com/teclado/image/upload/v1689180714/courses/rest-apis-flask-python/url-set_fgp9s9.png)
6162

6263
Once you're done, make sure that your Flask app is running! If it isn't, remember to activate your virtual environment first and then run the app:
6364

@@ -74,6 +75,6 @@ If you get an error, read it carefully and make sure that no other Flask app is
7475

7576
Once your Flask app is running, you can hit "Send" on the Insomnia client, and you should see the JSON come back from your API!
7677

77-
![Making a request to our API using Insomnia](assets/after-pressing-send.png)
78+
![Making a request to our API using Insomnia](https://res.cloudinary.com/teclado/image/upload/v1689180712/courses/rest-apis-flask-python/after-pressing-send_okjkjq.png)
7879

7980
If that worked and you can see your JSON, you're good to go! You've made your first API request. Now we can continue developing our REST API, remembering to always create new Requests in Insomnia and test our code as we go along!

docs/docs/03_first_rest_api/06_creating_stores/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: How to create stores
33
description: Learn how to add data to our REST API.
4+
ctslug: how-to-create-stores
45
---
56

67
# How to create stores in our REST API

docs/docs/03_first_rest_api/07_creating_items/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: How to create items in each store
33
description: A brief description of the lecture goes here.
4+
ctslug: how-to-create-items-in-each-store
45
---
56

67
# How to create items in our REST API

docs/docs/03_first_rest_api/08_return_data_from_rest_api/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Get a specific store and its items
33
description: How to use Flask to return data from your REST API to your client.
4+
ctslug: get-a-specific-store-and-its-items
45
---
56

67
# How to get a specific store and its items

docs/docs/03_first_rest_api/09_final_code/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Final code of this section
33
description: Overview of the project we've built and all the code in it.
4+
ctslug: final-code-of-this-section
45
---
56

67
# Final code of this section

docs/docs/04_docker_intro/01_what_is_docker_container/README.md

+80-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
# What is a Docker container?
1+
---
2+
ctslug: what-is-a-docker-container
3+
description: Learn what Docker images and containers are, and how we can use them to distribute and run our applications.
4+
---
5+
6+
# What are Docker images and containers?
27

38
I'm sure you have heard of the term "Virtual Machine". A virtual machine is an emulation of an Operating System. For example, if you run a Windows virtual machine on your MacOS computer, it will run a whole copy of Windows so you can run Windows programs.
49

510
This diagram shows what happens in that case:
611

7-
![Virtual Machine Diagram stack](./assets/vm.drawio.png)
12+
![Virtual Machine Diagram stack](https://res.cloudinary.com/teclado/image/upload/v1689180716/courses/rest-apis-flask-python/vm.drawio_nlrxmx.png)
813

914
When you run a Virtual Machine, you can configure what hardware it has access to (e.g. 50% of the host's RAM, 2 CPU cores, etc).
1015

@@ -14,7 +19,7 @@ Containers have their own storage and networking, but because they don't have to
1419

1520
This diagram shows how Linux containers run in a Linux host:
1621

17-
![Docker Diagram stack](./assets/docker-linux.drawio.png)
22+
![Docker Diagram stack](https://res.cloudinary.com/teclado/image/upload/v1689180716/courses/rest-apis-flask-python/docker-linux.drawio_ebvff5.png)
1823

1924
Looks similar, but the `docker -> container` section is much more efficient than running a VM because it **uses the host's kernel** instead of running its own.
2025

@@ -85,4 +90,75 @@ Yes!
8590
When we build our Docker image, we will be building it _on top of_ other, pre-built, existing images. Those images come with the lower-level requirements such as compilers, the C language, and most utilities and programs we need.
8691
:::
8792

88-
Let's take a look at Docker images in the next lecture.
93+
## What is a Docker image?
94+
95+
A Docker image is a snapshot of source code, libraries, dependencies, tools, and everything else (except the Operating System kernel!) that a container needs to run.
96+
97+
There are many pre-built images that you can use. For example, some come with Ubuntu (a Linux distribution). Others come with Ubuntu and Python already installed. You can also make your own images that already have Flask installed (as well as other dependencies your app needs).
98+
99+
:::info Comes with Ubuntu?
100+
In the last lecture I mentioned that Docker containers use the host OS kernel, so why does the container need Ubuntu?
101+
102+
Remember that operating systems are kernel + programs/libraries. Although the container uses the host kernel, we may still need a lot of programs/libraries that Ubuntu ships with. An example might be a C language compiler!
103+
:::
104+
105+
This is how you define a Docker image. I'll guide you through how to do this in the next lecture, but bear with me for a second:
106+
107+
```dockerfile
108+
FROM python:3.10
109+
EXPOSE 5000
110+
WORKDIR /app
111+
RUN pip install flask
112+
COPY . .
113+
CMD ["flask", "run", "--host", "0.0.0.0"]
114+
```
115+
116+
This is a `Dockerfile`, a definition of how to create a Docker image. Once you have this file, you can ask Docker to create the Docker image. Then, after creating the Docker image, you can ask Docker to run it as a container.
117+
118+
```
119+
Dockerfile ---build--> docker image ---run--> docker container
120+
```
121+
122+
In this `Dockerfile` you can see the first line: `FROM python:3.10`. This tells Docker to first download the `python:3.10` image (an image someone else already created), and once that image is created, run the following commands.
123+
124+
:::info What's in the Python image?
125+
The `python:3.10` image is also built using a `Dockerfile`! You can see the `Dockerfile` for it [here](https://github.com/docker-library/python/blob/master/3.10/bookworm/Dockerfile).
126+
127+
You can see it comes `FROM` another image. There is usually a chain of these, images built upon other images, until you reach the base image. In this case, the [base image](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/Dockerfile) is running Debian (a Linux distribution).
128+
129+
<details>
130+
<summary>Where is the base image!?</summary>
131+
<div>
132+
<div>
133+
134+
If you really want to go deep, you will be able to find...
135+
136+
- The [`python3.10:bookworm`](https://github.com/docker-library/python/blob/master/3.10/bookworm/Dockerfile) image builds on `buildpack-deps:bookworm`
137+
- [`buildpack-deps:bookworm`](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/Dockerfile) builds on `buildpack-deps:bookworm-scm`
138+
- [`buildpack-deps:bookworm-scm`](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/scm/Dockerfile) builds on `buildpack-deps:bookworm-curl`
139+
- [`buildpack-deps:bookworm-curl`](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/curl/Dockerfile) builds on `debian:bookworm`
140+
- [`debian:bookworm`](https://github.com/debuerreotype/docker-debian-artifacts/blob/f7257ef5b83f6b64385edddeae2d2ba7d1b34935/bookworm/Dockerfile) looks really weird!
141+
142+
Eventually, the base image has to physically include the files that make up the operating system. In that last image, that's the Debian OS files that the maintainers have deemed necessary for the `bookworm` image.
143+
144+
</div>
145+
</div>
146+
</details>
147+
148+
So, why the chain?
149+
150+
Three main reasons:
151+
152+
1. So you don't have to write a super long and complex `Dockerfile` which contains everything you need.
153+
2. So pre-published images can be shared online, and all you have to do is download them.
154+
3. So when your own images use the same base image, Docker in your computer only downloads the base image once, saving you a lot of disk space.
155+
:::
156+
157+
Back to our `Dockerfile`. The commands after `FROM...` are specific to our use case, and do things like install requirements, copy our source code into the image, and tell Docker what command to run when we start a container from this image.
158+
159+
This separation between images and containers is interesting because once the image is created you can ship it across the internet and:
160+
161+
- Share it with other developers.
162+
- Deploy it to servers.
163+
164+
Plus once you've downloaded the image (which can take a while), starting a container from it is almost instant since there's very little work to do.

docs/docs/04_docker_intro/03_run_docker_container/README.md renamed to docs/docs/04_docker_intro/02_run_docker_container/README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
---
2+
ctslug: how-to-run-a-docker-container
3+
description: Learn how to run a Docker container with your REST API using Docker Desktop.
4+
---
5+
16
# How to run a Docker container
27

38
## Install Docker Desktop
@@ -122,6 +127,6 @@ docker run -dp 5001:5000 rest-apis-flask-python
122127

123128
Try making requests using the URL `127.0.0.1:5000` with Insomnia REST Client or Postman, and you should see it working well!
124129

125-
![Insomnia REST Client successfully made a request to the API running in Docker](assets/running-app-docker.png)
130+
![Insomnia REST Client successfully made a request to the API running in Docker](https://res.cloudinary.com/teclado/image/upload/v1689180719/courses/rest-apis-flask-python/running-app-docker_mkosjm.png)
126131

127132
[^1]: [Docker `EXPOSE` command (Official Documentation)](https://docs.docker.com/engine/reference/builder/#expose)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM python:3.10
2+
EXPOSE 5000
3+
WORKDIR /app
4+
RUN pip install flask
5+
COPY . .
6+
CMD ["flask", "run", "--host", "0.0.0.0"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from flask import Flask, request
2+
3+
app = Flask(__name__)
4+
5+
stores = [{"name": "My Store", "items": [{"name": "Chair", "price": 15.99}]}]
6+
7+
8+
@app.get("/store")
9+
def get_stores():
10+
return {"stores": stores}
11+
12+
13+
@app.post("/store")
14+
def create_store():
15+
request_data = request.get_json()
16+
new_store = {"name": request_data["name"], "items": []}
17+
stores.append(new_store)
18+
return new_store, 201
19+
20+
21+
@app.post("/store/<string:name>/item")
22+
def create_item(name):
23+
request_data = request.get_json()
24+
for store in stores:
25+
if store["name"] == name:
26+
new_item = {"name": request_data["name"], "price": request_data["price"]}
27+
store["items"].append(new_item)
28+
return new_item, 201
29+
return {"message": "Store not found"}, 404
30+
31+
32+
@app.get("/store/<string:name>")
33+
def get_store(name):
34+
for store in stores:
35+
if store["name"] == name:
36+
return store
37+
return {"message": "Store not found"}, 404
38+
39+
40+
@app.get("/store/<string:name>/item")
41+
def get_item_in_store(name):
42+
for store in stores:
43+
if store["name"] == name:
44+
return {"items": store["items"]}
45+
return {"message": "Store not found"}, 404

0 commit comments

Comments
 (0)