Most trendy net functions are powered by a REST API beneath the hood. That manner, builders can separate the front-end code from the back-end logic, and customers can work together with the interface dynamically. On this three-part tutorial collection, you’re constructing a REST API with the Flask net framework.
You’ve created a basis with a primary Flask mission and added endpoints, which you related to a SQLite database. You’re additionally testing your API with Swagger UI API documentation that you just’re constructing alongside the way in which.
Within the third a part of this tutorial collection, you’ll discover ways to:
- Work with a number of tables in a database
- Create one-to-many fields in your database
- Handle relationships with SQLAlchemy
- Leverage nested schemas with Marshmallow
- Show associated objects within the entrance finish
You may obtain the code for the third a part of this mission by clicking the hyperlink under:
Demo
On this three-part tutorial collection, you’re constructing a REST API to maintain observe of notes for individuals who could go to you all year long. You’ll create folks just like the Tooth Fairy, the Easter Bunny, and Knecht Ruprecht.
Ideally, you need to be on good phrases with all three of them. That’s why you’ll ship them notes, to extend the prospect of getting precious presents from them.
On this tutorial, you’ll increase your programming device belt additional. You’ll discover ways to create hierarchical knowledge buildings represented as one-to-many relationships by SQLAlchemy. As well as, you’ll additionally lengthen the REST API that you just’ve already constructed to create, learn, replace, and delete notes for an individual:
It’s time to complete this three-part tutorial collection by creating relationships between folks and notes!
Planning Half Three
In half one of this collection, you constructed your REST API. Working via half two, you related your REST API to a database. That manner, your Flask software could make adjustments to present knowledge and create new knowledge that persists even while you restart your app server.
To this point, you’ve added the power to avoid wasting adjustments made via the REST API to a database utilizing SQLAlchemy and discovered methods to serialize that knowledge for the REST API utilizing Marshmallow.
At present, the folks.db
database solely comprises folks knowledge. On this a part of the collection, you’ll add a brand new desk to retailer notes. To attach notes to an individual, you’ll create relationships between the entries of the particular person
desk and the observe
desk in your database.
You’ll bootstrap folks.db
with a build_database.py
script that comprises the mandatory folks and notes knowledge for you.
Right here’s an excerpt of the dataset that you just’ll work with:
PEOPLE_NOTES = [
{
"lname": "Fairy",
"fname": "Tooth",
"notes": [
("I brush my teeth after each meal.", "2022-01-06 17:10:24"),
("The other day a friend said I have big teeth.", "2022-03-05 22:17:54"),
("Do you pay per gram?", "2022-03-05 22:18:10"),
],
},
# ...
]
You’ll discover ways to alter your SQLite database to implement relationships. After that, you’ll be capable of translate the PEOPLE_NOTES
dictionary into knowledge that conforms together with your database construction.
Lastly, you’ll present the content material of your database on the house web page of your app and use your Flask REST API so as to add, replace, and delete notes that you just’re writing for folks.
Getting Began
Ideally, you adopted the first half and the second half of this tutorial collection earlier than persevering with with the third half, which you’re studying proper now. Alternatively, it’s also possible to obtain the supply code from half two by clicking the hyperlink under:
Should you downloaded the supply code from the hyperlink above, then ensure that to observe the set up directions inside the offered README.md
file.
Earlier than you proceed with the tutorial, confirm that your folder construction seems to be like this:
rp_flask_api/
│
├── templates/
│ └── house.html
│
├── app.py
├── config.py
├── fashions.py
├── folks.py
└── swagger.yml
When you’ve bought the Flask REST API folder construction in place, you may learn on to examine in case your Flask mission works as anticipated.
Test Your Flask Undertaking
Earlier than you proceed working in your Flask mission, it’s a good suggestion to create and activate a digital setting. That manner, you’re putting in any mission dependencies not system-wide however solely in your mission’s digital setting.
Choose your working system under and use your platform-specific command to arrange a digital setting:
With the instructions proven above, you create and activate a digital setting named venv
through the use of Python’s built-in venv
module. The parenthesized (venv)
in entrance of the immediate point out that you just’ve efficiently activated the digital setting.
Word: Should you haven’t labored via half two of this tutorial collection, then ensure that to obtain the supply code by clicking the hyperlink under:
Earlier than persevering with, set up the dependencies by following the directions listed within the offered README.md
file.
Now you may confirm that your Flask software is operating with out errors. Execute the next command within the listing containing the app.py
file:
If you run this software, an online server will begin on port 8000. Should you open a browser and navigate to http://localhost:8000
, you need to see a web page with the heading Whats up, Folks! displayed:

