Now, we will create the models that we can use to represent and persist the message categories, messages, and their relationships. Open the api/models.py
file and replace its contents with the following code. The lines that declare fields related to other models are highlighted in the code listing. In case you created a new virtual environment, create a new models.py
file within the api
folder. The code file for the sample is included in the restful_python_chapter_06_01
folder:
from marshmallow import Schema, fields, pre_load
from marshmallow import validate
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
db = SQLAlchemy()
ma = Marshmallow()
class AddUpdateDelete():
def add(self, resource):
db.session.add(resource)
return db.session.commit()
def update(self):
return db.session.commit()
def delete(self, resource):
db.session.delete(resource)
return db.session.commit()
class Message(db.Model, AddUpdateDelete):
id = db.Column(db.Integer, primary_key=True)
message = db.Column(db.String(250), unique=True, nullable=False)
duration = db.Column(db.Integer, nullable=False)
creation_date = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('category.id', ondelete='CASCADE'), nullable=False)
category = db.relationship('Category', backref=db.backref('messages', lazy='dynamic' , order_by='Message.message'))
printed_times = db.Column(db.Integer, nullable=False, server_default='0')
printed_once = db.Column(db.Boolean, nullable=False, server_default='false')
def __init__(self, message, duration, category):
self.message = message
self.duration = duration
self.category = category
class Category(db.Model, AddUpdateDelete):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(150), unique=True, nullable=False)
def __init__(self, name):
self.name = name
First, the code creates an instance of the flask_sqlalchemy.SQLAlchemy
class named db
. This instance will allow us to control the SQLAlchemy integration for our Flask application. In addition, the instance will provide access to all the SQLAlchemy functions and classes.
Then, the code creates an instance of the flask_marshmallow.Marshmallow
class named ma
. It is very important to create the flask_sqlalchemy.SQLAlchemy
instance before the Marshmallow
instance, and therefore, order matters in this case. Marshmallow is a wrapper class that integrates Mashmallow with a Flask application. The instance named ma
will provide access to the Schema
class, the fields defined in marshmallow.fields
, and the Flask-specific fields declared in flask_marshmallow.fields
. We will use them later when we declare the schemas related to our models.
The code creates the AddUpdateDelete
class that declares the following three methods to add, update, and delete a resource through SQLAlchemy sessions:
add
: This method receives the object to be added in the resource
argument and calls the db.session.add
method with the received resource as an argument to create the object in the underlying database. Finally, the code commits the session.update
: This method just commits the session to persist the changes made to the objects in the underlying database.delete
: This method receives the object to be deleted in the resource
argument and calls the db.session.delete
method with the received resource as an argument to remove the object in the underlying database. Finally, the code commits the session.The code declares the following two models, specifically, two classes, as a subclass of both the db.Model
, and the AddUpdateDelete
classes:
Message
Category
We specified the field types, maximum lengths, and defaults for many attributes. The attributes that represent fields without any relationship are instances of the db.Column
class. Both models declare an id
attribute and specify the True
value for the primary_key
argument to indicate it is the primary key. SQLAlchemy will use the data to generate the necessary tables in the PostgreSQL database.
The Message
model declares the category
field with the following line:
category = db.relationship('Category', backref=db.backref('messages', lazy='dynamic', order_by='Message.message'))
The previous line uses the db.relationship function to provide a many-to-one relationship to the Category model. The backref argument specifies a call to the db.backref function with 'messages' as the first value that indicates the name to use for the relation from the related Category object back to a Message object. The order_by argument specifies 'Message.message' because we want the messages for each category to be sorted by the value of the message field in ascending order.
Both models declare a constructor, that is, the __init__
method. This constructor for the Message
model receives many arguments and uses them to initialize the attributes with the same names: message
, duration
, and category
. The constructor for the Category
model receives a name
argument and uses it to initialize the attribute with the same name.
3.21.46.78