Search code examples
pythondjangodjango-formstinymcedjango-tinymce

django-tinymce widget not outputting correct error message


I just set up django-tinymce and made some changes to my form to do it. However, now my form is no longer outputting the correct error message.

My form:

TITLE_LENGTH_ERROR = "This title is too long, please make it 200 characters or less."
TITLE_EMPTY_ERROR = "You’ll have to add a title."
TEXT_EMPTY_ERROR = "Please enter some text."
NO_CATEGORY_ERROR = "Please select a category."
NO_CITY_ERROR = "Please select a city."


class ArticleForm(ModelForm):
    text = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
    class Meta:
        model = Article
        fields = ['title', 'text', 'categories', 'city']
        widgets = {'title': forms.TextInput(attrs={
            'placeholder': 'Enter a descriptive title'}),
            'categories': forms.CheckboxSelectMultiple(choices=Category.CATEGORY_CHOICES),
            'city': forms.RadioSelect(choices=City.CITY_CHOICES),
        }
        error_messages = {
            'title': {
                'max_length': TITLE_LENGTH_ERROR,
                'required': TITLE_EMPTY_ERROR,
            },
            'text': {
                'required': TEXT_EMPTY_ERROR,
            },
            'categories': {
                'required': NO_CATEGORY_ERROR,
            },
            'city': {
                'required': NO_CITY_ERROR,
            }
        }

The test:

from articles.models import Article, Category, City
from articles.forms import (
    ArticleForm,
    TITLE_LENGTH_ERROR,
    TITLE_EMPTY_ERROR,
    TEXT_EMPTY_ERROR,
    NO_CATEGORY_ERROR,
    NO_CITY_ERROR,
)


class ArticleFormTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(username='testuser')
        self.user.set_password('12345')
        self.user.save()
        self.client.login(username='testuser', password='12345')

    def test_form_validation_for_blank_inputs(self):
        form = ArticleForm(data={'title': '', 'text': '', 'categories': '', 'city': '', 'author': self.user})
        self.assertFalse(form.is_valid())

        self.assertEqual(
            form.errors['text'],
            [TEXT_EMPTY_ERROR]
        )

The traceback:

(venv) Robins-MacBook-Pro:togethere robin$ python manage.py test articles/
Creating test database for alias 'default'...
.F....................
======================================================================
FAIL: test_form_validation_for_blank_inputs (articles.tests.test_forms.ArticleFormTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/robin/work/2016-06-04_togethere/togethere/articles/tests/test_forms.py", line 36, in test_form_validation_for_blank_inputs
    [TEXT_EMPTY_ERROR]
AssertionError: ['This field is required.'] != ['Please enter some text.']

----------------------------------------------------------------------
Ran 22 tests in 4.171s

FAILED (failures=1)
Destroying test database for alias 'default'...

How do I make the form output the correct error message? Also, is it possible to declare the tinymce widget in the same way as the other widgets?


Solution

  • Ok so a little more explanation and a couple links that might help shed some light on this. In the official Django documentation (https://docs.djangoproject.com/en/1.10/ref/forms/fields/) there is an example of using form field validation with custom error messages. The error_messages must be defined within the field you want the error message associated with:

    text = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}), error_messages = { 'required': TEXT_EMPTY_ERROR})
    

    That being said, another Django documentation (https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/) shows creating custom error_messages in the Meta class for a Model form. Since the first line is working that's great, but I think if you wanted to create error messages in the manner you originally posted, you might try following the documentation. Under the "Overriding Default Fields section in the docs they show an example very similar to what you are doing so that should give you an idea of maybe what went wrong. I believe it's a combination of using these [] instead of these () to wrap your fields and then not overriding the field in the Meta class itself. Hopefully this gives a bit of insight into Django and testing though!!