django.contrib.auth 1.8 failed if user.pk not int

88 views
Skip to first unread message

Petr V. Bondarenko

unread,
Oct 9, 2015, 5:06:59 PM10/9/15
to django...@googlegroups.com
Hi,

when migrating code from version 1.7 to 1.8 I have a problem.
We do not use standard authentication through ModelBackend.
Authentication takes place on a different server protocol OAuth2.
For the User, using fake-model RemoteApiUser. In which the primary key is access_token.
Acces_token is written to the standard key django.contrib.auth.SESSION_KEY.
It is used in RemoteAuthenticationBackend as user_id in get_user() function.
This function generates a request to api-server  in which the token is returned by the User.
It is formed from the data object RemoteApiUser and return it.

In version 1.7. everything worked fine, but when migrating to 1.8 there is an error:

Traceback (most recent call last):
File "/usr/lib/python3.4/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/contrib/staticfiles/handlers.py", line 63, in __call__
return self.application(environ, start_response)                                                                      
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/core/handlers/wsgi.py", line 189, in __call__
response = self.get_response(request)
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/core/handlers/base.py", line 218, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/core/handlers/base.py", line 261, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/views/debug.py", line 97, in technical_500_response
html = reporter.get_traceback_html()
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/views/debug.py", line 383, in get_traceback_html
c = Context(self.get_traceback_data(), use_l10n=False)
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/views/debug.py", line 328, in get_traceback_data
frames = self.get_traceback_frames()              
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/views/debug.py", line 501, in get_traceback_frames
'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame),
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/views/debug.py", line 234, in get_traceback_frame_variables
cleansed[name] = self.cleanse_special_types(request, value)   
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/views/debug.py", line 189, in cleanse_special_types
if isinstance(value, HttpRequest):
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/utils/functional.py", line 225, in inner
self._setup()
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/utils/functional.py", line 365, in _setup
self._wrapped = self._setupfunc()
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/contrib/auth/middleware.py", line 22, in <lambda>
request.user = SimpleLazyObject(lambda: get_user(request))
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/contrib/auth/middleware.py", line 10, in get_user
request._cached_user = auth.get_user(request)
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/contrib/auth/__init__.py", line 167, in get_user
user_id = _get_user_session_key(request)
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/contrib/auth/__init__.py", line 59, in _get_user_session_key
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
File "/root/django/envs/wallet/lib/python3.4/site-packages/django/db/models/fields/__init__.py", line 969, in to_python
params={'value': value},
django.core.exceptions.ValidationError: ["Value 'TBQqn1Cpz4aO1UNeDgKzmgvtW1ygTS' must be int."]

For what purpose we have introduced such a restriction?
Can I get around it without rewriting the whole authentication mechanism?
As the authenctication server uses Django with oauth2_provider package.

P.S. Sorry for bad English.

Tim Graham

unread,
Oct 9, 2015, 9:25:50 PM10/9/15
to Django users
Here's the commit and ticket:

https://github.com/django/django/commit/0f7f5bc9
https://code.djangoproject.com/ticket/24161

I think you'll probably have to fix this in your app, but if a change in Django will help, let me know. Possibly your user model needs a CharField for its primary key.

Petr Bondarenko

unread,
Oct 12, 2015, 10:03:25 AM10/12/15
to Django users
Apparently my problem is caused by the transition to a new Model._meta API.
It was:
request.session[SESSION_KEY] = user.pk
It became:
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)

As user.pk we use access_token - CharField(max_length=64, primary_key=True)
An error occurs in a certain magic method to_python() in django.db.models.fields
Traceback is seen.

суббота, 10 октября 2015 г., 6:25:50 UTC+5 пользователь Tim Graham написал:

Tim Graham

unread,
Oct 12, 2015, 9:47:50 PM10/12/15
to Django users
In the traceback it appears that to_python() is being called for AutoField, not CharField. Are you sure the custom user model with the CharField pk is properly configured?

Petr Bondarenko

unread,
Oct 14, 2015, 1:52:33 PM10/14/15
to Django users
Yes.
CharField(primary_key=True)
When referring to RemoteApiUser._mata.pk returned this field.

вторник, 13 октября 2015 г., 6:47:50 UTC+5 пользователь Tim Graham написал:
Reply all
Reply to author
Forward
0 new messages