Hi,
Today I was trying to do user authentication with Django + MongoDB. I was 
constantly getting "Metadict object has no attribute pk" error. I searched 
for the fix but nothing helped. In the end, I read the implementation of 
login function and changed request.session[SESSION_KEY] = 
user._meta.pk.value_to_string(user) to request.session[SESSION_KEY] = 
user.id in django/contrib/auth/__init__.py and correspondingly changed 
return int(value) line no 947 to return value in 
django/db/models/fields/__init__.py as automated primary key for mongo db 
is a hexadecimal string. It worked this way.
Is there any other way to achieve same thing ? If not should I create a PR 
to fix this.

My settings.py
"""
Django settings for testApp project.

Generated by 'django-admin startproject' using Django 1.8.2.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ')s&uno-o3x)v^1-2bjt4o8*(sf^8zw42+#tvm(&km&fs+39x!5'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ["localhost"]


# Application definition

INSTALLED_APPS = (
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'meriApp',
)

MIDDLEWARE_CLASSES = (
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware',
  'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'testApp.urls'

TEMPLATES = [
  {
      'BACKEND': 'django.template.backends.django.DjangoTemplates',
      'DIRS': [],
      'APP_DIRS': True,
      'OPTIONS': {
          'context_processors': [
              'django.template.context_processors.debug',
              'django.template.context_processors.request',
              'django.contrib.auth.context_processors.auth',
              'django.contrib.messages.context_processors.messages',
          ],
      },
  },
]

WSGI_APPLICATION = 'testApp.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }


# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Kolkata'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'

LOGIN_URL = ''

LOGIN_REDIRECT_URL = '/meriApp/'

import mongoengine

DATABASES = {
  'default': {
      'ENGINE': 'django.db.backends.dummy',
  },
}

SESSION_ENGINE = 'mongoengine.django.sessions' # optional
# _MONGODB_USER = ''
# _MONGODB_PASSWD = ''
# _MONGODB_HOST = ''

_MONGODB_NAME = 'test'

# _MONGODB_DATABASE_HOST = \
#     'mongodb://%s:%s@%s/%s' \
#     % (_MONGODB_USER, _MONGODB_PASSWD, _MONGODB_HOST, _MONGODB_NAME)

# mongoengine.connect(_MONGODB_NAME, host=_MONGODB_DATABASE_HOST)
mongoengine.connect(_MONGODB_NAME)
AUTHENTICATION_BACKENDS = (
  'mongoengine.django.auth.MongoEngineBackend',
)

This is the view with which I am authenticating :
Enter code here...@csrf_protect
def login_view(request):
  if request.method == 'GET':
            return render_to_response('index.html', context_instance=
RequestContext(request))
      elif request.method == 'POST':
         try:
                   username = request.POST['email']
                       password = request.POST['password']
                    user = User.objects.get(username=username)
                     if user.check_password(password):
                              user.backend = 'mongoengine.django.auth.
MongoEngineBackend'
                            user = authenticate(username=username, password=
password)

                                login(request, user)
                           return HttpResponseRedirect('/meriApp/dashboard')
                      else:
                          return render_to_response('index.html', {'msg' : 
"Invalid 
Email/Password"}, context_instance=RequestContext(request))
          except DoesNotExist:
                   return render_to_response('index.html', {'msg' : "This 
user doesn't exist"}, context_instance=RequestContext(request))


Changes I did in django/contrib/auth/__init__.py :
try:
       request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
   except Exception:
       request.session[SESSION_KEY] = user.id


Changes I did in django/contrib/auth/__init__.py :
try: return int(value) except ValueError: try: # As mongoDB id is hex 
string, try to parse it. # If it raises exception than raise validation 
error # else return the hex string int(value, 16) return value except 
ValueError: raise exceptions.ValidationError( 
self.error_messages['invalid'], code='invalid', params={'value': value}, ) 
except (ValueError, TypeError): raise exceptions.ValidationError( 
self.error_messages['invalid'], code='invalid', params={'value': value}, )


Now if I don't perform these changes, I get metadict object has no 
attribute pk. Which i resolved by adding try except. Similarly to resolve 
validation error i added try except block there.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/4d64d632-2d5b-46d9-abe0-d5f35375bb1c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to