The official document: marshmallow. Readthedocs. IO/en/latest /
Marshmallow is a lightweight data to format conversion module, also known as serialization (converting P data model objects to stored or transportable data types) and deserialization (converting transportable data types to data model objects).
-
Serializing
Serialization, which converts data model objects to stored or transportable data types, such as objects/ Object ->list/dict, dict/list-> String
-
Deseriazing
Deserializers convert stored or transportable data types to data model objects, such as List /dict->objects/object, string->dict/list
-
Validate data
In the deserialization phase, type validation or custom validation is performed against the content of the data to be converted.
Installation and basic configuration
Module is installed
pip install -U marshmallow-sqlalchemy
pip install -U flask-sqlalchemy -i https://pipy.douban.com/simple
pip install -U flask-marshmallow
Copy the code
Module initialization (without ma)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from datetime import datetime
app = False(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset= utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow
db.init_app(app)
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer,primary_key=True,comment="The primary key id")
username = db.Column(db.String(255), index=True, comment="Username")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(15), index=True, comment="Mobile phone number")
sex = db.Column(db.Boolean, default=True, comment="Gender")
email = db.Column(db.String(255), index=True, comment="Email")
created_time = db.Column(db.DateTime, default=datetime.now, comment="Creation time")
updated_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now, comment="Update Time")
def __repr__(self) :
return "<%s : %s>" %(self.__class__.name, self.username)
@app.route("/")
def index() :
return ""
if __name__ = "__main__":
with app.app_context():
db.drop_all()
db.create_all()
app.run(debug=True,port=6000)
Copy the code
Basic constructor
Marshmallow transforms data formats primarily through constructors. In marshmallow’s use, all constructors must inherit the Schema base class from one another or indirectly.
The transformation is based on schema serialization
from datetime import datetime
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofangapp? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
db.init_app(app)
ma = Marshmallow()
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer, primary_key=True, comment="The primary key ID")
username = db.Column(db.String(255), index=True, comment="Username")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(15), index=True, comment="Mobile phone number")
sex = db.Column(db.Boolean, default=True, comment="Gender")
email = db.Column(db.String(255), index=True, comment="Email")
created_time = db.Column(db.DateTime, default=datetime.now, comment="Creation time")
updated_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now, comment="Update Time")
def __repr__(self) :
return "<%s: %s>" % (self.__class__.__name__, self.username)
Marshmallow transforms data formats primarily through schema transformation classes.
All Schema transformation classes used by Marshmallow must inherit directly or indirectly from the Schema base class
class UserSchema(Schema) :
username = fields.String()
mobile = fields.String()
# sex = fields.Boolean()
email = fields.Email()
created_time = fields.DateTime()
@app.route("/")
def index() :
user = User(
username="xiaoming",
mobile="13312345677",
sex=True,
email="[email protected]",
created_time=datetime.now(),
updated_time=datetime.now()
)
Call marsh to convert the model to python basic data format [dictionary/list]
us = UserSchema() # Serialize multiple data, can use many=True
ret1 = us.dump(user) Format output into a dictionary
ret2 = us.dumps(user) Format output as a JSON string
print(">>>> us.dump(user) --> dictionary")
print(ret1)
print(">>>> us.dumps(user) --> JSON string")
print(ret2)
"" "run results: > > > > us. Dump (user) -- - > dictionary {' created_time ':' the 2021-03-02 T11:07:45. 520209 ', 'updated_time' : '2021-03-02T11:07:45.520221', 'username': 'xiaoming', 'email': '[email protected]', 'sex': True, 'mobile': '13312345677'} >>>> us.dumps(user) --> JSON string {" creATED_time ": "2021-03-02t11:07:45.520209 ", "updated_time": "2021-03-02T11:07:45.520221", "username": "xiaoming", "email": "[email protected]", "sex": true, "mobile": "13312345677"} "" "
print(type(ret1), type(ret2))
user1 = User(
username="Xiaoming1 no.",
mobile="13312345677",
sex=True,
email="[email protected]",
created_time=datetime.now(),
updated_time=datetime.now()
)
user2 = User(
username="Xiaoming2 no.",
mobile="13312345677",
sex=True,
email="[email protected]",
created_time=datetime.now(),
updated_time=datetime.now()
)
user_list = [user,user1,user2]
us = UserSchema()
data_list = us.dump(user_list,many=True)
print(data_list)
[{'mobile': '13312345677', 'created_time': '2021-03-02T11:12:50.128294', 'email': '[email protected]', 'username': 'xiaoming'}, {'mobile': '13312345677', 'created_time': '2021-03-02T11:12:50.129576', 'email': '[email protected]', 'username': 'xiaoming1 '}, {'mobile': '13312345677', 'creATED_time ': '2021-03-02T11:12:50.129642', 'email': '[email protected]', 'username': 'xiaoming2 '}] ""
return "Basic Usage: Model serialization"
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True,host="0.0.0.0",port=5999)
Copy the code
Schema reuses attribute data types
type | describe |
---|---|
fields.Dict (keys, type]] = None, values,…) |
Dictionary type, often used to receive JSON-type data |
fields.List (cls_or_instance, type], **kwargs) |
List type, often used to receive array data |
fields.Tuple (tuple_fields, *args, **kwargs) |
A tuple type |
fields.String (*, default, missing, data_key, …) |
String type |
fields.UUID (*, default, missing, data_key, …) |
The value is a character string in UUID format |
fields.Number (*, as_string, **kwargs) |
Numeric primitive type |
fields.Integer (*, strict, **kwargs) |
The integer |
fields.Decimal A. Pawnchess B. Chess C. Pawnchess D. Pawnchess |
numeric |
fields.Boolean (*, truthy, falsy, **kwargs) |
The Boolean |
fields.Float (*, allow_nan, as_string, **kwargs) |
Floating point type |
fields.DateTime (format, **kwargs) |
Date time type |
fields.Time (format, **kwargs) |
Time to type |
fields.Date (format, **kwargs) |
The date type |
fields.Url (*, relative, schemes, Set[STR]]] = None,…) |
Url The url is a string of characters |
fields.Email (*args, **kwargs) |
Mailbox string type |
fields.IP (*args[, exploded]) |
IP address The value is a string of characters |
fields.IPv4 (*args[, exploded]) |
IPv4 address The value is a character string |
fields.IPv6 (*args[, exploded]) |
IPv6 address The value is a string of characters |
fields.Method (serialize, deserialize, **kwargs) |
Field based on the return value of the Schema class method |
fields.Function (serialize Any], Callable [[Any,…). |
Return the value field based on the function |
fields.Nested (nested, type, str, Callable[[], …) |
Foreign key type |
Schema Common common attributes of a data type
The property name | describe |
---|---|
default | Set the default values for the fields in the serialization phase |
missing | Set the default values for the fields in the deserialization phase |
validate | The built-in data validator or built-in validation set that the deserialization phase calls |
required | Sets the required field for the current field |
allow_none | Whether to allow null None, “” |
load_only | Whether the current field is used in the deserialization phase, equivalent to the previous write_only |
dump_only | Whether the current field is used in the serialization phase, equivalent to the previous read_only |
error_messages | The dictionary type that can be used instead of the default field exception prompt in the format: Error_messages ={” Required “: User name is mandatory. } |
Nested use of constructors
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields
from datetime import datetime
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class Author(object) :
def __init__(self, name, email) :
self.name = name
self.email = email
self.created_time = datetime.now()
self.books = [] # 1 to many foreign keys
self.courses = [] # many-to-many foreign keys
class Book(object) :
def __init__(self, title, author) :
self.title = title
self.author = author # replace the foreign key relationship in MySQL
class Course(object) :
""" "Writing Course """
def __init__(self,name) :
self.name = name
self.students = []
class Book2Schema(Schema) :
title = fields.String()
class AuthorSchema(Schema) :
name = fields.String()
email = fields.String()
Two-way nesting, such as finding all books belonging to that author. Note: In the case of large data volumes, data return will be very slow
# books = fields.List(fields.Nested(lambda: BookSchema(exclude=["author"])))
books = fields.List(fields.Nested(lambda: Book2Schema()))
class BookSchema(Schema) :
title = fields.String()
# Use lambda anonymous functions so that the AuthorSchema object is only found when author is used, otherwise it may be called in sequence and the object may not be found
A foreign key object can be serialized to the format specified, and the format specified by the foreign key can perform any supported marshmallow operation
author = fields.Nested(lambda: AuthorSchema())
class CourseSchema(Schema) :
name = fields.Str() # equivalent to fields.string ()
students = fields.List(fields.Nested(lambda: Author3Schema(exclude=["courses")))class Author3Schema(Schema) :
name = fields.String()
email = fields.String()
# Method 1: Universal nesting
# courses = fields.List(fields.Nested(lambda: CourseSchema(exclude=["students"])))
# method 2: use its own constructor as the foreign key method, and specify the serialized field
# courses = fields.Nested(CourseSchema, only=("name",), many=True)
You can also do this without specifying a field
# courses = fields.Nested(CourseSchema(many=True))
Pluck: Replace the nested data with a single value and return the list data with only name as a member. The name is a foreign key model field and can be another field name. Name is just an example
courses = fields.Pluck(CourseSchema, "name", many=True)
@app.route("/index1")
def index1() :
Many-to-one nested serialization ""
author = Author(
name="Xiao Ming",
email="[email protected]",
)
book = Book(
title = "The Adventures of Xiao Ming",
author = author,
)
bs = BookSchema()
book_dict1 = bs.dump(book)
book_dict2 = bs.dumps(book)
print(book_dict1)
print(book_dict2)
return "Basic Use: Nested serialization"
@app.route("/index2")
def index2() :
""1 to many nested serialization ""
author = Author(
name="Xiao Ming",
email="[email protected]"
)
author.books = [
Book(
title="The Adventures of Xiao Ming part 1.",
author=author,
),Book(
title="The Adventures of Xiao Ming, Part 2.",
author=author,
),Book(
title="The Adventures of Xiao Ming, Part 3.",
author=author,
),Book(
title="The Adventures of Xiao Ming, Part 4.",
author=author,
),
]
aus = AuthorSchema()
ret1 = aus.dump(author)
ret2 = aus.dumps(author)
print(ret1)
print(ret2)
return "Basic Use: Nested serialization"
@app.route("/index3")
def index3() :
"" Many-to-many nested serialization ""
author1 = Author(
name="xiaoming",
email="[email protected]"
)
course1 = Course(name="Prose fiction")
author1.courses = [
course1,
Course(name="Romance novel"),
Course(name="Wuxia Novels"),
]
course1.students = [
author1,
Author(
name="xiaoli",
email="[email protected]"
)
]
aus = Author3Schema()
ret1 = aus.dump(author1)
print(ret1)
cs = CourseSchema()
ret2 = cs.dump(course1)
print(ret2)
return "Basic Use: Nested serialization"
if __name__ == '__main__':
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
Since the correlation
The presence of a primary foreign key in a table is self-association.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields
from datetime import datetime
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class Area(object) :
def __init__(self, id, name) :
self.id = id
self.name = name
self.sub = []
class AreaSchema(Schema) :
id = fields.Integer()
name = fields.String()
# Method 1: Universal nesting
# sub = fields.List(fields.Nested(lambda: AreaSchema(exclude=["sub"])))
# method 2: use its own constructor as the foreign key method, and specify the serialized field
# sub = fields.Nested("self", only=("id","name",), many=True)
You can also do this without specifying a field
# sub = fields.Nested(lambda: AreaSchema(many=True))
Pluck: Replace the nested data with a single value and return the list data with only name as a member. The name is a foreign key model field and can be another field name. Name is just an example
sub = fields.Pluck("self"."name", many=True.)@app.route("/")
def index() :
""" Self-nested serialization ""
area1 = Area( id=1, name="Guangdong province" )
area2 = Area( id=2, name="Guangzhou" )
area3 = Area( id=3, name="Baiyun District" )
area4 = Area( id=4, name="Liwan District" )
area5 = Area( id=5, name="Hebei Province" )
area6 = Area( id=6, name="Shijiazhuang" )
area7 = Area( id=7, name="Bridge East" )
area8 = Area( id=8, name="Bridgewest" )
area1.sub = [area2]
area2.sub = [area3,area4]
area5.sub = [area6]
area6.sub = [area7,area8]
ars = AreaSchema()
ret1 = ars.dump(area1)
ret2 = ars.dump(area2)
print(ret1)
print(ret2)
return "Basic Use: Self-nested serialization"
if __name__ == '__main__':
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
Schema based deserialization transformation
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields,validate
from datetime import datetime
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class UserSchema(Schema) :
name = fields.Str(validate=validate.Length(min=1))
email = fields.Email()
permission = fields.Str(validate=validate.OneOf(["read"."write"."admin"]))
age = fields.Int(validate=validate.Range(min=18.max=40))
@app.route("/")
def index() :
us = UserSchema()
user_data = {"email": "[email protected]"."permission":"admin"}
ret1 = us.load(user_data)
print(ret1)
return "Basic usage: Model sequencing and negation"
if __name__ == '__main__':
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields,validate
from datetime import datetime
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class UserSchema(Schema) :
name = fields.Str(required=True, validate=validate.Length(min=1))
email = fields.Email()
permission = fields.Str(validate=validate.OneOf(["read"."write"."admin"]))
age = fields.Int(validate=validate.Range(min=18.max=40))
@app.route("/")
def index() :
us = UserSchema()
user_data = {"email": "[email protected]"."permission":"admin"}
ret1 = us.load(user_data,partial=("name")),print(ret1)
return "Basic usage: Model sequencing and negation"
if __name__ == '__main__':
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
The Settings field is enabled only during the serialization or deserialization phase
class UserSchema(Schema) :
name = fields.Str()
# password is
password = fields.Str(load_only=True) # write only field "write-only"
created_time = fields.DateTime(dump_only=True) # equivalent to "read-only"
Copy the code
Code:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields,validate
from datetime import datetime
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class User(object) :
def __init__(self,name,email,age,password,permission) :
self.name=name
self.email=email
self.age=age
self.password=password
self.permission=permission
self.created_time = datetime.now()
class UserSchema(Schema) :
name = fields.Str(required=True, validate=validate.Length(min=1))
email = fields.Email()
age = fields.Int(validate=validate.Range(min=18.max=40))
password = fields.Str(required=True, load_only=True)
permission = fields.Str(validate=validate.OneOf(["read"."write"."admin"]))
created_time = fields.DateTime(dump_only=True)
@app.route("/")
def index() :
us = UserSchema()
user_data = {"email": "[email protected]"."permission":"admin"."password":"123456"}
ret1 = us.load(user_data,partial=("name")),print(ret1)
user = User(
name="xiaoming",
age=18,
**user_data,
)
ret2 = us.dump(user)
print(ret2)
return "Basic usage: Model sequencing and negation"
if __name__ == '__main__':
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
Hook methods for the deserialization phase
Marshmallow provides a total of four hook methods:
Pre_dump ([fn, pass_many]) registers methods to be called before the object is serialized, which is called before the object is serialized. Pre_load ([fn, pass_many]) registers the method to be called before deserializing the object, which is called before validating the data.
Post_dump ([fn, pass_many, pass_original]) registers the method to be called after the object has been serialized. It is called after the object has been serialized. Post_load ([fn, pass_many, pass_original]) the method to be called after registering the deserialized object, which is called after validating the data.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from werkzeug.security import generate_password_hash
from marshmallow import Schema,fields,validate,pre_load,pre_dump,post_dump,post_load
from datetime import datetime
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer, primary_key=True, comment="The primary key ID")
name = db.Column(db.String(255), index=True, comment="Username")
age = db.Column(db.Integer, comment="Age")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(20), comment="Mobile phone Number")
created_time = db.Column(db.DateTime, default=datetime.now, comment="Creation time")
def __repr__(self) :
return "<%s: %s>" % (self.__class__.__name__, self.name)
class UserSchema(Schema) :
name = fields.String(validate=validate.Length(min=1))
age = fields.Integer(required=True)
password = fields.Str(load_only=True) # write only field "write-only"
# created_time = fields.DateTime(dump_only=True) #
mobile = fields.String()
created_time = fields.DateTime(format='%Y-%m-%d %H:%M:%S')
@pre_load
def pre_load(self,data,**kwargs) :
""" """ """ """ """
# print(f"kwargs={kwargs}")
data["created_time"] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
Data must be returned
return data
@post_load
def post_load(self,data,**kwargs) :
""" "a post-serialized hook that executes after data validation.
# print(f"kwargs={kwargs}")
The password is encrypted before entering the database
data["password"] = generate_password_hash(data["password"])
Delete unnecessary fields such as verification code and confirm password before entering database
return User(**data) You can also convert dictionaries to model objects manually here
Note that no database is committed here, so we are just instantiating a model object, not adding a database
If you want to synchronize to the database after deserialization, the code is as follows:
# instance = User(**data)
# db.session.add(instance)
# db.session.commit()
# return instance
@pre_dump
def pre_dump(self,data,**kwargs) :
""" serialized front hook that executes before data conversion """ "
data.mobile = "130 ____0001"
return data
@post_dump
def post_dump(self,data,**kwargs) :
Serialized post-hook that executes after data conversion.
data["age"] = f"{data['age']}At the age of"
return data
@app.route("/")
def index() :
us = UserSchema()
instance = us.load({"name":"xiaomingf"."age":19."password":"123456"."mobile":"13000000001"})
data = us.dump(instance)
print(data)
return "Basic use: Hook method calls"
if __name__ == '__main__':
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
The deserialization phase validates the data
Data validation based on built-in validators
Built-in validator | describe |
---|---|
validate.Email (*, error) |
Email address verification |
validate.Equal (comparable, *, error) |
Determine whether the values are equal |
validate.Length (min, max, *, equal, error) |
Value length/size validation |
validate.OneOf (choices, labels, *, error) |
Option to verify |
validate.Range ([min, max]) |
Scope of validation |
validate.Regexp (regex, bytes, Pattern][, flags]) |
The regular verification |
validate.URL (*, relative, schemes, Set[STR]]] = None,…) |
Verify that it is a URL |
The built-in validator is mainly written in the field options, code:
from datetime import datetime
from flask import Flask
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields,validate,post_dump,post_load,pre_dump,pre_load
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofangapp? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
db.init_app(app)
ma = Marshmallow()
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer, primary_key=True, comment="The primary key ID")
name = db.Column(db.String(255), index=True, comment="Username")
email = db.String(db.String(255))
age = db.Column(db.Integer, comment="Age")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(20), comment="Mobile phone Number")
def __repr__(self) :
return "<%s: %s>" % (self.__class__.__name__, self.name)
class UserSchema(Schema) :
name = fields.String(validate=validate.Length(min=1))
age = fields.Integer(required=True,validate=validate.Range(min=16.max=100))
email = fields.String(validate=validate.Email())
password = fields.Str(load_only=True,validate=validate.Length(min=6.max=16)) # write only field "write-only"
mobile = fields.String(validate=validate.Regexp("^1[3-9]\d{9}$",error="The phone number format is not correct!"))
@app.route("/")
def index() :
user_data = {"email":"[email protected]"."name": "Xiao Ming"."age": 20."password":"123456"."mobile":"13312345678"} # error
us = UserSchema()
# deserialize
instance = us.load(user_data)
print(instance)
return "hello"
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0",port=5999)
Copy the code
Custom authentication methods
Parameters are passed through the context or constructor instance object
import random
from datetime import datetime
from flask import Flask
from flask_marshmallow import Marshmallow
from marshmallow import Schema,fields,validate,validates,validates_schema,ValidationError,post_load,pre_load
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofangapp? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
db.init_app(app)
ma = Marshmallow()
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer, primary_key=True, comment="The primary key ID")
name = db.Column(db.String(255), index=True, comment="Username")
email = db.String(db.String(255))
age = db.Column(db.Integer, comment="Age")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(20), comment="Mobile phone Number")
def __repr__(self) :
return "<%s: %s>" % (self.__class__.__name__, self.name)
class UserSchema(Schema) :
name = fields.String()
age = fields.Integer()
email = fields.String()
password = fields.Str() # your password
password2 = fields.String() Confirm password
mobile = fields.String(validate=validate.Regexp("^1[3-9]\d{9}$",error="The phone number format is not correct!"))
Validate against the value of a single specified field
@validates("mobile")
def validate_mobile(self,mobile) :
if(mobile == "13312345678") :raise ValidationError("Cell phone number has been registered!!")
return mobile
Validation for multiple fields
@validates_schema
def validate(self,data,**kwargs) :
if(data["password"] != data["password2") :Raise raises an exception when this verification fails. Can't be a return!!!!!!!!!!
raise ValidationError(field_name="password2",message="Passwords and confirmation passwords do not match!")
return data
@post_load
def post_load(self,data,**kwargs) :
Deserialize the hook method after validation
print("num=%s" % self.num)
print(self.context)
del data["password2"] Delete unnecessary fields
return User(**data)
@app.route("/")
def index() :
user_data = {"email":"[email protected]"."name": "Xiao Ming"."age": 20."password":"123456"."mobile":"13312345671"."password2": "123456"}
num = random.randint(1.100)
If you need to pass some data to the constructor in the future, you can instantiate the constructor by passing the context argument, and call it within the constructor by self.context
us = UserSchema(context={"num":num})
If part of the data needs to be passed into the constructor for future calls during development, it can be passed as properties of the constructor object
us.num = num
# deserialize
instance = us.load(user_data)
print(instance)
return "hello"
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0",port=5999)
Copy the code
Model constructor (ModelSchema)
Official documentation: github.com/marshmallow…
marshmallow-sqlalchemy.readthedocs.io/en/latest/
Note: Flask_marshmallow has removed the ModelSchema and TableSchema model constructor classes since version 0.12.0. Instead, SQLAlchemyAutoSchema and SQLAlchemySchema are recommended. The two are used similarly.
Create a model constructor based on SQLAlchemySchema
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer, primary_key=True, comment="The primary key ID")
name = db.Column(db.String(255), nullable=False, index=True, comment="Username")
email = db.Column(db.String(255))
age = db.Column(db.Integer, comment="Age")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(20), comment="Mobile phone Number")
def __repr__(self) :
return "<%s: %s>" % (self.__class__.__name__, self.name)
from marshmallow_sqlalchemy import SQLAlchemySchema,auto_field
from marshmallow import post_load,fields,validate
class UserSchema(SQLAlchemySchema) :
""" Model constructor """
[dump_only] [dump_only] [dump_only]
id = auto_field() The # auto_field is generally referred to as an inherited field, which automatically inherits field declarations and constraints of the same name into the corresponding model
name = auto_field()
email = auto_field()
age = auto_field()
password = auto_field(validate=validate.Length(min=6.max=16))
In addition to copying the information and data types of the corresponding fields in the model, we can also add a supplementary description
mobile = auto_field(required=True,validate=validate.Regexp("^1[3-9]\d{9}$"))
password2 = fields.String() If there are no declared fields in the model, fill them in as you did in the previous custom constructor
class Meta:
model = User Table = models.album.__table__
load_instance = True In the deserialization phase, True returns the model object directly, False returns the dictionary
include_relationships = True Output model object with foreign key
include_fk = True The serialization stage also returns the primary key, that is, the ID
@post_load
def post_load(self,instance,**kwargs) :
Hook executed after deserialization ""
db.session.add(instance)
db.session.commit()
return instance
@app.route("/")
def index() :
user_data = {"name": "Xiao Ming 1"."mobile": "13312345676"."age":18."email":"[email protected]"."password":"123456"."password2":"123456"}
us = UserSchema(session=db.session)
instance = us.load(user_data) # Note: If we are currently calling the model constructor, we must pass in the Session property, which is the session object of the current database
print(instance)
return "Basic Use: Validators for the deserialization phase"
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code
Create a model constructor based on SQLAlchemyAutoSchema
Usage:
classConstructor class name (SQLAlchemyAutoSchema) :
class Meta:Model = Name of the model class# table = models.Album.__table__
include_relationships = True Output model object with foreign key
include_fk = True Whether the sequenced phase also returns the primary key
load_instance = True In the deserialization phase, the model object is returned directly
sqla_session = db.session Database connection session object
# fields= ["id","name"
exclude = ["id"."name"] Exclude the list of fields
Copy the code
Code:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] ="Mysql: / / root: 123 @127.0.0.1:3306 / mofang? charset=utf8mb4"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy()
ma = Marshmallow()
db.init_app(app)
ma.init_app(app)
class User(db.Model) :
__tablename__ = "tb_user"
id = db.Column(db.Integer, primary_key=True, comment="The primary key ID")
name = db.Column(db.String(255), nullable=False, index=True, comment="Username")
email = db.Column(db.String(255))
age = db.Column(db.Integer, comment="Age")
password = db.Column(db.String(255), comment="Login password")
mobile = db.Column(db.String(20), comment="Mobile phone Number")
def __repr__(self) :
return "<%s: %s>" % (self.__class__.__name__, self.name)
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema,auto_field
from marshmallow import post_load,fields,validate
class UserSchema(SQLAlchemyAutoSchema) :
""" Model constructor """
password2 = fields.String() If there are no declared fields in the model, fill them in as you did in the previous custom constructor
class Meta:
model = User # model class name
Whitelist fields are declared in the serializer
# fields = [" id ", "name", "password2", "email", "age", "mobile"] # field list
# blacklist fields, which are not used in the serializer, are mutually exclusive with whitelists
exclude = ["age"] A list of fields that the constructor disables
load_instance = True In the deserialization phase, True returns the model object directly, False returns the dictionary
include_relationships = True Output model object with foreign key
include_fk = True The serialization stage also returns the primary key, that is, the ID
sqla_session = db.session Session object of the current database connection
@post_load
def post_load(self,instance,**kwargs) :
Hook executed after deserialization ""
db.session.add(instance)
db.session.commit()
return instance
@app.route("/")
def index() :
user_data = {"name": "Xiao Ming 1"."mobile": "13312345676"."email":"[email protected]"."password":"123456"."password2":"123456"}
us = UserSchema()
instance = us.load(user_data) # Note: If we are currently calling the model constructor, we must pass in the Session property, which is the session object of the current database
print(instance.id)
return "Basic Use: Validators for the deserialization phase"
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True,port=7000, host="0.0.0.0")
Copy the code