首页 > 解决方案 > MongoEngine - 仅在创建文档或设置特定字段时调用函数?

问题描述

我不确定让用户文档在创建时自动散列其密码的最佳/pythonic 方式是什么。

考虑以下 mongoengine 模型:

class User(Document):
    email = EmailField(required=True, primary_key=True)
    name = StringField(required=True)
    pswd = StringField(required=True)

    def check_pswd(self, password):
        return verify_password(password, self.pswd)

    def hash_pswd(self, password):
        return hash_password(password):

    def save(self, *args, **kwargs):
        self.pswd = self.hash_pswd(self.pswd)
        super().save(*args, **kwargs)

当我创建用户时,它工作正常:

user = User()
user.email = 'user@email.com'
user.pswd = 'password'
user.name = 'User'
user.save()

如果我更新它,它会双重哈希它的密码,我不想要那个。

#User wants to change his name
user = User.objects(email='user@email.com')
user.name = 'User 2'
user.save()

有没有办法让我仅在创建或更改密码时散列其密码?

或者也许我应该将散列密码的责任委托给视图/控制器?

标签: pythonmongoengineflask-mongoengine

解决方案


我没有给你代码示例,你可以使用 Document.update() 方法来更新只有改变的字段。

如果您仍然想使用 save 方法,那么您可以按照以下几行创建一个逻辑。

  1. 检查用户是否更改了密码(通过比较现有存储的哈希和新的哈希(如果有))
  2. 如果新的哈希值不同,则用户已更改密码,在这种情况下,您可以推送 Document.update 方法。
  3. 如果没有,请不要在该字段上调用更新。

或者,Mongoengine 中的 update 接受一个可迭代对象,因此您可以简单地创建一个列表或字典对象,然后轻松地选择从中删除密码哈希字段。

至于谁应该执行这个,即视图/控制器,这是一个设计决定,但我宁愿将表示(GUI /前端)与逻辑分开,所以我会将它委托给控制器,甚至更多地委托给负责的对象处理所有与数据库/网络相关的任务,这样它将被隔离且易于修改。并且不会使视图对象进程/线程复杂化或减慢

使用像 Dict 这样的可迭代的更新链接。 使用可迭代的 Mongoengine 更新的 stackoverflow 问题

讨论保存方法弃用的链接(维护者在下面评论说保存方法未被弃用,所以相信他/她并在此链接上随意继续) Mongoengine 保存方法已弃用?

mongoengine 中更新方法的链接。 Mongoengine 原子更新


推荐阅读