Skip to content

Commit

Permalink
Merge pull request #98 from tecladocode/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
jslvtr committed Dec 6, 2022
2 parents bd7d743 + d5d9827 commit 77fe34e
Show file tree
Hide file tree
Showing 97 changed files with 1,024 additions and 691 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/algolia-scraper.yml
@@ -0,0 +1,21 @@
name: Run Algolia Scraper

on:
push:
branches: ["master", "develop"]
pull_request:
branches: ["master", "develop"]

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: darrenjennings/algolia-docsearch-action@master
with:
algolia_application_id: "1BEGBIP9SH"
algolia_api_key: ${{ secrets.ALGOLIA_API_KEY }}
file: "docs/algolia.config.json"
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -6,7 +6,7 @@

<div align="center">

[![Udemy rating 4.6/5](https://img.shields.io/badge/udemy-4.6%2F5-brightgreen)](https://go.tecla.do/rest-apis-sale) ![GitHub last commit](https://img.shields.io/github/last-commit/tecladocode/rest-apis-flask-python/develop) ![Python 3.10](https://img.shields.io/badge/python-3.10-yellow) [![Discord](https://img.shields.io/discord/614395983807250433)](https://discord.gg/78Nvd3p) [![Twitter Follow](https://img.shields.io/twitter/follow/jslvtr?style=social) ](https://twitter.com/jslvtr)
[![Udemy rating 4.6/5](https://img.shields.io/badge/udemy-4.6%2F5-brightgreen)](https://go.tecla.do/rest-apis-ebook) ![GitHub last commit](https://img.shields.io/github/last-commit/tecladocode/rest-apis-flask-python/develop) ![Python 3.10](https://img.shields.io/badge/python-3.10-yellow) [![Discord](https://img.shields.io/discord/614395983807250433)](https://discord.gg/78Nvd3p) [![Twitter Follow](https://img.shields.io/twitter/follow/jslvtr?style=social) ](https://twitter.com/jslvtr)

</div>

Expand All @@ -16,7 +16,7 @@

## Getting started

Enrol in the course by going to [this link](https://go.tecla.do/rest-apis-sale).
Enrol in the course by going to [this link](https://go.tecla.do/rest-apis-ebook).

Then you can come back here to download the repository. This repository contains the code that we develop in each section of the course.

Expand Down
49 changes: 49 additions & 0 deletions docs/algolia.config.json
@@ -0,0 +1,49 @@
{
"index_name": "docusaurus-2",
"start_urls": [
"https://rest-apis-flask.teclado.com/"
],
"sitemap_urls": [
"https://rest-apis-flask.teclado.com/sitemap.xml"
],
"sitemap_alternate_links": true,
"stop_urls": [
"/tests"
],
"selectors": {
"lvl0": {
"selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
"type": "xpath",
"global": true,
"default_value": "Documentation"
},
"lvl1": "header h1",
"lvl2": "article h2",
"lvl3": "article h3",
"lvl4": "article h4",
"lvl5": "article h5, article td:first-child",
"lvl6": "article h6",
"text": "article p, article li, article td:last-child"
},
"strip_chars": " .,;:#",
"custom_settings": {
"separatorsToIndex": "_",
"attributesForFaceting": [
"language",
"version",
"type",
"docusaurus_tag"
],
"attributesToRetrieve": [
"hierarchy",
"content",
"anchor",
"url",
"url_without_anchor",
"type"
]
},
"conversation_id": [
"833762294"
]
}

This file was deleted.

1 change: 0 additions & 1 deletion docs/docs-upcoming/11_celery_background_tasks/README.md

This file was deleted.

4 changes: 0 additions & 4 deletions docs/docs-upcoming/11_celery_background_tasks/_category_.json

This file was deleted.

5 changes: 4 additions & 1 deletion docs/docs/01_course_intro/01_curriculum_overview/README.md
Expand Up @@ -5,4 +5,7 @@ description: A brief description of the lecture goes here.

# Curriculum overview

The curriculum overview goes here.
import DocCategoryIndex from '@theme/DocCardList';
import {useDocsSidebar} from '@docusaurus/theme-common/internal';

<DocCategoryIndex items={useDocsSidebar().items} />
8 changes: 4 additions & 4 deletions docs/docs/01_course_intro/04_what_is_rest_api/README.md
Expand Up @@ -84,7 +84,7 @@ An API client can be any device, such as a web app or a mobile app.

### Making an API for your own consumption

Make software companies make APIs that only they use (so they aren't fully public).
Many software companies make APIs that only they use (so they aren't fully public).

Here's an example. You're making a multiplayer mobile game, and you need to store information about the moves that your character is making.

Expand All @@ -109,7 +109,7 @@ REST APIs deal in resources, so every individual "thing" that can be named is a
The main characteristics (or constraints) of a REST API are:

1. **Uniform interface**. Whichever way clients should access a certain resource should also be the way the access other resources. Clients should have a single way to retrieve resources.
2. **Client-server**. Clients should know the endpoints of the API, but they should not be coupled to the development of the API. A client or a servevr may be swapped out for a different implementation without the other noticing.
2. **Client-server**. Clients should know the endpoints of the API, but they should not be coupled to the development of the API. A client or a server may be swapped out for a different implementation without the other noticing.
3. **Stateless**. The server (API) doesn't store anything about previous client requests. Each client request is treated as a brand new client. If the client needs the server to personalize the response, then the client must send the server whatever information the server needs in order to do so.
4. **Cacheable**. The client or server must be able to cache the resources returned by the API. This is a very general constraint, but it's an important one.
5. **Layered system**. REST APIs may be developed as multiple layers, where each layer interacts [only with the layer above and below it](https://excalidraw.com/#json=or3Umoigss4yIeuKg3cO8,qH6uDDCXc7DSjweqNvlmzw).
Expand Down Expand Up @@ -156,7 +156,7 @@ We'll deal with user authentication in a later section, but that's what the lock
| `GET` | `/store` | Get a list of all stores. |
| `POST` | `/store` | Create a store. |
| `GET` | `/store/{id}` | Get a single store, given its unique id. |
| `POST` | `/store/{id}` | Delete a store, given its unique id. |
| `DELETE` | `/store/{id}` | Delete a store, given its unique id. |

### Items

Expand Down Expand Up @@ -191,4 +191,4 @@ Then, over the following sections, we'll improve on this REST API. We'll add:
- Add user authentication.
- Add item tagging.
- Add an admin panel so changing data manually is a bit easier.
- And much more!
- And much more!
6 changes: 6 additions & 0 deletions docs/docs/01_course_intro/index.md
Expand Up @@ -4,6 +4,12 @@ id: intro

# REST APIs with Flask and Python

import VideoEmbed from "@site/src/components/VideoEmbed";

<div style={{ maxWidth: "720px", margin: "3rem auto", boxShadow: "0 5px 15px 0 rgba(0, 0, 0, 0.15)" }}>
<VideoEmbed url="https://customer-zmitazl0ztnd2pvm.cloudflarestream.com/1c4db6119cf0c6e682a88a737af146eb/iframe?poster=https%3A%2F%2Fcustomer-zmitazl0ztnd2pvm.cloudflarestream.com%2F1c4db6119cf0c6e682a88a737af146eb%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600" />
</div>

Hi, and welcome!

REST APIs with Flask and Python is a complete course that teaches you how to develop complete, professional REST APIs using **Flask**, **PostgreSQL**, and **Docker**.
Expand Down
10 changes: 10 additions & 0 deletions docs/docs/03_first_rest_api/01_project_overview/README.md
Expand Up @@ -5,6 +5,12 @@ description: A first look at the project we'll build in this section.

# Overview of your first REST API

import VideoEmbed from "@site/src/components/VideoEmbed";

<div style={{ maxWidth: "720px", margin: "3rem auto", boxShadow: "0 5px 15px 0 rgba(0, 0, 0, 0.15)" }}>
<VideoEmbed url="https://customer-zmitazl0ztnd2pvm.cloudflarestream.com/cda9c0473bdc485a36905144f13f4d3f/iframe?poster=https%3A%2F%2Fcustomer-zmitazl0ztnd2pvm.cloudflarestream.com%2Fcda9c0473bdc485a36905144f13f4d3f%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600" />
</div>

In this section we'll make a simple REST API that allows us to:

- Create stores, each with a `name` and a list of stocked `items`.
Expand All @@ -15,6 +21,10 @@ In this section we'll make a simple REST API that allows us to:

This is how the interaction will go!

:::tip Insomnia files
Remember to get the Insomnia files for this section or for all sections [here](/insomnia-files/)!
:::

## Create stores

Request:
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/03_first_rest_api/02_getting_set_up/README.md
Expand Up @@ -5,6 +5,12 @@ description: Set up a Flask project and create the Flask app.

# Getting set up

import VideoEmbed from "@site/src/components/VideoEmbed";

<div style={{ maxWidth: "720px", margin: "3rem auto", boxShadow: "0 5px 15px 0 rgba(0, 0, 0, 0.15)" }}>
<VideoEmbed url="https://customer-zmitazl0ztnd2pvm.cloudflarestream.com/42b7de55034431b4c4c9420460f8df7d/iframe?poster=https%3A%2F%2Fcustomer-zmitazl0ztnd2pvm.cloudflarestream.com%2F42b7de55034431b4c4c9420460f8df7d%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600" />
</div>

Create a virtual environment and activate it.

```
Expand Down
Expand Up @@ -5,6 +5,10 @@ description: Learn how to define a REST API endpoint using Flask.

# Your First REST API Endpoint

import LockedVideoEmbed from "@site/src/components/LockedVideoEmbed";

<LockedVideoEmbed />

Let's start off by defining where we'll store our data. In most REST APIs, you'd store your data in a database. For now, and for simplicity, we'll store it in a Python list.

Later on we'll work on making this data dynamic. For now let's use some sample data.
Expand Down
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/Insomnia_section3.json
@@ -0,0 +1 @@
{"_type":"export","__export_format":4,"__export_date":"2022-11-09T15:36:47.360Z","__export_source":"insomnia.desktop.app:v2022.6.0","resources":[{"_id":"req_e15dafc098ac4a2198304d2aead2a5b9","parentId":"fld_8b9c03412d0e463fabe784d205f1d604","modified":1666900815265,"created":1666123912423,"url":"http://127.0.0.1:5000/store/My Store/item","name":"/store/<name>/item Create item in store","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"name\": \"Table\",\n\t\"price\": 17.99\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"}],"authentication":{},"metaSortKey":-1666124423081,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_8b9c03412d0e463fabe784d205f1d604","parentId":"wrk_6aa19b7d9ecd4f93a3602d257e54a163","modified":1666124528874,"created":1666124528874,"name":"Stores","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1666124528874,"_type":"request_group"},{"_id":"wrk_6aa19b7d9ecd4f93a3602d257e54a163","parentId":null,"modified":1666991857781,"created":1666122928011,"name":"Section 3","description":"","scope":"collection","_type":"workspace"},{"_id":"req_697ca0714a3d4e94819411e3df0a2a17","parentId":"fld_8b9c03412d0e463fabe784d205f1d604","modified":1666900846590,"created":1666124316888,"url":"http://127.0.0.1:5000/store/My store3/item","name":"/store/<name>/item","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1666124423056,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_9451df3aae714e93a8ed529b3a1f99c2","parentId":"fld_8b9c03412d0e463fabe784d205f1d604","modified":1666124555354,"created":1666122990495,"url":"http://127.0.0.1:5000/store","name":"/store Get all store data","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1666124423031,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_6363c8d4deb74b5bbccb1e2105277dac","parentId":"fld_8b9c03412d0e463fabe784d205f1d604","modified":1666900812784,"created":1666124168137,"url":"http://127.0.0.1:5000/store/My store3","name":"/store/<name>","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1666124422956,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_0a9c4822679b4eae92dec7432fe144b8","parentId":"fld_8b9c03412d0e463fabe784d205f1d604","modified":1666900810115,"created":1666123651275,"url":"http://127.0.0.1:5000/store","name":"/store Create new store","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"name\": \"My store3\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"}],"authentication":{},"metaSortKey":-1666124422881,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_19db457230041d88ca9420d1b3c0f1f02bbcae93","parentId":"wrk_6aa19b7d9ecd4f93a3602d257e54a163","modified":1666122928025,"created":1666122928025,"name":"Base Environment","data":{},"dataPropertyOrder":null,"color":null,"isPrivate":false,"metaSortKey":1666122928025,"_type":"environment"},{"_id":"jar_19db457230041d88ca9420d1b3c0f1f02bbcae93","parentId":"wrk_6aa19b7d9ecd4f93a3602d257e54a163","modified":1666122928027,"created":1666122928027,"name":"Default Jar","cookies":[],"_type":"cookie_jar"},{"_id":"spc_c5b803a7c6514ff29573e26487d898d4","parentId":"wrk_6aa19b7d9ecd4f93a3602d257e54a163","modified":1666122928018,"created":1666122928018,"fileName":"Your First REST API","contents":"","contentType":"yaml","_type":"api_spec"}]}
11 changes: 10 additions & 1 deletion docs/docs/05_flask_smorest/02_data_model_improvements/README.md
Expand Up @@ -89,9 +89,14 @@ CMD ["flask", "run", "--host", "0.0.0.0"]
</Tabs>
</div>


## New files

:::tip Insomnia files
Remember to get the Insomnia files for this section or for all sections [here](/insomnia-files/)!

There are two Insomnia files for this section: one for lectures 1-5 (before adding Docker), and one for the other lectures (after adding Docker).
:::

Let's start off by creating a `requirements.txt` file with all our dependencies:

```txt title="requirements.txt"
Expand Down Expand Up @@ -245,6 +250,8 @@ def create_store():
<TabItem value="new" label="create_store (new)">

```py title="app.py"
import uuid

@app.post("/store")
def create_store():
store_data = request.get_json()
Expand All @@ -255,6 +262,8 @@ def create_store():
return store
```

Here we add a new import, [the `uuid` module](https://docs.python.org/3/library/uuid.html). We will be using it to create unique IDs for our stores and items instead of relying on the uniqueness of their names.

</TabItem>
</Tabs>
</div>
Expand Down
Expand Up @@ -37,7 +37,7 @@ class ItemSchema(Schema):
id = fields.Str(dump_only=True)
name = fields.Str(required=True)
price = fields.Float(required=True)
store_id = fields.Int(required=True)
store_id = fields.Str(required=True)
```

A couple of weird things maybe!
Expand Down
Expand Up @@ -5,7 +5,7 @@ class ItemSchema(Schema):
id = fields.Str(dump_only=True)
name = fields.Str(required=True)
price = fields.Float(required=True)
store_id = fields.Int(required=True)
store_id = fields.Str(required=True)


class ItemUpdateSchema(Schema):
Expand Down
Expand Up @@ -5,7 +5,7 @@ class ItemSchema(Schema):
id = fields.Str(dump_only=True)
name = fields.Str(required=True)
price = fields.Float(required=True)
store_id = fields.Int(required=True)
store_id = fields.Str(required=True)


class ItemUpdateSchema(Schema):
Expand Down
Expand Up @@ -5,7 +5,7 @@ class ItemSchema(Schema):
id = fields.Str(dump_only=True)
name = fields.Str(required=True)
price = fields.Float(required=True)
store_id = fields.Int(required=True)
store_id = fields.Str(required=True)


class ItemUpdateSchema(Schema):
Expand Down
Expand Up @@ -5,7 +5,7 @@ class ItemSchema(Schema):
id = fields.Str(dump_only=True)
name = fields.Str(required=True)
price = fields.Float(required=True)
store_id = fields.Int(required=True)
store_id = fields.Str(required=True)


class ItemUpdateSchema(Schema):
Expand Down
Expand Up @@ -5,7 +5,7 @@ class ItemSchema(Schema):
id = fields.Str(dump_only=True)
name = fields.Str(required=True)
price = fields.Float(required=True)
store_id = fields.Int(required=True)
store_id = fields.Str(required=True)


class ItemUpdateSchema(Schema):
Expand Down

0 comments on commit 77fe34e

Please sign in to comment.