0
def decorator(cls):
    #code

    return cls

@decorator
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20),nullable=False)
    ssid = db.Column(db.String(20))    

    def __repr__(self):
        return f"User('{self.username}',{self.password})"

我想装饰一个类,这样我就可以在装饰器函数中访问 ssid 的值并向该类添加一个新属性。因为新属性需要 ssid 的值。

user = User(username='prince',ssid='9734ait')
db.session.add(user)
4

4 回答 4

0

在评论中,您说实际目标是在进出课堂时加密密码。Sqlalchemy 使用混合属性提供此功能。这是我的一个项目中的一个例子-

class User(Base):
    __tablename__ = "user"
    id = Column(Integer, primary_key=True)
    username = Column(String(255))
    hashed_password = Column("password", String(255))


    @hybrid_property
    def password(self):
        return self.hashed_password

    @password.setter  # type: ignore
    def password(self, value):
        rounds = 4
        if not isinstance(value, bytes):
            value = value.encode("utf-8")
        self.hashed_password = hashpw(value, gensalt(rounds)).decode("utf-8")

(所以在这种情况下,只有散列的密码存储在数据库中——为了检查密码,你对输入进行散列并将其与 user.password 进行比较)

于 2020-05-07T16:09:30.867 回答
0

在装饰器中定义一个属性是否足以满足您的用例?

例如:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///site.db"

db = SQLAlchemy(app)


class Encryptor:
    def __call__(self, cls):
        class Inner(cls):

            # define a getter function to return the password
            def password_getter(self):
                # return the calculated password here now you have access to username and ssid
                return f'{self.username} - {self.ssid}'.upper()

            setattr(cls, "password", property(fget=password_getter))

        return Inner


@Encryptor()
class User5(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), nullable=False)
    ssid = db.Column(db.String(20))

    def __repr__(self):
        return f"User('{self.username}',{self.ssid}; PASSWORD: {self.password})"


db.create_all()

user = User5(username="prince", ssid="3456ait")
db.session.add(user)
db.session.commit()

users = User5.query.all()
print(users)
于 2020-05-07T16:01:48.863 回答
0

如果你坚持使用装饰器:

class Decorator:
    def __call__(self, cls):
        class Inner(cls):
            cls.password = cls.ssid[::-1]
        return Inner

@Decorator()
class User:
    ssid = "fooo" 

    def __repr__(self):
        return f"User({self.ssid}, {self.password})"

u = User()
print(u)

输出:

User(fooo, ooof)
于 2020-05-05T08:19:59.283 回答
0

这似乎不是装饰器的合适用例……在我看来,您可以只使用继承并在__init__. 例如:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20),nullable=False)
    ssid = db.Column(db.String(20))    

    def __init__(self, *args, password=None, your_new_attribute=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.password = hash(ssid)
        self.your_new_attribute = your_new_attribute

    def __repr__(self):
        return f"User('{self.username}',{self.password})"
于 2020-05-05T07:24:08.777 回答