python - 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()
有没有办法让我仅在创建或更改密码时散列其密码?
或者也许我应该将散列密码的责任委托给视图/控制器?
解决方案
我没有给你代码示例,你可以使用 Document.update() 方法来更新只有改变的字段。
如果您仍然想使用 save 方法,那么您可以按照以下几行创建一个逻辑。
- 检查用户是否更改了密码(通过比较现有存储的哈希和新的哈希(如果有))
- 如果新的哈希值不同,则用户已更改密码,在这种情况下,您可以推送 Document.update 方法。
- 如果没有,请不要在该字段上调用更新。
或者,Mongoengine 中的 update 接受一个可迭代对象,因此您可以简单地创建一个列表或字典对象,然后轻松地选择从中删除密码哈希字段。
至于谁应该执行这个,即视图/控制器,这是一个设计决定,但我宁愿将表示(GUI /前端)与逻辑分开,所以我会将它委托给控制器,甚至更多地委托给负责的对象处理所有与数据库/网络相关的任务,这样它将被隔离且易于修改。并且不会使视图对象进程/线程复杂化或减慢
使用像 Dict 这样的可迭代的更新链接。 使用可迭代的 Mongoengine 更新的 stackoverflow 问题
讨论保存方法弃用的链接(维护者在下面评论说保存方法未被弃用,所以相信他/她并在此链接上随意继续) Mongoengine 保存方法已弃用?
mongoengine 中更新方法的链接。 Mongoengine 原子更新