如何处理 Marshmallow 模式中的 Flask_SQLAlchemy 模型方法?

How to handle Flask_SQLAlchemy models methods in Marshmallow schemas?

我有几个Flask_SQLAlchemy数据模型及其方法如下:

class User(db.Model):

    __table_args__ = {'extend_existing': True}
    id = db.Column('id',db.Integer , primary_key=True)
    username = db.Column('username', db.String(), unique=False , index=True)
    password = db.Column('password' , db.String())
    email = db.Column('email',db.String(),unique=True , index=True)
    role = db.Column('role', db.Integer(), default=0)
    account_state = db.Column('account_state', db.Integer(), default=1)
    karma = db.relationship('Karma', backref='user', lazy='dynamic', cascade="all, delete-orphan")
    registered_on = db.Column('registered_on' , db.DateTime(timezone=True), server_default=func.now())

    followed = db.relationship('Follow', 
        foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), 
        lazy='dynamic', cascade='all, delete-orphan')
    followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], 
        backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan')

    def to_dict(self):
        data = {
            'id': self.id,
            'username': self.username,
            'is_admin': self.is_admin(),
            'followers_count': self.followers_count(),
            'followed_count': self.followed_count(),
            'has_karma': self.has_karma(),
            'karma_count': self.karma_count(),
            'registered_on': self.registered_on,
        }
        return data

    def is_admin(self):
        if self.role == 1:
            return True
        return False

    def load_karma(self):
        karma = self.karma.filter_by(user_id=self.id).first()
        return karma

    def has_karma(self):
        karma = self.load_karma()
        if not karma:
            return False
        if karma:
            return True
        return False

    def karma_count(self):
        karma = self.load_karma()
        if karma:
            return karma.number
        return 0

    def followers_count(self):
        return self.followers.count()

    def followed_count(self):
        return self.followed.count()

class Karma(db.Model):
    __table_args__ = {'extend_existing': True}
    id = db.Column(db.Integer, primary_key=True)
    number = db.Column(db.Integer)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    last_karma_date = db.Column(db.DateTime, default=datetime.utcnow)

class Follow(db.Model):
    __tablename__ = 'follows'
    __table_args__ = {'extend_existing': True}
    follower_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    followed_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    state = db.Column(db.Integer, default=0)
    date_followed = db.Column(db.DateTime, default=datetime.utcnow)

如您在用户 class 中所见,我有一些方法,其中之一是 to_dict(),我将其用于 return JSON 数据我的 API 端点,但现在我切换到 Marshmallow 以自动序列化我的模型,我无法理解如何序列化我的用户模型的数据,例如 returns,如 has_karma () 和 karma_count()。我去过官方文档和许多关于 Whosebug 的在线文章和问题,但还没有。到目前为止,这是我的用户模式:

from marshmallow import Schema, fields, ValidationError

class UserSchema(Schema):
    id = fields.Int(dump_only=True)
    username = fields.Str()
    fullname = fields.Str()
    registered_on = fields.DateTime(dump_only=True)

如何像 to_dict() 那样序列化我的方法的 returned 数据?

您必须将方法更改为属性。您可以使用装饰器 @property.

轻松完成此操作

一个最小的工作示例


from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from marshmallow import Schema, fields

app = Flask(__name__)
db = SQLAlchemy(app)


class User(db.Model):    
    id = db.Column('id', db.Integer, primary_key=True)
    username = db.Column('username', db.String(), unique=False, index=True)

    @property
    def has_karma(self):
        return True


class UserSchema(Schema):
    id = fields.Int(dump_only=True)
    username = fields.Str()
    has_karma = fields.Boolean()


@app.route("/")
def home():    
    return UserSchema().dump(User(id=1, username='hi'))


if __name__ == '__main__':
    app.run()

输出(如果您 运行 应用并访问 http://127.0.0.1:5000/):

has_karma   true
id          1
username    "hi"