Friday, March 24, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Python

Python REST APIs With Flask, Connexion, and SQLAlchemy – Part 3 – Real Python

learningcode_x1mckf by learningcode_x1mckf
November 21, 2022
in Python
0
Python REST APIs With Flask, Connexion, and SQLAlchemy – Part 3 – Real Python
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


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:

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 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:

Screenshot of Flask Hello World website with a people list

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 as db.relationship. This object creates the connection that you simply’re including to the Particular 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 the Particular person class will probably be associated to. The Be 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 of Be aware right here.

  • Line 16: The backref="individual" parameter creates what’s generally known as a backwards reference in Be aware objects. Every occasion of Be aware will include an attribute known as .individual. The .individual attribute references the mum or dad object {that a} explicit Be 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 with Be aware cases when modifications are made to the mum or dad Particular person occasion. For instance, when a Particular person object is deleted, SQLAlchemy will create the SQL essential to delete the Particular person object from the database. This parameter tells SQLAlchemy to additionally delete all of the Be 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 if delete-orphan is a part of the earlier cascade parameter. This tells SQLAlchemy to not enable an orphaned Be aware occasion—that’s, a Be aware with out a mum or dad Particular person object—to exist, as a result of every Be aware has a single mum or dad.

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

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

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

Screenshot of Flask frontend with people and notes

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:

Screenshot of API response with no notes

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:

Screenshot of API response of people with notes

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:

Screenshot of API response with people and notes

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:

Screenshot of API response with one note

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.





Source link

You might also like

When Should You Use .__repr__() vs .__str__() in Python? – Real Python

Summing Values the Pythonic Way With sum() – Real Python

Executing Python Scripts With a Shebang – Real Python

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

When Should You Use .__repr__() vs .__str__() in Python? – Real Python

by learningcode_x1mckf
March 22, 2023
0
When Should You Use .__repr__() vs .__str__() in Python? – Real Python

One of the vital frequent duties that a pc program performs is to show information. This system typically shows this info to this system’s person. Nonetheless, a program...

Read more

Summing Values the Pythonic Way With sum() – Real Python

by learningcode_x1mckf
March 21, 2023
0
Summing Values the Pythonic Way With sum() – Real Python

Python’s built-in perform sum() is an environment friendly and Pythonic strategy to sum an inventory of numeric values. Including a number of numbers collectively is a typical intermediate...

Read more

Executing Python Scripts With a Shebang – Real Python

by learningcode_x1mckf
March 20, 2023
0
Executing Python Scripts With a Shebang – Real Python

While you learn another person’s Python code, you continuously see a mysterious line, which all the time seems on the high of the file, beginning with the distinctive...

Read more

Coding With namedtuple & Python’s Dynamic Superpowers – The Real Python Podcast

by learningcode_x1mckf
March 17, 2023
0
Coding With namedtuple & Python’s Dynamic Superpowers – The Real Python Podcast

Mar 17, 2023 53m Have you ever explored Python’s collections module? Inside it, you’ll discover a highly effective manufacturing facility operate known as namedtuple(), which gives a number...

Read more

How to Evaluate the Quality of Python Packages – Real Python

by learningcode_x1mckf
March 15, 2023
0
How to Evaluate the Quality of Python Packages – Real Python

Putting in packages with Python is only one pip set up command away. That’s one of many many nice qualities that the Python ecosystem has to supply. Nonetheless,...

Read more
Next Post
Saudi Arabia expresses solidarity with Indonesia after West Java earthquake

Saudi Arabia expresses solidarity with Indonesia after West Java earthquake

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

East Java chiefly prioritizing people’s welfare improvement in 2023

East Java chiefly prioritizing people’s welfare improvement in 2023

January 8, 2023
It Is Time To Shun C, C++ Languages For New Projects: Microsoft Azure CTO – Amazon, Android, Azure, Chrome, Delhi, Google, Intel, Languages, Microsoft, Projects, Python, Shun, Windows – It is time to shun C, C++ languages for new projects: Microsoft Azure CTO

It Is Time To Shun C, C++ Languages For New Projects: Microsoft Azure CTO – Amazon, Android, Azure, Chrome, Delhi, Google, Intel, Languages, Microsoft, Projects, Python, Shun, Windows – It is time to shun C, C++ languages for new projects: Microsoft Azure CTO

October 20, 2022
Everyday Project Packaging With pyproject.toml – Real Python

Everyday Project Packaging With pyproject.toml – Real Python

November 22, 2022

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • Java Developer Survey Reveals Increased Need for Java … – PR Newswire
  • What You Should Definitely Pay Attention to When Hiring Java Developers – Modern Diplomacy
  • Java Web Frameworks Software Market Research Report 2023 … – Los Alamos Monitor

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?