首页 > 解决方案 > 在 ORM 模型类中编写非 ORM 模型代码是否可以接受?

问题描述

我正在使用 Python 构建一个非常小的 API,并且想知道在使用 Django 或 Flask 等框架(使用 Peewee 或 Pony 等 ORM)时,将 API 代码放在模型类中是否通常是可以接受的。让我解释一下我的意思...

为了说明我的意思,假设我有一个包含我所有模型的包,然后是另一个包含我的 API 代码的包,它在客户端 ping 我定义的特定路由时执行。如您所知,模型基本上仅用于将对象映射到数据库。尽管在某些情况下,出于某种原因,将一些 API 代码放在我定义的模型类之一中更有意义。

例如,我有一个将用户映射到数据库的用户模型。此外,在 API 代码中,我有一个登录用户的功能。这个函数基本上设置 cookie 来登录用户,所以将它放在 API 包中可能是有意义的。然而,我觉得如果我把这个函数变成一个方法并将它放在用户模型中,它在语义上更有意义,并且可能更容易理解。

class UserModel(Peewee or Pony or Django.model...):
    def login(self):
        """" Login code goes here. Set cookies, login the user, etc. """
        add_cookies(self.username)
        return jsonify({"logged_in": True})  # Flask example...

user = UserModel()
user.login()

然而,这样做的一个警告是,模型代码和 API 代码不再分离,现在相互强烈依赖。

因此,我想我的“客观”问题是关于每一个的可接受性。保持模型(数据库和 ORM 的东西)和 API 路由解耦比将它们组合在一起更好吗?做这些都有哪些优点和缺点?最常见和推荐的做法是什么?

提前致谢。

标签: pythondjangodjango-models

解决方案


TL;DR:在模型类中放置一个函数很好,但是如果你想要安全登录,你需要使用Flask-Login之类的东西在令牌中传递登录信息(我不确定 django 的等效扩展是什么)。

在类中放置一个函数很好,但是这对于登录来说不是很安全,所以我建议遵循一个实现安全登录扩展的教程。

例如,在我的一个项目中,登录页面的视图功能是:

@user.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm(next=request.args.get('next'))

    if form.validate_on_submit():
        u = User.find_by_identity(request.form.get('identity'))

        if u and u.authenticated(password=request.form.get('password')):
            if login_user(u, remember=True) and u.is_active():
                # Handle optionally redirecting to the next URL safely.
                next_url = request.form.get('next')
                if next_url:
                    return redirect(safe_next_url(next_url))
                return redirect(url_for('user.settings'))
        else:
            flash('Identity or password is incorrect.', 'error')

return render_template('user/login.html', form=form)

请注意,这u.authenticated是我的用户模型类中的一个函数,用于检查用户密码哈希是否正确:

    def authenticated(self, with_password=True, password=''):

    #Ensure a user is authenticated, and optionally check their password.
    if with_password:
        return check_password_hash(self.password, password)

    return True

推荐阅读