Excellent, your app is operating flawlessly! Now it’s time to consider the brand new database construction.
Examine the Dataset
Earlier than beginning to plan the way you need to alter your database, it’s a good suggestion to take a look on the knowledge that your database presently comprises and the dataset that you just’ll work with.
The particular person
desk of your folks.db
database presently seems to be like this:
id | lname | fname | timestamp |
---|---|---|---|
1 | Fairy | Tooth | 2022-10-08 09:15:10 |
2 | Ruprecht | Knecht | 2022-10-08 09:15:13 |
3 | Bunny | Easter | 2022-10-08 09:15:27 |
You’ll begin to lengthen your database with a PEOPLE_NOTES
checklist:
PEOPLE_NOTES = [
{
"lname": "Fairy",
"fname": "Tooth",
"notes": [
("I brush my teeth after each meal.", "2022-01-06 17:10:24"),
("The other day a friend said, I have big teeth.", "2022-03-05 22:17:54"),
("Do you pay per gram?", "2022-03-05 22:18:10"),
],
},
{
"lname": "Ruprecht",
"fname": "Knecht",
"notes": [
("I swear, I'll do better this year.", "2022-01-01 09:15:03"),
("Really! Only good deeds from now on!", "2022-02-06 13:09:21"),
],
},
{
"lname": "Bunny",
"fname": "Easter",
"notes": [
("Please keep the current inflation rate in mind!", "2022-01-07 22:47:54"),
("No need to hide the eggs this time.", "2022-04-06 13:03:17"),
],
},
]
Word that the lname
values in PEOPLE_NOTES
correspond to the contents of your lname
column within the particular person
desk of your folks.db
database.
Within the dataset above, every particular person features a key known as notes
, which is related to a listing containing tuples of information. Every tuple within the notes
checklist represents a single observe containing the content material and a timestamp.
Every single particular person is related to a number of notes, and every single observe is related to just one particular person. This hierarchy of information is named a one-to-many relationship, the place a single mum or dad object is expounded to many baby objects. You’ll see how this one-to-many relationship is managed within the database with SQLAlchemy later on this tutorial.
Construct Relationships With Folks
As a substitute of extending the particular person
desk and attempting to symbolize hierarchical knowledge in a single desk, you’ll break up the information into a number of tables and join them.
For the particular person
desk, this implies there can be no adjustments. To symbolize the brand new observe data, you’ll create a brand new desk known as observe
.
The observe
desk will seem like this:
id |
person_id |
content material |
timestamp |
---|---|---|---|
1 | 1 | I brush my tooth after every meal. | 2022-01-06 17:10:24 |
2 | 1 | The opposite day a good friend mentioned, I’ve large tooth. | 2022-03-05 22:17:54 |
3 | 1 | Do you pay per gram? | 2022-03-05 22:18:10 |
4 | 2 | I swear, I’ll do higher this yr. | 2022-01-01 09:15:03 |
5 | 2 | Actually! Solely good deeds any more! | 2022-02-06 13:09:21 |
6 | 3 | Please hold the present inflation fee in thoughts! | 2022-01-07 22:47:54 |
7 | 3 | No want to cover the eggs this time. | 2022-04-06 13:03:17 |
Discover that, just like the particular person
desk, the observe
desk has a singular identifier known as id
, which is the main key for the observe
desk. The person_id
column creates the connection to the particular person
desk.
Whereas id
is the first key for the desk, person_id
is what’s often called a overseas key. The overseas key offers every entry within the observe
desk the first key of the particular person
report that it’s related to. Utilizing this, SQLAlchemy can collect all of the notes related to every particular person by connecting the particular person.id
main key to the observe.person_id
overseas key, making a relationship.
The database that you just constructed saved the information in a desk, and a desk is a two-dimensional array of rows and columns. Can the Folks
dictionary above be represented in a single desk of rows and columns? It may be, within the following manner, in your particular person
database desk:
id |
lname |
fname |
timestamp |
content material |
note_timestamp |
---|---|---|---|---|---|
1 | Fairy | Tooth | 2022-10-08 09:15:10 | I brush my tooth after every meal. | 2022-01-06 17:10:24 |
2 | Fairy | Tooth | 2022-10-08 09:15:10 | The opposite day a good friend mentioned, I’ve large tooth. | 2022-03-05 22:17:54 |
3 | Fairy | Tooth | 2022-10-08 09:15:10 | Do you pay per gram? | 2022-03-05 22:18:10 |
4 | Ruprecht | Knecht | 2022-10-08 09:15:13 | I swear, I’ll do higher this yr. | 2022-01-01 09:15:03 |
5 | Ruprecht | Knecht | 2022-10-08 09:15:13 | Actually! Solely good deeds any more! | 2022-02-06 13:09:21 |
6 | Easter | Bunny | 2022-10-08 09:15:27 | Please hold the present inflation fee in thoughts! | 2022-01-07 22:47:54 |
7 | Easter | Bunny | 2022-10-08 09:15:27 | No want to cover the eggs this time. | 2022-04-06 13:03:17 |
The above desk would really work. All the information is represented, and a single particular person is related to a set of various notes.
Conceptually, the above desk construction has the benefit of being comparatively easy to grasp. You would even make the case that the information might be continued to a CSV file as an alternative of a database.
Whereas the above desk construction would work, it has some actual disadvantages. These embody the next:
- Upkeep points because of redundant knowledge
- Awkward column names
- Issue presenting one-to-many relationships
With a view to symbolize the gathering of notes, all the information for every particular person is repeated for each distinctive observe. The particular person knowledge is due to this fact redundant. This isn’t such a giant deal on your particular person knowledge, as there aren’t that many columns. However think about if an individual had many extra columns. Even with giant disk drives, this might get to be a storage concern when you have been coping with tens of millions of rows of information.
Having redundant knowledge like this may additionally result in upkeep points as time goes by. For instance, what if the Easter Bunny determined a change of identify was a good suggestion? With a view to do that, each report containing the Easter Bunny’s identify must be up to date in an effort to hold the information constant. This type of work towards the database can result in knowledge inconsistency, notably if the work is completed by an individual operating a SQL question by hand.
Additionally, naming columns turns into awkward. Within the desk above, there’s a timestamp
column used to trace the creation and replace time of an individual within the desk. You additionally need to have comparable performance for the creation and replace time for a observe, however as a result of timestamp
is already used, a contrived identify of note_timestamp
is used.
What when you needed so as to add further one-to-many relationships to the particular person
desk? For instance, perhaps you’d determine to incorporate an individual’s youngsters or telephone numbers. Every particular person might have a number of youngsters and a number of telephone numbers. With the Python Folks
dictionary above, you may do that comparatively simply by including youngsters
and phone_numbers
keys with new lists containing the information.
Nevertheless, representing these new one-to-many relationships in your particular person
database desk above turns into considerably tougher. Each new one-to-many relationship dramatically will increase the variety of rows essential to symbolize it for each single entry within the baby knowledge. As well as, the issues related to knowledge redundancy get greater and tougher to deal with.
Word: The necessity for storing more and more giant and complicated knowledge buildings boosted the recognition of NoSQL databases. These database programs enable builders to effectively retailer heterogeneous knowledge that isn’t structured in tables. Should you’re inquisitive about NoSQL databases, then try Python and MongoDB: Connecting to NoSQL Databases.
Lastly, the information you’d get again from the above desk construction could be annoying to work with, as it might simply be a giant checklist of lists.
By breaking the dataset into two tables and introducing the idea of a overseas key, you’ll make the information a bit extra complicated to consider. However you’ll resolve the disadvantages of a single desk illustration.
The most important benefit of associated tables is the truth that there’s no redundant knowledge within the database. There’s just one particular person entry for every particular person you need to retailer within the database.
If the Easter Bunny nonetheless desires to alter names, you then’ll solely have to alter a single row within the particular person
desk, and anything associated to that row will instantly make the most of the change.
Additionally, the column naming is extra constant and significant. As a result of particular person and observe knowledge exist in separate tables, the creation or replace timestamp will be named constantly in each tables, as there’s no battle for names throughout tables.
However sufficient with the speculation! Within the subsequent part, you’ll create the fashions that symbolize the database desk relationships you got here up with.
Extending Your Database
On this part, you’ll lengthen your database. You’re going to change the Folks
knowledge construction in fashions.py
to present every particular person a listing of notes related to them. Lastly, you’ll populate the database with some preliminary knowledge.
Create SQLAlchemy Fashions
To make use of the 2 tables above and leverage the connection between them, you’ll have to create SQLAlchemy fashions which might be conscious of each tables and the connection between them.
Begin by updating the Individual
mannequin in fashions.py
to incorporate a relationship to a set of notes
:
1# fashions.py
2
3from datetime import datetime
4from config import db, ma
5
6class Individual(db.Mannequin):
7 __tablename__ = "particular person"
8 person_id = db.Column(db.Integer, primary_key=True)
9 lname = db.Column(db.String(32), distinctive=True)
10 fname = db.Column(db.String(32))
11 timestamp = db.Column(
12 db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
13 )
14 notes = db.relationship(
15 Word,
16 backref="particular person",
17 cascade="all, delete, delete-orphan",
18 single_parent=True,
19 order_by="desc(Word.timestamp)"
20 )
21
22# ...
In strains 14 to twenty, you create a brand new attribute within the Individual
class known as .notes
. This new .notes
attribute is outlined within the following strains of code:
-
Line 14: Just like what you’ve executed for different attributes of the category, right here you create a brand new attribute known as
.notes
and set it equal to an occasion of an object known asdb.relationship
. This object creates the connection that you just’re including to theIndividual
class, and it’s created with the entire parameters outlined within the strains that observe. -
Line 15: The parameter
Word
defines the SQLAlchemy class that theIndividual
class can be associated to. TheWord
class isn’t outlined but, so it received’t work in the mean time. Typically it is likely to be simpler to seek advice from courses as strings to keep away from points with which class is outlined first. For instance, you may use"Word"
as an alternative ofWord
right here. -
Line 16: The
backref="particular person"
parameter creates what’s often called a backwards reference inWord
objects. Every occasion ofWord
will include an attribute known as.particular person
. The.particular person
attribute references the mum or dad object {that a} explicitWord
occasion is related to. Having a reference to the mum or dad object (Individual
on this case) within the baby will be very helpful in case your code iterates over notes and has to incorporate details about the mum or dad. -
Line 17: The
cascade="all, delete, delete-orphan"
parameter determines methods to deal withWord
situations when adjustments are made to the mum or dadIndividual
occasion. For instance, when aIndividual
object is deleted, SQLAlchemy will create the SQL essential to delete theIndividual
object from the database. This parameter tells SQLAlchemy to additionally delete all of theWord
situations related to it. You may learn extra about these choices within the SQLAlchemy documentation. -
Line 18: The
single_parent=True
parameter is required ifdelete-orphan
is a part of the earliercascade
parameter. This tells SQLAlchemy to not enable an orphanedWord
occasion—that’s, aWord
with no mum or dadIndividual
object—to exist, as a result of everyWord
has a single mum or dad. -
Line 19: The
order_by="desc(Word.timestamp)"
parameter tells SQLAlchemy methods to type theWord
situations related to aIndividual
object. When aIndividual
object is retrieved, by default thenotes
attribute checklist will includeWord
objects in an unknown order. The SQLAlchemydesc()
perform will type the notes in descending order from latest to oldest, reasonably than the default ascending order.
Now that your Individual
mannequin has the brand new .notes
attribute, and this represents the one-to-many relationship to Word
objects, you’ll have to outline a SQLAlchemy mannequin for a Word
object. Because you’re referencing Word
from inside Individual
, add the brand new Word
class proper earlier than the Individual
class definition:
1# fashions.py
2
3from datetime import datetime
4from config import db, ma
5
6class Word(db.Mannequin):
7 __tablename__ = "observe"
8 id = db.Column(db.Integer, primary_key=True)
9 person_id = db.Column(db.Integer, db.ForeignKey("particular person.id"))
10 content material = db.Column(db.String, nullable=False)
11 timestamp = db.Column(
12 db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
13 )
14
15class Individual(db.Mannequin):
16 # ...
17
18# ...
The Word
class defines the attributes that make up a observe, as you discovered in your pattern observe
database desk above. With this code, you outline the attributes:
-
Line 6 creates the
Word
class, inheriting fromdb.Mannequin
, precisely as you probably did earlier than when creating theIndividual
class. -
Line 7 tells the category what database desk to make use of to retailer
Word
objects. -
Line 8 creates the
.id
attribute, defining it as an integer worth and because the main key for theWord
object. -
Line 9 creates the
.person_id
attribute and defines it because the overseas key, relating theWord
class to theIndividual
class utilizing the.particular person.id
main key. This and theIndividual.notes
attribute are how SQLAlchemy is aware of what to do when interacting withIndividual
andWord
objects. -
Line 10 creates the
.content material
attribute, which comprises the precise textual content of the observe. Thenullable=False
parameter signifies that it’s okay to create new notes that don’t have any content material. -
Strains 11 to 13 create the
.timestamp
attribute, and precisely like within theIndividual
class, this attribute comprises the creation or replace time for any explicitWord
occasion.
Now that you just’ve up to date Folks
and created the mannequin for Word
, go on to replace the database.
Feed the Database
Now that you just’ve up to date Individual
and created the Word
mannequin, you’ll use them to rebuild the folks.db
database. To do that, create a helper Python script named build_database.py
:
# build_database.py
from datetime import datetime
from config import app, db
from fashions import Individual, Word
PEOPLE_NOTES = [
{
"lname": "Fairy",
"fname": "Tooth",
"notes": [
("I brush my teeth after each meal.", "2022-01-06 17:10:24"),
("The other day a friend said, I have big teeth.", "2022-03-05 22:17:54"),
("Do you pay per gram?", "2022-03-05 22:18:10"),
],
},
{
"lname": "Ruprecht",
"fname": "Knecht",
"notes": [
("I swear, I'll do better this year.", "2022-01-01 09:15:03"),
("Really! Only good deeds from now on!", "2022-02-06 13:09:21"),
],
},
{
"lname": "Bunny",
"fname": "Easter",
"notes": [
("Please keep the current inflation rate in mind!", "2022-01-07 22:47:54"),
("No need to hide the eggs this time.", "2022-04-06 13:03:17"),
],
},
]
with app.app_context():
db.drop_all()
db.create_all()
for knowledge in PEOPLE_NOTES:
new_person = Individual(lname=knowledge.get("lname"), fname=knowledge.get("fname"))
for content material, timestamp in knowledge.get("notes", []):
new_person.notes.append(
Word(
content material=content material,
timestamp=datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S"),
)
)
db.session.add(new_person)
db.session.commit()
Within the code above, you’re feeding your mission’s database with the content material of PEOPLE_NOTES
. You utilize db
out of your config
module so Python is aware of methods to deal with knowledge
and commit it to the corresponding database tables and cells.
Word: If you execute build_database.py
, you’ll re-create folks.db
. Any present knowledge in folks.db
can be misplaced.
Operating the build_database.py
program from the command line will re-create the database with the brand new additions, getting it prepared to be used with the online software:
(venv) $ python build_database.py
As soon as your mission comprises a contemporary database, you may alter your mission to show the notes within the entrance finish.
Displaying Folks With Their Notes
Now that your database comprises knowledge to work with, you can begin displaying the information in each the entrance finish and your REST API.
Present Notes within the Entrance Finish
Within the earlier part, you created the connection between an individual and their notes by including a .notes
attribute to the Individual
class.
Replace house.html
in your templates/
folder to entry an individual’s notes:
<!-- templates/house.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RP Flask REST API</title>
</head>
<physique>
<h1>
Whats up, Folks!
</h1>
{% for particular person in folks %}
<h2>{{ particular person.fname }} {{ particular person.lname }}</h2>
<ul>
{% for observe in particular person.notes %}
<li>
{{ observe.content material }}
</li>
{% endfor %}
</ul>
{% endfor %}
</physique>
</html>
Within the code above, you entry the .notes
attribute of every particular person. After that, you’re looping via all of the notes for a selected particular person to entry a observe’s content material.
Navigate to http://localhost:8000
to examine in case your template renders as anticipated:

