Thursday, February 23, 2017

Re: Issue with mongo in Django

Hi Ashish, I know it's been long since you worked on this problem. I am not able to get past this error despite trying these solution. Is there a permanent sort of fix for this problem? could you please help me out. Thanks!

On Wednesday, June 24, 2015 at 3:43:45 AM UTC+5:30, Ashish Khatkar wrote:
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

For the full list of settings and their values, see
"""

# 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

# 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

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


# Internationalization

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Kolkata'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)

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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/1252fe2e-193d-4ca9-9366-9aecf63da8ad%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment