Skip to content

Commit f501b32

Browse files
committed
✨ (Flask-SQLAlchemy) Add info on schema updates and conclusion lecture
1 parent a072a37 commit f501b32

File tree

7 files changed

+163
-28
lines changed

7 files changed

+163
-28
lines changed

docs/docs/06_sql_storage_sqlalchemy/02_create_simple_sqlalchemy_model/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class ItemModel(db.Model):
2929
id = db.Column(db.Integer, primary_key=True)
3030
name = db.Column(db.String(80), unique=True, nullable=False)
3131
price = db.Column(db.Float(precision=2), unique=False, nullable=False)
32+
store_id = db.Column(db.Integer, unique=False, nullable=False)
3233
```
3334

3435
```python title="models/store.py"

docs/docs/06_sql_storage_sqlalchemy/02_create_simple_sqlalchemy_model/end/models/item.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ class ItemModel(db.Model):
77
id = db.Column(db.Integer, primary_key=True)
88
name = db.Column(db.String(80), unique=True, nullable=False)
99
price = db.Column(db.Float(precision=2), unique=False, nullable=False)
10+
store_id = db.Column(db.Integer, unique=False, nullable=False)
Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,18 @@
11
from marshmallow import Schema, fields
22

33

4-
class PlainItemSchema(Schema):
5-
id = fields.Int(dump_only=True)
4+
class ItemSchema(Schema):
5+
id = fields.Str(dump_only=True)
66
name = fields.Str(required=True)
77
price = fields.Float(required=True)
8-
9-
10-
class PlainStoreSchema(Schema):
11-
id = fields.Int(dump_only=True)
12-
name = fields.Str()
13-
14-
15-
class ItemSchema(PlainItemSchema):
16-
store_id = fields.Int(required=True, load_only=True)
17-
store = fields.Nested(lambda: PlainStoreSchema(), dump_only=True)
8+
store_id = fields.Int(required=True)
189

1910

2011
class ItemUpdateSchema(Schema):
2112
name = fields.Str()
2213
price = fields.Float()
2314

2415

25-
class StoreSchema(PlainStoreSchema):
26-
items = fields.List(fields.Nested(PlainItemSchema()), dump_only=True)
16+
class StoreSchema(Schema):
17+
id = fields.Str(dump_only=True)
18+
name = fields.Str(required=True)
Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,18 @@
11
from marshmallow import Schema, fields
22

33

4-
class PlainItemSchema(Schema):
5-
id = fields.Int(dump_only=True)
4+
class ItemSchema(Schema):
5+
id = fields.Str(dump_only=True)
66
name = fields.Str(required=True)
77
price = fields.Float(required=True)
8-
9-
10-
class PlainStoreSchema(Schema):
11-
id = fields.Int(dump_only=True)
12-
name = fields.Str()
13-
14-
15-
class ItemSchema(PlainItemSchema):
16-
store_id = fields.Int(required=True, load_only=True)
17-
store = fields.Nested(lambda: PlainStoreSchema(), dump_only=True)
8+
store_id = fields.Int(required=True)
189

1910

2011
class ItemUpdateSchema(Schema):
2112
name = fields.Str()
2213
price = fields.Float()
2314

2415

25-
class StoreSchema(PlainStoreSchema):
26-
items = fields.List(fields.Nested(PlainItemSchema()), dump_only=True)
16+
class StoreSchema(Schema):
17+
id = fields.Str(dump_only=True)
18+
name = fields.Str(required=True)

docs/docs/06_sql_storage_sqlalchemy/03_one_to_many_relationships_sqlalchemy/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,49 @@ And here's how you would do some filtering:
7272

7373
```python
7474
store.items.filter_by(name=="Chair").first()
75+
```
76+
77+
## Updating our marshmallow schemas
78+
79+
Now that the models have these relationships, we can modify our marshmallow schemas so they will return some or all of the information about the related models.
80+
81+
We do this with the `Nested` marshmallow field.
82+
83+
:::caution
84+
Something to be careful about is having schema A which has a nested schema B, which has a nested schema A.
85+
86+
This will lead to an infinite nesting, which is obviously never what you want!
87+
:::
88+
89+
To avoid infinite nesting, we are renaming our schemas which _don't_ use nested fields to `Plain`, such as `PlainItemSchema` and `PlainStoreSchema`.
90+
91+
Then the schemas that _do_ use nesting can be called `ItemSchema` and `StoreSchema`, and they inherit from the plain schemas. This reduces duplication and prevents infinite nesting.
92+
93+
```python title="schemas.py"
94+
from marshmallow import Schema, fields
95+
96+
97+
class PlainItemSchema(Schema):
98+
id = fields.Int(dump_only=True)
99+
name = fields.Str(required=True)
100+
price = fields.Float(required=True)
101+
102+
103+
class PlainStoreSchema(Schema):
104+
id = fields.Int(dump_only=True)
105+
name = fields.Str()
106+
107+
108+
class ItemSchema(PlainItemSchema):
109+
store_id = fields.Int(required=True, load_only=True)
110+
store = fields.Nested(lambda: PlainStoreSchema(), dump_only=True)
111+
112+
113+
class ItemUpdateSchema(Schema):
114+
name = fields.Str()
115+
price = fields.Float()
116+
117+
118+
class StoreSchema(PlainStoreSchema):
119+
items = fields.List(fields.Nested(PlainItemSchema()), dump_only=True)
75120
```