Excellent, you may see the notes from every particular person listed in your entrance finish.
Which means Flask efficiently connects Individual
and Notes
beneath the hood and serves you a folks
object you can conveniently work with.
Reply With Notes
Subsequent, examine the /api/folks
endpoint of your API at http://localhost:8000/api/folks
:

You’re receiving the folks assortment with none errors. Nevertheless, there are not any notes within the knowledge you obtain.
To analyze the difficulty, take a look at read_all()
in folks.py
:
1# folks.py
2
3# ...
4
5def read_all():
6 folks = Individual.question.all()
7 person_schema = PersonSchema(many=True)
8 return person_schema.dump(folks)
9
10# ...
The .dump()
methodology in line 8 works with what it receives and doesn’t filter out any knowledge. So the difficulty could also be within the definition of both folks
in line 6 or person_schema
in line 7.
The question name to the database to populate folks
is precisely the identical because the one in app.py
:
This name efficiently labored within the entrance finish to indicate the notes for every particular person. This singles out PersonSchema
because the almost certainly perpetrator.
By default, a Marshmallow schema doesn’t traverse into associated database objects. It’s important to explicitly inform a schema to incorporate relationships.
Open fashions.py
and replace PersonSchema
:
# fashions.py
# ...
class PersonSchema(ma.SQLAlchemyAutoSchema):
class Meta:
mannequin = Individual
load_instance = True
sqla_session = db.session
include_relationships = True
With include_relationships
within the Meta
class of PersonSchema
, you inform Marshmallow so as to add any associated objects to the particular person schema. Nevertheless, the consequence nonetheless doesn’t look as anticipated:

