Most trendy net purposes are powered by a REST API beneath the hood. That approach, 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 fundamental Flask venture and added endpoints, which you linked to a SQLite database. You’re additionally testing your API with Swagger UI API documentation that you simply’re constructing alongside the best way.
Within the third a part of this tutorial collection, you’ll learn 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 venture by clicking the hyperlink beneath:
Demo
On this three-part tutorial collection, you’re constructing a REST API to maintain monitor of notes for individuals who might go to you all year long. You’ll create individuals 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 useful presents from them.
On this tutorial, you’ll broaden your programming instrument belt additional. You’ll learn to create hierarchical knowledge buildings represented as one-to-many relationships by SQLAlchemy. As well as, you’ll additionally prolong the REST API that you simply’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 individuals and notes!
Planning Half Three
In part one of this collection, you constructed your REST API. Working by part two, you linked your REST API to a database. That approach, your Flask utility could make modifications to current knowledge and create new knowledge that persists even while you restart your app server.
To date, you’ve added the power to save lots of modifications made by the REST API to a database utilizing SQLAlchemy and discovered methods to serialize that knowledge for the REST API utilizing Marshmallow.
At present, the individuals.db
database solely comprises individuals 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 individual
desk and the word
desk in your database.
You’ll bootstrap individuals.db
with a build_database.py
script that comprises the mandatory individuals and notes knowledge for you.
Right here’s an excerpt of the dataset that you simply’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 learn to alter your SQLite database to implement relationships. After that, you’ll have the ability to translate the PEOPLE_NOTES
dictionary into knowledge that conforms along 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 simply’re writing for individuals.
Getting Began
Ideally, you adopted the first part and the second part 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 beneath:
For those who downloaded the supply code from the hyperlink above, then be certain that to observe the set up directions inside the supplied README.md
file.
Earlier than you proceed with the tutorial, confirm that your folder construction seems like this:
rp_flask_api/
│
├── templates/
│ └── dwelling.html
│
├── app.py
├── config.py
├── fashions.py
├── individuals.py
└── swagger.yml
When you’ve received the Flask REST API folder construction in place, you may learn on to examine in case your Flask venture works as anticipated.
Verify Your Flask Undertaking
Earlier than you proceed working in your Flask venture, it’s a good suggestion to create and activate a virtual environment. That approach, you’re putting in any venture dependencies not system-wide however solely in your venture’s digital atmosphere.
Choose your working system beneath and use your platform-specific command to arrange a digital atmosphere:
With the instructions proven above, you create and activate a digital atmosphere named venv
by utilizing Python’s built-in venv
module. The parenthesized (venv)
in entrance of the immediate point out that you simply’ve efficiently activated the digital atmosphere.
Be aware: For those who haven’t labored by half two of this tutorial collection, then be certain that to obtain the supply code by clicking the hyperlink beneath:
Earlier than persevering with, set up the dependencies by following the directions listed within the supplied README.md
file.
Now you may confirm that your Flask utility is working with out errors. Execute the next command within the listing containing the app.py
file:
While you run this utility, an online server will begin on port 8000. For those who open a browser and navigate to http://localhost:8000
, it is best to see a web page with the heading Hi there, Individuals! displayed:

Excellent, your app is working 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 simply’ll work with.
The individual
desk of your individuals.db
database presently seems 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 prolong 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"),
],
,
]
Be aware that the lname
values in PEOPLE_NOTES
correspond to the contents of your lname
column within the individual
desk of your individuals.db
database.
Within the dataset above, every individual features a key known as notes
, which is related to an inventory containing tuples of knowledge. Every tuple within the notes
checklist represents a single word containing the content material and a timestamp.
Every single individual is related to a number of notes, and every single word is related to just one individual. This hierarchy of knowledge 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 Individuals
As a substitute of extending the individual
desk and making an attempt to signify hierarchical knowledge in a single desk, you’ll break up the info into a number of tables and join them.
For the individual
desk, this implies there will probably be no modifications. To signify the brand new word data, you’ll create a brand new desk known as word
.
The word
desk will appear 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 buddy stated, 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 12 months. | 2022-01-01 09:15:03 |
5 | 2 | Actually! Solely good deeds any longer! | 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 individual
desk, the word
desk has a novel identifier known as id
, which is the major key for the word
desk. The person_id
column creates the connection to the individual
desk.
Whereas id
is the first key for the desk, person_id
is what’s generally known as a overseas key. The foreign key provides every entry within the word
desk the first key of the individual
report that it’s related to. Utilizing this, SQLAlchemy can collect all of the notes related to every individual by connecting the individual.id
major key to the word.person_id
overseas key, making a relationship.
The database that you simply constructed saved the info in a desk, and a desk is a two-dimensional array of rows and columns. Can the Individuals
dictionary above be represented in a single desk of rows and columns? It may be, within the following approach, in your individual
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 buddy stated, 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 12 months. | 2022-01-01 09:15:03 |
5 | Ruprecht | Knecht | 2022-10-08 09:15:13 | Actually! Solely good deeds any longer! | 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 truly work. All the info is represented, and a single individual is related to a set of various notes.
Conceptually, the above desk construction has the benefit of being comparatively easy to know. You might even make the case that the info could possibly be persevered 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 attributable to redundant knowledge
- Awkward column names
- Issue presenting one-to-many relationships
In an effort to signify the gathering of notes, all the info for every individual is repeated for each distinctive word. The individual knowledge is due to this fact redundant. This isn’t such an enormous deal to your individual knowledge, as there aren’t that many columns. However think about if an individual had many extra columns. Even with massive disk drives, this might get to be a storage concern in the event you have been coping with thousands and thousands of rows of knowledge.
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 title was a good suggestion? In an effort to do that, each report containing the Easter Bunny’s title must be up to date with a purpose to hold the info constant. This sort of work towards the database can result in knowledge inconsistency, notably if the work is completed by an individual working 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 word, however as a result of timestamp
is already used, a contrived title of note_timestamp
is used.
What in the event you needed so as to add extra one-to-many relationships to the individual
desk? For instance, perhaps you’ll resolve to incorporate an individual’s kids or cellphone numbers. Every individual may have a number of kids and a number of cellphone numbers. With the Python Individuals
dictionary above, you might do that comparatively simply by including kids
and phone_numbers
keys with new lists containing the info.
Nevertheless, representing these new one-to-many relationships in your individual
database desk above turns into considerably tougher. Each new one-to-many relationship dramatically will increase the variety of rows essential to signify it for each single entry within the baby knowledge. As well as, the issues related to knowledge redundancy get larger and tougher to deal with.
Be aware: The necessity for storing more and more massive and sophisticated knowledge buildings boosted the recognition of NoSQL databases. These database methods enable builders to effectively retailer heterogeneous knowledge that isn’t structured in tables. For those who’re interested in NoSQL databases, then take a look at Python and MongoDB: Connecting to NoSQL Databases.
Lastly, the info you’d get again from the above desk construction could be annoying to work with, as it might simply be an enormous checklist of lists.
By breaking the dataset into two tables and introducing the idea of a overseas key, you’ll make the info a little bit extra complicated to consider. However you’ll resolve the disadvantages of a single desk illustration.
The largest benefit of associated tables is the truth that there’s no redundant knowledge within the database. There’s just one individual entry for every individual you need to retailer within the database.
If the Easter Bunny nonetheless desires to vary names, then you definitely’ll solely have to vary a single row within the individual
desk, and anything associated to that row will instantly benefit from the change.
Additionally, the column naming is extra constant and significant. As a result of individual and word knowledge exist in separate tables, the creation or replace timestamp might be named constantly in each tables, as there’s no battle for names throughout tables.
However sufficient with the idea! Within the subsequent part, you’ll create the fashions that signify the database desk relationships you got here up with.
Extending Your Database
On this part, you’ll prolong your database. You’re going to switch the Individuals
knowledge construction in fashions.py
to present every individual an inventory 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 must create SQLAlchemy fashions which might be conscious of each tables and the connection between them.
Begin by updating the Particular person
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 Particular person(db.Mannequin):
7 __tablename__ = "individual"
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 Be aware,
16 backref="individual",
17 cascade="all, delete, delete-orphan",
18 single_parent=True,
19 order_by="desc(Be aware.timestamp)"
20 )
21
22# ...
In strains 14 to twenty, you create a brand new attribute within the Particular person
class known as .notes
. This new .notes
attribute is outlined within the following strains of code:
-
Line 14: Much like what you’ve accomplished 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 simply’re including to theParticular person
class, and it’s created with all the parameters outlined within the strains that observe. -
Line 15: The parameter
Be aware
defines the SQLAlchemy class that theParticular person
class will probably be associated to. TheBe aware
class isn’t outlined but, so it gained’t work for the time being. Typically it is perhaps simpler to confer with courses as strings to keep away from points with which class is outlined first. For instance, you might use"Be aware"
as an alternative ofBe aware
right here. -
Line 16: The
backref="individual"
parameter creates what’s generally known as a backwards reference inBe aware
objects. Every occasion ofBe aware
will include an attribute known as.individual
. The.individual
attribute references the mum or dad object {that a} explicitBe aware
occasion is related to. Having a reference to the mum or dad object (Particular person
on this case) within the baby might 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 withBe aware
cases when modifications are made to the mum or dadParticular person
occasion. For instance, when aParticular person
object is deleted, SQLAlchemy will create the SQL essential to delete theParticular person
object from the database. This parameter tells SQLAlchemy to additionally delete all of theBe aware
cases 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 orphanedBe aware
occasion—that’s, aBe aware
with out a mum or dadParticular person
object—to exist, as a result of everyBe aware
has a single mum or dad. -
Line 19: The
order_by="desc(Be aware.timestamp)"
parameter tells SQLAlchemy methods to kind theBe aware
cases related to aParticular person
object. When aParticular person
object is retrieved, by default thenotes
attribute checklist will includeBe aware
objects in an unknown order. The SQLAlchemydesc()
perform will kind the notes in descending order from latest to oldest, somewhat than the default ascending order.
Now that your Particular person
mannequin has the brand new .notes
attribute, and this represents the one-to-many relationship to Be aware
objects, you’ll must outline a SQLAlchemy mannequin for a Be aware
object. Because you’re referencing Be aware
from inside Particular person
, add the brand new Be aware
class proper earlier than the Particular person
class definition:
1# fashions.py
2
3from datetime import datetime
4from config import db, ma
5
6class Be aware(db.Mannequin):
7 __tablename__ = "word"
8 id = db.Column(db.Integer, primary_key=True)
9 person_id = db.Column(db.Integer, db.ForeignKey("individual.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 Particular person(db.Mannequin):
16 # ...
17
18# ...
The Be aware
class defines the attributes that make up a word, as you discovered in your pattern word
database desk above. With this code, you outline the attributes:
-
Line 6 creates the
Be aware
class, inheriting fromdb.Mannequin
, precisely as you probably did earlier than when creating theParticular person
class. -
Line 7 tells the category what database desk to make use of to retailer
Be aware
objects. -
Line 8 creates the
.id
attribute, defining it as an integer worth and because the major key for theBe aware
object. -
Line 9 creates the
.person_id
attribute and defines it because the overseas key, relating theBe aware
class to theParticular person
class utilizing the.individual.id
major key. This and theParticular person.notes
attribute are how SQLAlchemy is aware of what to do when interacting withParticular person
andBe aware
objects. -
Line 10 creates the
.content material
attribute, which comprises the precise textual content of the word. Thenullable=False
parameter signifies that it’s okay to create new notes that haven’t any content material. -
Traces 11 to 13 create the
.timestamp
attribute, and precisely like within theParticular person
class, this attribute comprises the creation or replace time for any explicitBe aware
occasion.
Now that you simply’ve up to date Individuals
and created the mannequin for Be aware
, go on to replace the database.
Feed the Database
Now that you simply’ve up to date Particular person
and created the Be aware
mannequin, you’ll use them to rebuild the individuals.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 Particular person, Be aware
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 = Particular person(lname=knowledge.get("lname"), fname=knowledge.get("fname"))
for content material, timestamp in knowledge.get("notes", []):
new_person.notes.append(
Be aware(
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 venture’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.
Be aware: While you execute build_database.py
, you’ll re-create individuals.db
. Any current knowledge in individuals.db
will probably be misplaced.
Working 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 utility:
(venv) $ python build_database.py
As soon as your venture comprises a contemporary database, you may alter your venture to show the notes within the entrance finish.
Displaying Individuals With Their Notes
Now that your database comprises knowledge to work with, you can begin displaying the info 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 Particular person
class.
Replace dwelling.html
in your templates/
folder to entry an individual’s notes:
<!-- templates/dwelling.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RP Flask REST API</title>
</head>
<physique>
<h1>
Hi there, Individuals!
</h1>
% for individual in individuals %
<h2> individual.fname individual.lname </h2>
<ul>
% for word in individual.notes %
<li>
word.content material
</li>
% endfor %
</ul>
% endfor %
</physique>
</html>
Within the code above, you entry the .notes
attribute of every individual. After that, you’re looping by all of the notes for a specific individual to entry a word’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 individual listed in your entrance finish.
Which means Flask efficiently connects Particular person
and Notes
beneath the hood and serves you a individuals
object that you could conveniently work with.
Reply With Notes
Subsequent, examine the /api/individuals
endpoint of your API at http://localhost:8000/api/individuals
:

You’re receiving the individuals assortment with none errors. Nevertheless, there are not any notes within the knowledge you obtain.
To research the problem, take a look at read_all()
in individuals.py
:
1# individuals.py
2
3# ...
4
5def read_all():
6 individuals = Particular person.question.all()
7 person_schema = PersonSchema(many=True)
8 return person_schema.dump(individuals)
9
10# ...
The .dump()
technique in line 8 works with what it receives and doesn’t filter out any knowledge. So the problem could also be within the definition of both individuals
in line 6 or person_schema
in line 7.
The question name to the database to populate individuals
is precisely the identical because the one in app.py
:
This name efficiently labored within the entrance finish to indicate the notes for every individual. This singles out PersonSchema
because the most probably 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 = Particular person
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 individual schema. Nevertheless, the end result nonetheless doesn’t look as anticipated:

The response at http://localhost:8000/api/individuals
now comprises every individual’s notes. However as an alternative of exhibiting all the info a word comprises, the notes
object solely comprises an inventory of major keys.
Create a Notes Schema
Your API response solely listed the first keys of every individual’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 Be aware
and above Particular person
:
# fashions.py
# ...
class Be aware(db.Mannequin):
# ...
class NoteSchema(ma.SQLAlchemyAutoSchema):
class Meta:
mannequin = Be aware
load_instance = True
sqla_session = db.session
include_fk = True
class Particular person(db.Mannequin):
# ...
class PersonSchema(ma.SQLAlchemyAutoSchema):
# ...
note_schema = NoteSchema()
# ...
You’re referencing Be aware
from inside NoteSchema
, so it’s essential to place NoteSchema
beneath your Be aware
class definition to stop errors. You additionally instantiate NoteSchema
to create an object that you simply’ll confer with later.
Since your Be aware
mannequin comprises a overseas key, it’s essential 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 = Particular person
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 Be aware
object by its NoteSchema
. To keep away from working into errors, confirm that you simply outlined NoteSchema
above PeopleSchema
.
Though you’re working with SQLAlchemyAutoSchema
, you must explicitly create the notes
subject in PersonSchema
. In any other case Marshmallow doesn’t obtain all the data it must work with the Notes
knowledge. For instance, it gained’t know that you simply’re anticipating an inventory of objects utilizing the many
argument.
With the modifications in place, examine the endpoint of your API at http://localhost:8000/api/individuals
:

Excellent, your read_all()
perform not solely returns all of the individuals, but in addition all of the notes which might be hooked up to every individual!
Within the subsequent part, you’ll prolong your Flask REST API to create, learn, replace, and delete a single word.
Deal with Notes With Your REST API
You’ve up to date the SQLAlchemy fashions and used them to learn from the individuals.db
database. Your notes can be found as a nested schema in Individuals
. You obtain the checklist of notes while you request a set of individuals or a specific individual:
Motion | HTTP Verb | URL Path | Description |
---|---|---|---|
Learn | GET |
/api/individuals |
Learn a set of individuals. |
Learn | GET |
/api/individuals/<lname> |
Learn a specific individual. |
When you can learn the notes over the endpoints proven within the desk above, there’s presently no strategy to learn just one word or to handle any notes in your REST API.
Be aware: The URL parameters are case delicate. For instance, it’s essential to go to http://localhost:8000/api/individuals/Ruprecht
with an uppercase R within the final title Ruprecht.
You may jump over to part one to recap the way you constructed the prevailing individuals
endpoints of your REST API. On this part of the tutorial, you’ll add extra endpoints to supply performance to create, learn, replace, and delete notes:
Motion | HTTP Verb | URL Path | Description |
---|---|---|---|
Create | POST |
/api/notes |
URL to create a brand new word |
Learn | GET |
/api/notes/<note_id> |
URL to learn a single word |
Replace | PUT |
api/notes/<note_id> |
URL to replace a single word |
Delete | DELETE |
api/notes/<note_id> |
URL to delete a single word |
You’ll begin off by including the performance to learn a single word. To take action, you’ll alter your Swagger configuration file that comprises your API definitions.
Learn a Single Be aware
At present you’re in a position to obtain all of the notes of an individual while you request knowledge from that specific individual. To get details about one word, you’ll add one other endpoint.
Earlier than you add the endpoint, replace your Swagger configuration by making a note_id
parameter part within the swagger.yml
file:
# swagger.yml
# ...
parts:
schemas:
# ...
parameters:
lname:
# ...
note_id:
title: "note_id"
description: "ID of the word"
in: path
required: true
schema:
kind: "integer"
# ...
The note_id
in parameters
will probably be a part of your endpoints to determine which word you need to deal with.
Proceed to edit swagger.yml
and add the info for the endpoint to learn a single word:
# swagger.yml
# ...
paths:
/individuals:
# ...
/individuals/lname:
# ...
/notes/note_id:
get:
operationId: "notes.read_one"
tags:
- Notes
abstract: "Learn one word"
parameters:
- $ref: "#/parts/parameters/note_id"
responses:
"200":
description: "Efficiently learn one word"
The construction of /notes/note_id
is just like /individuals/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 word that you must go in as a URL parameter. So, for instance, the URL http://localhost:8000/api/notes/1
gives you the info for the word 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 Be aware, note_schema
def read_one(note_id):
word = Be aware.question.get(note_id)
if word is not None:
return note_schema.dump(word)
else:
abort(
404, f"Be aware 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()
technique to get the word with the first key of the note_id
integer.
If a word is discovered, then word
comprises a Be aware
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 word dataset seems precisely as anticipated! Subsequent, you’ll use the identical endpoint to replace and delete a word.
Replace and Delete a Be aware
This time, you begin by creating the capabilities 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, word):
existing_note = Be aware.question.get(note_id)
if existing_note:
update_note = note_schema.load(word, 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"Be aware with ID note_id not discovered")
def delete(note_id):
existing_note = Be aware.question.get(note_id)
if existing_note:
db.session.delete(existing_note)
db.session.commit()
return make_response(f"note_id efficiently deleted", 200)
else:
abort(404, f"Be aware with ID note_id not discovered")
While you evaluate replace()
with delete()
, they share an identical construction. Each capabilities search for an current word and work with a database session.
For replace()
to work, you additionally settle for a word
object as an argument, which comprises the .content material
attribute that you could be replace.
In distinction, you solely must know the ID of the word that you simply need to eliminate when calling delete()
.
Subsequent, create two operations in swagger.yml
that confer with notes.replace
and notes.delete
:
# swagger.yml
# ...
paths:
/individuals:
# ...
/individuals/lname:
# ...
/notes/note_id:
get:
# ...
put:
tags:
- Notes
operationId: "notes.replace"
abstract: "Replace a word"
parameters:
- $ref: "#/parts/parameters/note_id"
responses:
"200":
description: "Efficiently up to date word"
requestBody:
content material:
utility/json:
schema:
x-body-name: "word"
kind: "object"
properties:
content material:
kind: "string"
delete:
tags:
- Notes
operationId: "notes.delete"
abstract: "Delete a word"
parameters:
- $ref: "#/parts/parameters/note_id"
responses:
"204":
description: "Efficiently deleted word"
Once more, the construction of put
and delete
are comparable. The primary distinction is that it’s good to present a requestBody
that comprises the word knowledge to replace the database object.
You’ve now created the endpoints to work with current notes. Subsequent, you’ll add the endpoint to create a word.
Create a Be aware for a Particular person
To date, you may learn, replace, and delete a single word. These are actions that you could carry out on current notes. Now it’s time so as to add the performance to your REST API to additionally create a brand new word.
Add create()
to notes.py
:
# notes.py
from flask import make_response, abort
from config import db
from fashions import Be aware, Particular person, note_schema
# ...
def create(word):
person_id = word.get("person_id")
individual = Particular person.question.get(person_id)
if individual:
new_note = note_schema.load(word, session=db.session)
individual.notes.append(new_note)
db.session.commit()
return note_schema.dump(new_note), 201
else:
abort(
404,
f"Particular person not discovered for ID: person_id"
)
A word all the time wants an individual to belong to. That’s why it’s good to work with the Particular person
mannequin while you create a brand new word.
First, you search for the proprietor of the word by utilizing person_id
, which you present with the notes
argument for create()
. If this individual exists within the database, then you definitely go forward to append the brand new word to individual.notes
.
Though you’re working with the individual
database desk on this case, SQLAlchemy will take care that the word is added to the word
desk.
To entry notes.create
along with your API, jump over to swagger.yml
and add one other endpoint:
# swagger.yml
# ...
paths:
/individuals:
# ...
/individuals/lname:
# ...
/notes:
publish:
operationId: "notes.create"
tags:
- Notes
abstract: "Create a word related with a individual"
requestBody:
description: "Be aware to create"
required: True
content material:
utility/json:
schema:
x-body-name: "word"
kind: "object"
properties:
person_id:
kind: "integer"
content material:
kind: "string"
responses:
"201":
description: "Efficiently created a word"
/notes/note_id:
# ...
You add the /notes
endpoint proper earlier than the /notes/noted_id
endpoint. That approach, 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 info within the schema
block, you present Marshmallow the data on methods to serialize a word in your API. For those who evaluate this Be aware
schema to the Be aware
mannequin in fashions.py
, then you definitely’ll discover that the names person_id
and content material
match. The identical goes for the fields’ sorts.
You may additionally discover that not all of the word mannequin fields are current within the part schema. That’s okay, since you’ll solely use this schema to publish new notes. For every word, id
and timestamp
will probably 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 modifications 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 modifications that you simply carry out along 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 along with your database construction, and also you turned your Flask REST API right into a note-keeping net utility.
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
Understanding methods to construct and use database relationships provides you a robust instrument to unravel many troublesome issues. There are different relationship in addition to the one-to-many instance from this tutorial. Different widespread ones are one-to-one, many-to-many, and many-to-one. All of them have a spot in your instrument belt, and SQLAlchemy will help you sort out all of them!
You’ve efficiently constructed a REST API to maintain monitor of notes for individuals who might go to you all year long. Your database comprises individuals just like the Tooth Fairy, the Easter Bunny, and Knecht Ruprecht. By including notes, you may hold monitor of your good deeds and hopefully obtain useful presents from them.
To overview your code, click on the hyperlink beneath:
Did you add a particular individual or word to your Flask REST API venture? Let the Actual Python group know within the feedback beneath.