docs/docs/06_sql_storage_sqlalchemy/03_one_to_many_relationships_sqlalchemy/start/models/item.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ class ItemModel(db.Model):
77
id = db.Column(db.Integer, primary_key=True)
88
name = db.Column(db.String(80), unique=True, nullable=False)
99
price = db.Column(db.Float(precision=2), unique=False, nullable=False)
10+
store_id = db.Column(db.Integer, unique=False, nullable=False)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
title: Conclusion of this section
3+
description: Review everything we've changed this section to add SQL storage with SQLAlchemy to our API.
4+
---
5+
6+
# Conclusion of this section
7+
8+
Adding SQL storage to our app has required quite a few changes! Let's do a quick review.
9+
10+
## Installed SQLAlchemy and Flask-SQLAlchemy
11+
12+
```
13+
pip install sqlalchemy flask-sqlalchemy
14+
```
15+
16+
And
17+
18+
```text title="requirements.txt"
19+
sqlalchemy
20+
flask-sqlalchemy
21+
```
22+
23+
## Created models
24+
25+
```python title="models/item.py"
26+
from db import db
27+
28+
29+
class ItemModel(db.Model):
30+
__tablename__ = "items"
31+
32+
id = db.Column(db.Integer, primary_key=True)
33+
name = db.Column(db.String(80), unique=True, nullable=False)
34+
price = db.Column(db.Float(precision=2), unique=False, nullable=False)
35+
36+
store_id = db.Column(
37+
db.Integer, db.ForeignKey("stores.id"), unique=False, nullable=False
38+
)
39+
store = db.relationship("StoreModel", back_populates="items")
40+
```
41+
42+
And
43+
44+
```python title="models/store.py"
45+
from db import db
46+
47+
48+
class StoreModel(db.Model):
49+
__tablename__ = "stores"
50+
51+
id = db.Column(db.Integer, primary_key=True)
52+
name = db.Column(db.String(80), unique=True, nullable=False)
53+
54+
items = db.relationship("ItemModel", back_populates="store", lazy="dynamic")
55+
```
56+
57+
## Updated resources to use SQLAlchemy
58+
59+
Previously we were using Python dictionaries as a database. Now we've swapped them out for using SQLAlchemy models by:
60+
61+
- Importing the models in our resource files
62+
- Retrieving models from the database with `ModelClass.query.get_or_404(model_id)`.
63+
- Updating models by changing attributes, or creating new model class instances, and then saving and committing with `db.session.add(model_instance)` and `db.session.commit()`.
64+
- Deleting models with `db.session.delete(model_instance)` followed by `db.session.commit()`.
65+
66+
## Updated marshmallow schemas
67+
68+
Since now our models have relationships, that means that the schemas can have `Nested` fields.
69+
70+
The schemas that don't have `Nested` fields we've called "Plain" schemas, and those that do are named after the model they represent.
71+
72+
```python title="schemas.py"
73+
from marshmallow import Schema, fields
74+
75+
76+
class PlainItemSchema(Schema):
77+
id = fields.Int(dump_only=True)
78+
name = fields.Str(required=True)
79+
price = fields.Float(required=True)
80+
81+
82+
class PlainStoreSchema(Schema):
83+
id = fields.Int(dump_only=True)
84+
name = fields.Str()
85+
86+
87+
class ItemSchema(PlainItemSchema):
88+
store_id = fields.Int(required=True, load_only=True)
89+
store = fields.Nested(PlainStoreSchema(), dump_only=True)
90+
91+
92+
class ItemUpdateSchema(Schema):
93+
name = fields.Str()
94+
price = fields.Float()
95+
96+
97+
class StoreSchema(PlainStoreSchema):
98+
items = fields.List(fields.Nested(PlainItemSchema()), dump_only=True)
99+
```
100+
101+
And that's it! Quite a few changes, but hopefully you're still with me.
102+
103+
In the following sections we'll be adding more functionality to our API, so stay tuned!

0 commit comments

Comments
 (0)