The response at http://localhost:8000/api/folks
now comprises every particular person’s notes. However as an alternative of exhibiting all the information a observe comprises, the notes
object solely comprises a listing of main keys.
Create a Notes Schema
Your API response solely listed the first keys of every particular person’s notes. That’s truthful, since you haven’t but declared how Marshmallow ought to deserialize the notes.
Assist Marshmallow out by creating NoteSchema
in fashions.py
beneath Word
and above Individual
:
# fashions.py
# ...
class Word(db.Mannequin):
# ...
class NoteSchema(ma.SQLAlchemyAutoSchema):
class Meta:
mannequin = Word
load_instance = True
sqla_session = db.session
include_fk = True
class Individual(db.Mannequin):
# ...
class PersonSchema(ma.SQLAlchemyAutoSchema):
# ...
note_schema = NoteSchema()
# ...
You’re referencing Word
from inside NoteSchema
, so you will need to place NoteSchema
beneath your Word
class definition to forestall errors. You additionally instantiate NoteSchema
to create an object that you just’ll seek advice from later.
Since your Word
mannequin comprises a overseas key, you will need to set include_fk
to True
. In any other case Marshmallow wouldn’t acknowledge person_id
through the serialization course of.
With NoteSchema
in place, you may reference it in PeopleSchema
:
# fashions.py
from datetime import datetime
from marshmallow_sqlalchemy import fields
from config import db, ma
# ...
class PersonSchema(ma.SQLAlchemyAutoSchema):
class Meta:
mannequin = Individual
load_instance = True
sqla_session = db.session
include_relationships = True
notes = fields.Nested(NoteSchema, many=True)
After importing fields
from marshmallow_sqlalchemy
, you may reference the associated Word
object by its NoteSchema
. To keep away from operating into errors, confirm that you just outlined NoteSchema
above PeopleSchema
.
Though you’re working with SQLAlchemyAutoSchema
, it’s important to explicitly create the notes
area in PersonSchema
. In any other case Marshmallow doesn’t obtain all the knowledge it must work with the Notes
knowledge. For instance, it received’t know that you just’re anticipating a listing of objects utilizing the many
argument.
With the adjustments in place, examine the endpoint of your API at http://localhost:8000/api/folks
:

Excellent, your read_all()
perform not solely returns all of the folks, but additionally all of the notes which might be hooked up to every particular person!
Within the subsequent part, you’ll lengthen your Flask REST API to create, learn, replace, and delete a single observe.
Deal with Notes With Your REST API
You’ve up to date the SQLAlchemy fashions and used them to learn from the folks.db
database. Your notes can be found as a nested schema in Folks
. You obtain the checklist of notes while you request a set of individuals or a selected particular person:
Motion | HTTP Verb | URL Path | Description |
---|---|---|---|
Learn | GET |
/api/folks |
Learn a set of individuals. |
Learn | GET |
/api/folks/<lname> |
Learn a selected particular person. |
When you can learn the notes over the endpoints proven within the desk above, there’s presently no solution to learn just one observe or to handle any notes in your REST API.
Word: The URL parameters are case delicate. For instance, you will need to go to http://localhost:8000/api/folks/Ruprecht
with an uppercase R within the final identify Ruprecht.
You may jump over to half one to recap the way you constructed the present folks
endpoints of your REST API. On this part of the tutorial, you’ll add further endpoints to offer performance to create, learn, replace, and delete notes:
Motion | HTTP Verb | URL Path | Description |
---|---|---|---|
Create | POST |
/api/notes |
URL to create a brand new observe |
Learn | GET |
/api/notes/<note_id> |
URL to learn a single observe |
Replace | PUT |
api/notes/<note_id> |
URL to replace a single observe |
Delete | DELETE |
api/notes/<note_id> |
URL to delete a single observe |
You’ll begin off by including the performance to learn a single observe. To take action, you’ll alter your Swagger configuration file that comprises your API definitions.
Learn a Single Word
At present you’re in a position to obtain all of the notes of an individual while you request knowledge from that specific particular person. To get details about one observe, you’ll add one other endpoint.
Earlier than you add the endpoint, replace your Swagger configuration by making a note_id
parameter element within the swagger.yml
file:
# swagger.yml
# ...
parts:
schemas:
# ...
parameters:
lname:
# ...
note_id:
identify: "note_id"
description: "ID of the observe"
in: path
required: true
schema:
kind: "integer"
# ...
The note_id
in parameters
can be a part of your endpoints to determine which observe you need to deal with.
Proceed to edit swagger.yml
and add the information for the endpoint to learn a single observe:
# swagger.yml
# ...
paths:
/folks:
# ...
/folks/{lname}:
# ...
/notes/{note_id}:
get:
operationId: "notes.read_one"
tags:
- Notes
abstract: "Learn one observe"
parameters:
- $ref: "#/parts/parameters/note_id"
responses:
"200":
description: "Efficiently learn one observe"
The construction of /notes/{note_id}
is much like /folks/{lname}
. You begin with the get
operation for the /notes/{note_id}
path. The {note_id}
substring is a placeholder for the ID of a observe that it’s important to move in as a URL parameter. So, for instance, the URL http://localhost:8000/api/notes/1
will provide you with the information for the observe with the first key 1
.
The operationId
factors to notes.read_one
. Which means your API expects a read_one()
perform in a notes.py
file. Go on, create notes.py
and add read_one()
:
# notes.py
from flask import abort, make_response
from config import db
from fashions import Word, note_schema
def read_one(note_id):
observe = Word.question.get(note_id)
if observe is not None:
return note_schema.dump(observe)
else:
abort(
404, f"Word with ID {note_id} not discovered"
)
Though you’re not utilizing make_response()
and db
but, you may go forward and add them to your imports already. You’ll use them in a bit while you’re writing to the database.
For now, you’re solely studying from the database with the note_id
parameter from the REST URL path. You utilize note_id
within the question’s .get()
methodology to get the observe with the first key of the note_id
integer.
If a observe is discovered, then observe
comprises a Word
object and you come back the serialized object. Go forward and take a look at it out by visiting http://localhost:8000/api/notes/1
in your browser:

