Opened 8 years ago
Closed 8 years ago
#27266 closed Bug (fixed)
assertFormError fails when trying to check a custom validation in an Admin form
Reported by: | Diego Andrés Sanabria Martín | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | dev |
Severity: | Normal | Keywords: | unittest, admin, modelform, adminform, test |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When using the assertFormError in a unittest to check a custome validation in an admin form the assertion fails because apparently the form in the admin view behaviours slightly different from a normal view.
Create a project 'what' with an app 'why' (I used 1.8.4 but it was tested with master branch):
django-admin startproject what
cd what
python manage.py startapp why
Use this files to check the bug:
what/settings.py
... INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'why', ) ...
why/models.py
from django.db import models # Create your models here. class WhyMe(models.Model): name = models.CharField(max_length=255)
why/admin.py
from django.contrib import admin from django.core.exceptions import ValidationError from django.forms import ModelForm from why.models import WhyMe class WhyMeAdminForm(ModelForm): def clean_name(self): name = self.cleaned_data['name'] if name.startswith('xxx'): raise ValidationError('don\'t use xxx!', code='invalid') return name @admin.register(WhyMe) class WhyMeAdmin(admin.ModelAdmin): form = WhyMeAdminForm
why/tests.py
from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.test import TestCase class WhyMeAdminTest(TestCase): def setUp(self): self.user = User.objects.create_superuser(username='chuck', email='chuck@internet.com', password='no') self.client.login(username='chuck', password='no') def test_custome_validation(self): url = reverse('admin:why_whyme_add') data = { 'name': 'xxxDiegueus9' } response = self.client.post(url, data, follow=True) self.assertEqual(response.status_code, 200) self.assertFormError(response, 'adminform', 'name', ['don\'t use xxx!'])
Finally run the tests and the result would be something like:
Creating test database for alias 'default'... E ====================================================================== ERROR: test_custome_validation (why.tests.WhyMeAdminTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/diegueus9/.virtualenvs/django1.8/what/why/tests.py", line 18, in test_custome_validation self.assertFormError(response, 'adminform', 'name', ['don\'t use xxx!']) File "/Users/diegueus9/.virtualenvs/django1.8/lib/python2.7/site-packages/Django-1.11.dev20160923192832-py2.7.egg/django/test/testcases.py", line 428, in assertFormError if field in context[form].errors: AttributeError: 'AdminForm' object has no attribute 'errors' ---------------------------------------------------------------------- Ran 1 test in 0.771s FAILED (errors=1) Destroying test database for alias 'default'...
In the attached file I show that the validation works fine in the admin.
I did a little of debug using ipdb and noticed that the errors are in 'AdminForm.form.errors', perhaps it should be added a property to the AdminForm?
This also fails using django 1.8.x, 1.9.x, 1.10.x
Attachments (1)
Change History (4)
by , 8 years ago
Attachment: | Screen Shot 2016-09-23 at 17.22.19.png added |
---|
comment:1 by , 8 years ago
Has patch: | set |
---|---|
Triage Stage: | Unreviewed → Accepted |
I'd rather not have those form and formset wrappers in the first place, but as long as we have them, it seems like a sensible idea. Can you review my PR?
comment:2 by , 8 years ago
Tim, it looks good to me, I just wrote a comment:
" just wonder if self.formset.non_form_errors == self.form.non_form_errors."
Custom validation in admin