Question

I am using flask-mongoengine extension and I have a User class like this:

class User(db.Document, UserMixin):     
    email = db.StringField(max_length=120, required=True, unique=True)
    password_hash = db.StringField(max_length=80, required=True)   
    active = db.BooleanField()
    fb_id = db.StringField(max_length=120, required=False)

    def __init__(self, email, password, fb_id=None, active=True):           
        hashp = md5.md5(password).hexdigest()        
        self.email=email
        self.password_hash=hashp
        self.fb_id=fb_id
        self.active=active

But when I do a simple get: User.objects.get(email = email)

I get the error:

TypeError: __init__() got an unexpected keyword argument 'password_hash'

but I am setting the password_hash in my init though. Surprisingly, if I delete the whole __init__ and pass in everything by args, it works fine.

So I recon I am doing something wrong in the __init__, maybe something due the document super class? I am quite stuck on this, would appreciate your help.

Was it helpful?

Solution 2

This because when mongoengine get data from database then it create instance like User(**data) (there are also can be problem with id). So you haven't required password argument there:

{
    'id': ObjectId('51b349aef5ddaf191f2fb12f'), 
    u'email': u'test@test.test',
    u'password_hash': u'12345678123456781234567812345678'
}

Try next User class implementation:

class User(db.Document, UserMixin):
    email = db.StringField(max_length=120, required=True, unique=True)
    password_hash = db.StringField(max_length=80, required=True)
    active = db.BooleanField()
    fb_id = db.StringField(max_length=120, required=False)

    def __init__(self, password=None, **data):
        if password is not None:
            data['password_hash'] = md5.md5(password).hexdigest()
        super(User, self).__init__(**data)

I have next implementation for my project:

class User(db.Document, UserMixin):
    email = EmailField(unique=True, max_length=64, required=True)
    __password = StringField(db_field='password',
                             min_length=HASH_HEX_STRING_LENGTH,
                             max_length=HASH_HEX_STRING_LENGTH,
                             required=True)
    __password_salt = StringField(db_field='password_salt',
                                  min_length=DEFAULT_STRING_LENGTH,
                                  max_length=DEFAULT_STRING_LENGTH,
                                  required=True)

    def update_password(self, password):
        self.__password_salt = get_random_string(DEFAULT_STRING_LENGTH)
        self.__password = get_hash(password + self.__password_salt)
        return self

    def verify_password(self, password):
        return self.__password == get_hash(password + self.__password_salt)

OTHER TIPS

Try downgrading pymongo.

pip install pymongo==2.8

I was getting this error no matter what and the only way I fixed it was to downgrande pymongo from 3.0 to 2.8.

I know what happened on you code. you should use __str__ instead of using __init__ I have the same problem .now I have solved it . hope I can help you !

I don't know why but I was also keep getting the same error and only after downgrading pymongo from 3.0 to 2.8 it got fixed as David mentioned.

Pymongo should publish a fix for that, it is frustrating and made me waste couple of hours before realizing it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top