Excellent, the API response with the observe dataset seems to be precisely as anticipated! Subsequent, you’ll use the identical endpoint to replace and delete a observe.
Replace and Delete a Word
This time, you begin by creating the features in notes.py
first, earlier than creating the operations in swagger.yml
.
Add replace()
and delete()
to notes.py
:
# notes.py
# ...
def replace(note_id, observe):
existing_note = Word.question.get(note_id)
if existing_note:
update_note = note_schema.load(observe, session=db.session)
existing_note.content material = update_note.content material
db.session.merge(existing_note)
db.session.commit()
return note_schema.dump(existing_note), 201
else:
abort(404, f"Word with ID {note_id} not discovered")
def delete(note_id):
existing_note = Word.question.get(note_id)
if existing_note:
db.session.delete(existing_note)
db.session.commit()
return make_response(f"{note_id} efficiently deleted", 204)
else:
abort(404, f"Word with ID {note_id} not discovered")
If you evaluate replace()
with delete()
, they share the same construction. Each features search for an present observe and work with a database session.
For replace()
to work, you additionally settle for a observe
object as an argument, which comprises the .content material
attribute that you could be replace.
In distinction, you solely have to know the ID of the observe that you just need to do away with when calling delete()
.
Subsequent, create two operations in swagger.yml
that seek advice from notes.replace
and notes.delete
:
# swagger.yml
# ...
paths:
/folks:
# ...
/folks/{lname}:
# ...
/notes/{note_id}:
get:
# ...
put:
tags:
- Notes
operationId: "notes.replace"
abstract: "Replace a observe"
parameters:
- $ref: "#/parts/parameters/note_id"
responses:
"200":
description: "Efficiently up to date observe"
requestBody:
content material:
software/json:
schema:
x-body-name: "observe"
kind: "object"
properties:
content material:
kind: "string"
delete:
tags:
- Notes
operationId: "notes.delete"
abstract: "Delete a observe"
parameters:
- $ref: "#/parts/parameters/note_id"
responses:
"204":
description: "Efficiently deleted observe"
Once more, the construction of put
and delete
are comparable. The primary distinction is that you want to present a requestBody
that comprises the observe knowledge to replace the database object.
You’ve now created the endpoints to work with present notes. Subsequent, you’ll add the endpoint to create a observe.
Create a Word for a Individual
To this point, you may learn, replace, and delete a single observe. These are actions you can carry out on present notes. Now it’s time so as to add the performance to your REST API to additionally create a brand new observe.
Add create()
to notes.py
:
# notes.py
from flask import make_response, abort
from config import db
from fashions import Word, Individual, note_schema
# ...
def create(observe):
person_id = observe.get("person_id")
particular person = Individual.question.get(person_id)
if particular person:
new_note = note_schema.load(observe, session=db.session)
particular person.notes.append(new_note)
db.session.commit()
return note_schema.dump(new_note), 201
else:
abort(
404,
f"Individual not discovered for ID: {person_id}"
)
A observe all the time wants an individual to belong to. That’s why you want to work with the Individual
mannequin while you create a brand new observe.
First, you search for the proprietor of the observe through the use of person_id
, which you present with the notes
argument for create()
. If this particular person exists within the database, you then go forward to append the brand new observe to particular person.notes
.
Though you’re working with the particular person
database desk on this case, SQLAlchemy will take care that the observe is added to the observe
desk.
To entry notes.create
together with your API, jump over to swagger.yml
and add one other endpoint:
# swagger.yml
# ...
paths:
/folks:
# ...
/folks/{lname}:
# ...
/notes:
submit:
operationId: "notes.create"
tags:
- Notes
abstract: "Create a observe related with a particular person"
requestBody:
description: "Word to create"
required: True
content material:
software/json:
schema:
x-body-name: "observe"
kind: "object"
properties:
person_id:
kind: "integer"
content material:
kind: "string"
responses:
"201":
description: "Efficiently created a observe"
/notes/{note_id}:
# ...
You add the /notes
endpoint proper earlier than the /notes/{noted_id}
endpoint. That manner, you order your notes endpoints from common to particular. This order lets you navigate your swagger.yml
file when your API grows bigger.
With the information within the schema
block, you present Marshmallow the knowledge on methods to serialize a observe in your API. Should you evaluate this Word
schema to the Word
mannequin in fashions.py
, you then’ll discover that the names person_id
and content material
match. The identical goes for the fields’ varieties.
You may additionally discover that not all of the observe mannequin fields are current within the element schema. That’s okay, since you’ll solely use this schema to submit new notes. For every observe, id
and timestamp
can be set mechanically.
With all of the endpoints to deal with your notes in place, it’s time to take a look at your API documentation.
Discover Your API Documentation
With the above adjustments in place, you may leverage your API so as to add, replace, and take away notes. Go to your Swagger UI at http://localhost:8000/api/ui
and discover your API endpoints:
Superior, your Flask REST API endpoints work! Any adjustments that you just carry out together with your API seem in your entrance finish, too.
Conclusion
On this tutorial, you adjusted your SQLite database to implement relationships. After that, you translated the PEOPLE_NOTES
dictionary into knowledge that conforms together with your database construction, and also you turned your Flask REST API right into a note-keeping net software.
Within the third a part of this tutorial collection, you discovered methods to:
- Work with a number of tables in a database
- Create one-to-many fields in your database
- Handle relationships with SQLAlchemy
- Leverage nested schemas with Marshmallow
- Show associated objects within the entrance finish
Figuring out methods to construct and use database relationships offers you a strong device to resolve many troublesome issues. There are different relationship apart from the one-to-many instance from this tutorial. Different frequent ones are one-to-one, many-to-many, and many-to-one. All of them have a spot in your device belt, and SQLAlchemy will help you sort out all of them!
You’ve efficiently constructed a REST API to maintain observe of notes for individuals who could go to you all year long. Your database comprises folks just like the Tooth Fairy, the Easter Bunny, and Knecht Ruprecht. By including notes, you may hold observe of your good deeds and hopefully obtain precious presents from them.
To evaluation your code, click on the hyperlink under:
Did you add a particular particular person or observe to your Flask REST API mission? Let the Actual Python group know within the feedback under.