Wagtail not shows ValidationError correctly

3 min read 06-10-2024
Wagtail not shows ValidationError correctly


Wagtail's Silent Errors: Why ValidationErrors Go Missing and How to Fix Them

Wagtail, a powerful content management system built on Django, provides excellent tools for building beautiful websites. However, one common frustration users encounter is the lack of clear error messages during form validation. While Wagtail excels at handling user-facing input, its approach to displaying ValidationError instances can lead to confusion.

The Problem:

Imagine you're working on a Wagtail page that requires a specific format for a phone number field. You've set up validation in your Django model, but when a user enters an incorrect number, you see nothing but a generic "Please correct the errors below." This lack of clarity makes debugging and user feedback challenging.

Scenario and Code:

Let's say you have a ContactPage model in your Wagtail project:

from wagtail.core.models import Page
from wagtail.admin.edit_handlers import FieldPanel
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

class ContactPage(Page):
    phone_number = models.CharField(max_length=20, blank=True)

    def clean(self):
        cleaned_data = super().clean()
        phone_number = cleaned_data.get('phone_number')

        # Simple phone number validation (you might want to use a more robust library)
        if phone_number and not phone_number.isdigit():
            raise ValidationError(_("Please enter a valid phone number consisting only of digits."), code='invalid_phone')

        return cleaned_data

    panels = [
        FieldPanel('title'),
        FieldPanel('phone_number'),
    ]

In this example, if a user enters a phone number with letters, they'll get the generic error message, but not the specific "Please enter a valid phone number consisting only of digits" message.

Why is this happening?

The issue stems from how Wagtail handles form submissions. It relies on Django's built-in form handling, but it uses a custom form class (WagtailAdminPageForm) that overrides the default error handling behavior. This leads to:

  • Limited error display: By default, only the error codes ("invalid_phone" in our example) are presented to the user.
  • Missing custom messages: The specific error messages you define in ValidationError are not displayed on the page.

Solutions:

  1. Explicit Error Handling: You can customize the error rendering by overriding WagtailAdminPageForm and implementing your own error handling logic:

    from wagtail.admin.forms import WagtailAdminPageForm
    from django.forms.utils import ErrorList
    
    class ContactPageForm(WagtailAdminPageForm):
        def clean(self):
            cleaned_data = super().clean()
            phone_number = cleaned_data.get('phone_number')
    
            # ... your phone number validation ...
    
            return cleaned_data
    
        def get_errors(self):
            errors = super().get_errors()
            for field_name, field_errors in errors.items():
                if 'invalid_phone' in field_errors.codes:
                    error_message = _('Please enter a valid phone number consisting only of digits.')
                    errors[field_name] = ErrorList([error_message])
            return errors
    
  2. Wagtail 2.15+: Custom Error Messages: In recent Wagtail versions, the WagtailAdminPageForm was improved. You can now define custom error messages directly within the ValidationError:

    from wagtail.core.models import Page
    from wagtail.admin.edit_handlers import FieldPanel
    from django.core.exceptions import ValidationError
    from django.utils.translation import gettext_lazy as _
    
    class ContactPage(Page):
        # ... your model fields ...
    
        def clean(self):
            cleaned_data = super().clean()
            phone_number = cleaned_data.get('phone_number')
    
            if phone_number and not phone_number.isdigit():
                raise ValidationError(
                    _("Please enter a valid phone number consisting only of digits."),
                    code='invalid_phone'
                )
    
            return cleaned_data
    
        panels = [
            # ... your panels ...
        ]
    

Key Takeaways:

  • Wagtail's default error handling might not always display ValidationError messages as expected.
  • You can customize error handling by overriding the form class or utilizing the latest Wagtail features.
  • Be specific with your error messages to provide clear feedback to users and facilitate better debugging.

Additional Resources: