0
votes

I have managed to connect django 2.0 with mongoengine. Every other thing is working fine apart from the authentication part. in my settings.py I have the following:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    #For Mongo Authentication
    'mongoengine.django.mongo_auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',

]
AUTH_USER_MODEL = 'mongo_auth.MongoUser'
MONGOENGINE_USER_DOCUMENT = 'mongoengine.django.auth.User'

and am getting the following error

core/checks/registry.py", line 73, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/home/user/virtualenvs/project/lib/python3.5/site-packages/django/contrib/auth/checks.py", line 74, in check_user_model
    if isinstance(cls().is_anonymous, MethodType):
AttributeError: 'MongoUser' object has no attribute 'is_anonymous'

From the error above I see that the problem is at the declaration of the AUTH_MODEL_USER . I have not created any Custom User Model as I want to be able to user the django.uath User model....I need idea on how I can set it up and be able to create users and have them login. how should I go about??

1

1 Answers

1
votes

I understand the attraction of using Django being the ORM and the Authentication already pre-built for you. I have used Django before but never with Mongoengine. I understand that Mongoengine support for Django isn't yet complete. I have recently completed a project in Flask with Mongoengine, and I recommend making your own user model. Below is an example of what I do using bcrypt to encrypt the password automatically pre-save. You might need to install the blinker library for signal support.

from mongoengine import Document, StringField
from mongoengine import signals // blinker library may need to be installed 
from bcrypt import hashpw, gensalt


class User(Document):
    first_name = StringField(required=True, max_length=50)
    last_name = StringField(required=True, max_length=50)
    username = StringField(unique=True, required=True, max_length=50)
    password = StringField(required=True, min_length=6)

    def to_json(self):
        return {
            "_id": str(self.pk),
            "first_name": self.first_name,
            "last_name": self.last_name,
            "username": self.username,
            "password": self.password
        }

    @classmethod
    def pre_save(cls, sender, document, **kwargs):
        hashed = hashpw(document.password.encode('utf8'), gensalt())
        document.password = hashed.decode('utf8')

signals.pre_save.connect(User.pre_save, sender=User)

I understand you may be forfeiting one of the benefits of Django, but having this level of control of your user model makes things easier in my opinion, versus learning the Django way of doing things. The to_json() method is of course optional, it just overrides Mongoengine's to_json() and make it more human readable.

To authenticate the password:

bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8'))