8

在 Mongoengine 0.7.10 中,我仍然可以执行以下操作:

class User(db.Document):
    email = db.EmailField(unique=True, required=True)
    _password = db.StringField(max_length=255, required=True)

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, password):
        self._password = bcrypt.generate_password_hash(password)
user = User(email='1@1.com', password='12345')

但是,上面的代码在 0.8.0 中中断: ValidationError: ValidationError (User:None) (_password.Field is required: ['User'])

似乎 MongoEngine 在启动期间无法识别我的自定义密码设置器。我必须手动编写这些来修复它:

user = User(email='1@1.com')
user.password='12345'

这可能是由于以下更改(来自Mongonengine 0.8 升级说明):

Previously, if you had data the database that wasn’t defined in the Document definition, it would set it as an attribute on the document. This is no longer the case and the data is set only in the document._data dictionary:

我想知道这是有意的还是MongoEngine中的错误?在我的模型中编写自定义属性设置器的最佳实践是什么?

4

6 回答 6

5

试试这个代码:

class User(db.Document):
    email = db.EmailField(unique=True, required=True)
    _password = db.StringField(max_length=255, required=True, db_field='password')

    def __init__(self, *args, **kwargs):
            db.Document.__init__(self, *args, **kwargs)

            if 'password' in kwargs:
                self.password = kwargs['password']

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, password):
        self._password = bcrypt.generate_password_hash(password)
user = User(email='1@1.com', password='12345')

这个对我有用。

于 2014-08-12T07:10:11.213 回答
2

您应该使用mongoengine 文档中描述clean的 Document函数。

class User(db.Document):
    email = db.EmailField(unique=True, required=True)
    password = db.StringField(max_length=255, required=True)

    def clean(self):
        if not hashed(self.password):
            self.password = bcrypt.generate_password_hash(self.password)

    def hashed(self, password):
        return  # boolean check of whether the password is already hashed

user = User(email='1@1.com', password='12345')
user.save()

每次调用时user.save(),它现在都会检查您的密码是否类似于散列值,如果不是,则在更新数据库之前对其进行散列。

于 2019-04-22T17:09:44.010 回答
1

这不是一个错误 - 它清除了一些其他错误,并且是升级文档中提到的预期操作。但是,这对这种情况没有好处!

我认为创建密码哈希的自定义方法会更好,例如:set_password check_password 等...

过去有 PasswordField 实现,这是我将添加到 extras-mongoengine 的内容。

于 2013-06-03T12:36:42.400 回答
0

这不是一个优雅的解决方案,但我真的很喜欢将我的表单直接推送到模型中,并在模型级别而不是在一个或多个视图中使用安全密码散列。只需重命名password_password,运行 mongoengine 文档验证并设置self._password

class User(db.Document):
    """User model."""

    username = db.StringField(max_length=50, required=True, unique=True)
    _password = db.StringField(max_length=255, required=True)

    def __init__(self, *args, **kwargs):
        kwargs['_password'] = kwargs.pop('password')
        db.Document.__init__(self, *args, **kwargs)
        self.password = kwargs['_password']

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, password):
        self._password = bcrypt.generate_password_hash(password)
于 2018-07-08T10:56:20.587 回答
0

在我的示例中,我使用哈希值覆盖密码并将其存储为 BinaryField。

class Users(Document):
    name = db.StringField(required=True)
    password = db.BinaryField(required=True)

    def __init__(self, *args, **kwargs):
        if 'password' in kwargs:
            password = kwargs['password']
            if not isinstance(password, bytes): # if it creates from user input, not from DB's load
                kwargs['password'] = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
        Document.__init__(self, *args, **kwargs)
于 2020-07-13T18:48:00.357 回答
0

在最新版本的 MongoEngine 中,您将获得一个

FieldDoesNotExist: The fields "{'password'}" do not exist on the document "User"

当您尝试使用上述@property某些答案时。

为避免这种情况,'strict':False请在元字典中使用 a。

我希望读者知道我投入了大量时间来为您带来这些信息,仅此而已。

于 2020-07-27T06:40:46.893 回答