When I try to do request.user.is_authenticated() I get a ValidationError: None is not a valid ObjectId
I'm trying to track down the problem but I do not what's causing it.I'm using MongoEngine (and MongoDB.)
I have the following in my settings.py:
AUTHENTICATION_BACKENDS = (
'mongoengine.django.auth.MongoEngineBackend',
'rs.claimutil.auth_backend.ClaimAuthBackend',
)
SESSION_ENGINE = 'mongoengine.django.sessions'
This is what I get:
Traceback: File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/handlers/base.py"
in get_response
111. response = callback(request, *callback_args, **callback_kwargs) File "/Users/bastiano/Documents/ttsf/rsrv/views.py" in reserve
11. if not request.user.is_authenticated(): File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/functional.py"
in inner
184. self._setup() File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/utils/functional.py"
in _setup
248. self._wrapped = self._setupfunc() File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/auth/middleware.py"
in
16. request.user = SimpleLazyObject(lambda: get_user(request)) File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/auth/middleware.py"
in get_user
8. request._cached_user = auth.get_user(request) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/auth/init.py"
in get_user
101. user = backend.get_user(user_id) or AnonymousUser() File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/django/auth.py"
in get_user
149. return User.objects.with_id(user_id) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in with_id
923. return self.filter(pk=object_id).first() File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in first
843. result = self[0] File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in getitem
1136. return self._document._from_son(self._cursor[key]) File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in _cursor
579. self._cursor_obj = self._collection.find(self._query, File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in _query
375. self._mongo_query = self._query_obj.to_query(self._document) File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in to_query
202. query = query.accept(QueryCompilerVisitor(document)) File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in accept
267. return visitor.visit_query(self) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in visit_query
159. return QuerySet._transform_query(self.document, **query.query) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/queryset.py"
in _transform_query
720. value = field.prepare_query_value(op, value) File
"/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/base.py"
in prepare_query_value
455. return self.to_mongo(value) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/base.py"
in to_mongo
451. self.error(unicode(e)) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mongoengine/base.py"
in error
203. raise ValidationError(message, errors=errors, field_name=field_name)
Exception Type: ValidationError at /rs/claim Exception Value: None is
not a valid ObjectId
Any ideas why this is happening? Is there an easier way to do user authentication in Django + MongoDB?
Views.py:
def claim(request):
if request.method == 'GET':
if not request.user.is_authenticated():
return shortcuts.redirect('rs/login')
all_b = dbutil.get_b(all=True)
return shortcuts.render_to_response('rs/index.html',
{'all_b':all_b},
context_instance=template.RequestContext(request))
elif request.method == 'POST':
The rest of the view is omitted for simplicity. I used ipdb to debug it and if not request.user.is_authenticated() is the problem. I tried using django.contrib.auth.decorators.login_required.decorator before, but it, too, failed.
Try to update your mongoengine to the latest version. In master, it is
def get_user(userid):
"""Returns a User object from an id (User.id). Django's equivalent takes
request, but taking an id instead leaves it up to the developer to store
the id in any way they want (session, signed cookie, etc.)
"""
# your installed mongoengine might not include following two lines
if not userid:
return AnonymousUser()
return MongoEngineBackend().get_user(userid) or AnonymousUser()
A userid w/ value of None causes the problem, according to the trackback.
What version of MongoEngine / Django are you using?
Have you enabled the django.contrib.auth.middleware.AuthenticationMiddleware? That should set a User instance or AnonymousUser to the request.
What does rs.claimutil.auth_backend.ClaimAuthBackend look like? And what does its get_user method return? Does it stop erroring if you just have one authentication backend?
In one of my views I had the following:
r_v.obj.backend = 'mongoengine.django.auth.MongoEngineBackend', which is why Django was ignoring the AUTHENTICATION_BACKENDS in settings.py, and was never using my custom authentication backend.
Related
I have never had any problems with it previously but when I clicked on it just then, it did not do anything. However my login works fine.
I'm running a custom signup class (so I can include google recaptcha) - this has already been tried and tested to work:
class AllauthSignupForm(forms.Form):
captcha = ReCaptchaField()
class Meta:
model = User
def signup(self, request, user):
""" Required, or else it throws deprecation warnings """
pass
I believe I may have altered the source code in django-allauth/blob/master/allauth/account/forms.py however I can't figure out what I changed. So I tried copy pasting the whole forms.py on github to my forms.py, and that returned this error:
Traceback:
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/zorgan/Desktop/vorsso/venvor/draft1/views.py" in boxes_view
116. return render(request, 'boxes.html', context)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/shortcuts.py" in render
30. content = loader.render_to_string(template_name, context, request, using=using)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/template/loader.py" in render_to_string
68. return template.render(context, request)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/template/base.py" in render
205. with context.bind_template(self):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py" in __enter__
59. return next(self.gen)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/django/template/context.py" in bind_template
263. updates.update(processor(self.request))
File "/Users/zorgan/Desktop/project/app/draft1/processors.py" in everywhere
12. allauth_signup = SignupForm(request.POST or None)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/allauth/account/forms.py" in __init__
364. super(SignupForm, self).__init__(*args, **kwargs)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/allauth/account/forms.py" in __init__
321. getattr(self, 'field_order', None) or default_field_order)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/allauth/utils.py" in set_form_field_order
252. for f in fields_order)
File "/Users/zorgan/Desktop/postr1/lib/python3.5/site-packages/allauth/utils.py" in <genexpr>
252. for f in fields_order)
Exception Type: KeyError at /news/
Exception Value: 'email2'
so I believe I may have tampered something with email2.
Any idea what the problem is?
EDIT
Ok when I remove captcha = ReCaptchaField() from my custom form the register works. Any idea why?
EDIT2
So it seems it works on chrome but not firefox. Some problem with google recaptcha not working on firefox.
While upgrading my project from django 1.5.1 to 1.6.5, I am facing this weird issue.
This is forbidden when an 'atomic' block is active.
I am aware of the Database Transaction changes for django 1.6 and made the setting changes accordingly. Works for most part, except when request.user object is accessed.
The code, for instance:
with transaction.atomic():
if hasattr(request, 'user') and getattr(request.user, 'id', None):
#blah
Here is the stacktrace:
Environment:
Request Method: GET
Request URL: <domain>/api/v1/browser_id/
Django Version: 1.6.5
Python Version: 2.7.3
<Installed Applications & Middlewares snipped for brevity>
Traceback:
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
112. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/transaction.py" in inner
371. return func(*args, **kwargs)
File "/home/kravindra/workspace/puppysite/puppy/kennel/views/etag_session.py" in browser_id
43. if hasattr(request, 'user') and getattr(request.user, 'id', None):
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/utils/functional.py" in inner
213. self._setup()
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/utils/functional.py" in _setup
298. self._wrapped = self._setupfunc()
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/auth/middleware.py" in <lambda>
18. request.user = SimpleLazyObject(lambda: get_user(request))
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/auth/middleware.py" in get_user
10. request._cached_user = auth.get_user(request)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/auth/__init__.py" in get_user
140. user_id = request.session[SESSION_KEY]
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py" in __getitem__
47. return self._session[key]
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py" in _get_session
173. self._session_cache = self.load()
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/cached_db.py" in load
52. self.create()
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/db.py" in create
40. self.save(must_create=True)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/cached_db.py" in save
62. super(SessionStore, self).save(must_create)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/db.py" in save
63. obj.save(force_insert=must_create, using=using)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/models/base.py" in save
545. force_update=force_update, update_fields=update_fields)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/models/base.py" in save_base
582. update_fields=update_fields, raw=raw, using=using)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/dispatch/dispatcher.py" in send
185. response = receiver(signal=self, sender=sender, **named)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/transaction.py" in inner
430. with self:
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/transaction.py" in __enter__
422. self.entering(self.using)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/transaction.py" in entering
483. enter_transaction_management(using=using)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/transaction.py" in enter_transaction_management
70. get_connection(using).enter_transaction_management(managed, forced)
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/backends/__init__.py" in enter_transaction_management
287. self.validate_no_atomic_block()
File "/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/db/backends/__init__.py" in validate_no_atomic_block
367. "This is forbidden when an 'atomic' block is active.")
Exception Type: TransactionManagementError at /api/v1/browser_id/
Exception Value: This is forbidden when an 'atomic' block is active.
Looking at the stacktrace,
/usr/local/virtualenvs/karthik-django165/local/lib/python2.7/site-packages/django/contrib/sessions/backends/cached_db.py in load
self.create() ...
▼ Local vars
Variable Value
e
DoesNotExist('Session matching query does not exist.',)
self
<django.contrib.sessions.backends.cached_db.SessionStore object at 0x7f61d401c6d0>
data
None
SessionStore raises an exception.
Using POSTGRES as the backend database.
The backend session store related settings are:
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' #which is persistent storage
ATOMIC_REQUESTS = True
Any pointers on how to fix this issue?
I found that there are a bunch of Questions on SO, and blogposts that address TransactionManagementError issue in general, but nothing to address this issue in particular
From the traceback it looks like one of your post_save signal receiver is still using one of the following deprecated transaction APIs:
transaction.Transaction
transaction.autocommit
transaction.commit_on_success
transaction.commit_manually
commit_on_success_unless_managed
Make sure to replace it with a transaction.atomic instance instead and your issue should go away.
Let me know if you have trouble finding the culprit receiver.
I am writing a custom authentication backend for migrating legacyusers to a new django site running on Django 1.3.1.
The reason i have to do it this way is two fold, one users are authenticated using non-unique email addresses. And I only have the md5 hash of their passwords.
I have a model called LegacyUser with fields called login_email and login_password (from an old database design)
Here are my authentication backend:
from django.contrib.auth.models import User, check_password
from webshipping.accounts.models import LegacyUser, UserProfile
from hashlib import md5
# see https://docs.djangoproject.com/en/1.3/topics/auth/
# and http://query7.com/django-authentication-backends
class AccountBackend:
supports_object_permissions = False
supports_anonymous_user = False
supports_inactive_user = False
def authenticate(self, username=None, password=None):
users = User.objects.filter(email=username)
for user in users:
pwd_valid = check_password(password, user.password)
if pwd_valid:
return user
try:
md5hash = md5(password).hexdigest()
lu = LegacyUser.objects.filter(login_email=username).filter(login_password=md5hash)
if lu == []:
return None
user = User.objects.create_user(lu[0].login_email, lu[0].login_email, password)
(first, sep, last) = lu[0].login_realname.rpartition(" ");
user.first_name = first
user.last_name = last
p = user.get_profile()
p.language = lu[0].login_language
p.save()
user.save()
return user
except LegacyUser.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
The problem is that when i call
LegacyUser.objects.filter(login_email=username).filter(login_password=md5hash)
it throws :
get() returned more than one LegacyUser -- it returned 3! Lookup parameters were {'login_email': u'test'}
Which is exactly what i want it to do, I want all instances of LegacyUser with this particular email and password combination so that i can combine them in to a single new django user.
If i refresh the page 2-3 times it gets through and creates the User object and all future logins work as expected.
My question is, what am i missing? Isn't filter supposed to return multiple objects?
Here are the complete traceback:
Environment:
Request Method: POST
Request URL: http://192.168.100.65/accounts/login/?next=/
Django Version: 1.3.1
Python Version: 2.7.2
Installed Applications:
['django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'webshipping.accounts',
'webshipping.addressbooks',
'webshipping.shipments',
'webshipping.transports']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
93. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
79. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/views.py" in login
35. if form.is_valid():
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in is_valid
121. return self.is_bound and not bool(self.errors)
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in _get_errors
112. self.full_clean()
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in full_clean
268. self._clean_form()
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in _clean_form
296. self.cleaned_data = self.clean()
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/forms.py" in clean
85. self.user_cache = authenticate(username=username, password=password)
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/__init__.py" in authenticate
55. user = backend.authenticate(**credentials)
File "/usr/local/lib/link/dev/webshipping/../webshipping/accounts/backends.py" in authenticate
20. lu = LegacyUser.objects.filter(login_email=username).filter(login_password=md5hash)
File "/usr/lib/python2.7/dist-packages/django/db/models/manager.py" in get
132. return self.get_query_set().get(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/db/models/query.py" in get
351. % (self.model._meta.object_name, num, kwargs))
Exception Type: MultipleObjectsReturned at /accounts/login/
Exception Value: get() returned more than one LegacyUser -- it returned 3! Lookup parameters were {'login_email': u'test'}
I have this code in my view:
def add_intern(request):
if request.method == 'POST':
form = InternApplicationForm(request.POST)
if form.is_valid():
form.save()
form = InternApplicationForm()
else:
form = InternApplicationForm()
return render_to_response('application.html', {'form': form},
context_instance = RequestContext(request))
The form is a ModelForm, and the underlying model contains an IntegerField.
When I post a form with empty value, the validation message is displayed just fine.
When I post the form with a non-integer value, I get this:
KeyError at /
'invalid'
It kind of surprises me that the code seems to crash on is_valid() call, which I assumed is safe (i.e. should return False if there is a problem and not just crash). How do I fix this?
Stacktrace
Django Version: 1.3
Python Version: 2.6.5
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/home/dan/www/ints/backend/views.py" in add_intern
14. if form.is_valid():
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/forms/forms.py" in is_valid
121. return self.is_bound and not bool(self.errors)
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/forms/forms.py" in _get_errors
112. self.full_clean()
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/forms/forms.py" in full_clean
267. self._clean_fields()
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/forms/forms.py" in _clean_fields
284. value = field.clean(value)
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/forms/fields.py" in clean
169. value = self.to_python(value)
File "/usr/local/lib/python2.6/dist-packages/Django-1.3-py2.6.egg/django/forms/fields.py" in to_python
248. raise ValidationError(self.error_messages['invalid'])
Exception Type: KeyError at /
Exception Value: 'invalid'
Okay, so I just nailed it down.
I followed this advice to set my custom error message for validation.
So I had this code:
def __init__(self, *args, **kwargs):
super(InternApplicationForm, self).__init__(*args, **kwargs)
for field in self.fields.values():
field.error_messages = {'required':'*'}
that set the same required field validation message for all fields.
When the error was different (invalid for non-integer), Django looked in the dictionary I supplied—and guess what, KeyError. Because there is no message for invalid there (and that's my fault).
So the fix is
field.error_messages = {'required': '*', 'invalid': "That's not a number, sir."}
(and possibly other error message keys)
I'm trying to validate a form containing a ModelChoiceField:
forms.py:
from django import forms
from modelchoicetest.models import SomeObject
class SomeObjectAddForm(forms.ModelForm):
class Meta:
model = SomeObject
models.py:
from django.db import models
class SomeChoice(models.Model):
name = models.CharField(max_length=16)
def __unicode__(self):
return self.name
class SomeObject(models.Model):
choice = models.ForeignKey(SomeChoice)
views.py:
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from forms import SomeObjectAddForm
def add(request):
if request.method == 'POST':
form = SomeObjectAddForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('modelchoicetest_add'))
else:
form = SomeObjectAddForm()
return render_to_response('modelchoicetest/index.html',
{'form': form},
context_instance=RequestContext(request))
When it is used in normal circumstances, everything goes just fine. But I'd like to protect the form from the invalid input. It's pretty obvious that I must get forms.ValidationError when I put invalid value in this field, isn't it? But if I try to submit a form with a value 'invalid' in 'somechoice' field, I get
ValueError: invalid literal for int() with base 10: 'invalid'
and not the expected forms.ValidationError. What should I do? I tried to place a def clean_somechoice(self) to check this field but that didn't work: ValueError happens before it comes to clean_somechoice()
Plus I don't think this is a good solution, there must be something more simple but I just missed that.
here's the full traceback:
Traceback:
File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response
101. response = callback(request, *callback_args, **callback_kwargs)
File "/home/andrey/public_html/example/modelchoicetest/views.py" in add
11. if form.is_valid():
File "/usr/local/lib/python2.6/dist-packages/django/forms/forms.py" in is_valid
120. return self.is_bound and not bool(self.errors)
File "/usr/local/lib/python2.6/dist-packages/django/forms/forms.py" in _get_errors
111. self.full_clean()
File "/usr/local/lib/python2.6/dist-packages/django/forms/forms.py" in full_clean
276. value = field.clean(value)
File "/usr/local/lib/python2.6/dist-packages/django/forms/fields.py" in clean
154. value = self.to_python(value)
File "/usr/local/lib/python2.6/dist-packages/django/forms/models.py" in to_python
911. value = self.queryset.get(**{key: value})
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in get
330. clone = self.filter(*args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in filter
536. return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in _filter_or_exclude
554. clone.query.add_q(Q(*args, **kwargs))
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py" in add_q
1109. can_reuse=used_aliases)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py" in add_filter
1048. connector)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/where.py" in add
66. value = obj.prepare(lookup_type, value)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/where.py" in prepare
267. return self.field.get_prep_lookup(lookup_type, value)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py" in get_prep_lookup
314. return self.get_prep_value(value)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py" in get_prep_value
496. return int(value)
Exception Type: ValueError at /
Exception Value: invalid literal for int() with base 10: 'invalid'
It looks to me like the exception is being raised by the clean method of the actual ModelChoiceField object. Because it's a foreign key, Django is expecting an int, which would be representative of the pk for SomeChoice. How exactly are you passing invalid into the form?
RESPONSE TO COMMENT
If you really feel you need to catch this, you can try overriding the default ModelChoiceField by creating a new field called choice and pass in the to_field_name kwarg into the ModelChoiceField __init__ method. This way Django won't be filtering on pk, and won't raise that exception.
Personally I wouldn't use this solution. There is no need to accommodate user who are hacking your form.
This is known Django bug:
http://code.djangoproject.com/ticket/11716
And while this bug is not fixed, you can only handle ValueError manually.