Sunday, March 19, 2023
HomePythonPython REST APIs With Flask, Connexion, and SQLAlchemy – Half 3 –...

Python REST APIs With Flask, Connexion, and SQLAlchemy – Half 3 – Actual Python


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:

PS> python -m venv venv
PS> .venvScriptsactivate
(venv) PS>
$ python -m venv venv
$ supply venv/bin/activate
(venv) $

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.

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:

Screenshot of Flask Hello World website with a people list

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.

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 as db.relationship. This object creates the connection that you just’re including to the Individual 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 the Individual class can be associated to. The Word 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 of Word right here.

  • Line 16: The backref="particular person" parameter creates what’s often called a backwards reference in Word objects. Every occasion of Word will include an attribute known as .particular person. The .particular person attribute references the mum or dad object {that a} explicit Word 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 with Word situations when adjustments are made to the mum or dad Individual occasion. For instance, when a Individual object is deleted, SQLAlchemy will create the SQL essential to delete the Individual object from the database. This parameter tells SQLAlchemy to additionally delete all of the Word situations related to it. You may learn extra about these choices within the SQLAlchemy documentation.

  • Line 18: The single_parent=True parameter is required if delete-orphan is a part of the earlier cascade parameter. This tells SQLAlchemy to not enable an orphaned Word occasion—that’s, a Word with no mum or dad Individual object—to exist, as a result of every Word has a single mum or dad.

  • Line 19: The order_by="desc(Word.timestamp)" parameter tells SQLAlchemy methods to type the Word situations related to a Individual object. When a Individual object is retrieved, by default the notes attribute checklist will include Word objects in an unknown order. The SQLAlchemy desc() 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 from db.Mannequin, precisely as you probably did earlier than when creating the Individual 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 the Word object.

  • Line 9 creates the .person_id attribute and defines it because the overseas key, relating the Word class to the Individual class utilizing the .particular person.id main key. This and the Individual.notes attribute are how SQLAlchemy is aware of what to do when interacting with Individual and Word objects.

  • Line 10 creates the .content material attribute, which comprises the precise textual content of the observe. The nullable=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 the Individual class, this attribute comprises the creation or replace time for any explicit Word 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.

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:

Screenshot of Flask frontend with people and notes

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:

Screenshot of API response with no notes

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:

Screenshot of API response of people with notes

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:

Screenshot of API response with people and notes

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.

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:

Screenshot of API response with one note

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.

RELATED ARTICLES

Most Popular

Recent Comments