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.DecimalA. 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