MongoEngine - 仅在创建文档或设置特定字段时调用函数?

MongoEngine - Call function only when document is being created or specific field being set?

我不确定让用户文档在创建时自动散列其密码的 best/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()

Buf 如果我更新它,它会对其密码进行双重哈希处理,我不希望这样。

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

有没有办法让我仅在创建或更改密码时对其密码进行哈希处理?

或者我应该将散列密码的责任委托给 View/Controller?

我不会给你代码示例,你可以使用 Document.update() 方法来更新仅已更改的字段。

如果你还想使用保存方法, 然后您可以按照以下几行创建逻辑。

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

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

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

Link 用于使用像 Dict 这样的可迭代对象进行更新。 Whosebug question for Mongoengine update using iterable

Link 讨论保存方法的弃用(维护者在下面评论说保存方法没有被弃用,所以相信 him/her 并在这个 link 上随意进行)

Link 用于 mongoengine 中的更新方法。 Mongoengine Atomic Update