Hello, esteemed Django community!
I would like to propose an interesting enhancement that, in my opinion, could significantly simplify the process of model constraint validation. Currently, when detecting model constraint violations, Django generates a ValidationError
object, which code
and message
attributes are based on ‘violation_error_code’ and violation_error_message
of BaseConstraint
class. However, this mechanism has certain limitations, such as not being triggered in all scenarios, for example, when UniqueConstraint.fields
is set, but UniqueConstraint.condition
is not.
Example:
class Article(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE)
folder = models.ForeignKey(Folder, models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
status = models.CharField(max_length=32)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["user"],
condition=Q(status="DRAFT"),
name="unique_draft_user",
# These 2 parameters will be used for generating ValidationError
violation_error_code='unique_draft_user',
violation_error_message=_('You can have only one draft.')
),
models.UniqueConstraint(
fields=['user', 'folder', 'title'],
name='unique_path',
# These 2 parameters will not be used for generating ValidationError (no condition set)
violation_error_code='unique_path',
violation_error_message=_('Article with this Name already exists in this Folder.')
),
]
My proposal involves using the attributes BaseConstraint.violation_error_code
and BaseConstraint.violation_error_message
to set the corresponding values of ValidationError.code
and ValidationError.message
in all scenarios.
When validating the model using full_clean()
, it would be wonderful to have the ability to explicitly set the error code and message in case of constraint violations. This enhancement would allow us to more flexibly manage validation error behavior and better tailor it to our needs.
I would like to highlight an additional benefit that this mechanism would offer. It would provide us with the ability to override ModelForm.Meta.error_messages
specifically for certain NON_FIELD_ERRORS
exceptions.
For example:
from django import forms
from django.core.exceptions import NON_FIELD_ERRORS
from django.utils.translation import gettext_lazy as _
class ArticleForm(forms.ModelForm):
"""
Form for handling Article model data.
"""
class Meta:
model = Article
fields = ["title", "content", "status", "folder", "user"]
# Override error messages for specific NON_FIELD_ERRORS exceptions
error_messages = {
NON_FIELD_ERRORS: {
'unique_draft_user': _('This message will override the original "unique_draft_user" error message'),
'unique_path': _('This message will override the original "unique_path" error message'),
}
}
With this enhancement, we can provide more customized and meaningful error messages for specific non-field errors, enhancing the overall user experience.
Also, I propose the addition of default parameters for ValidationError.params
(the Model.unique_error_message()
method builds interesting default params). This would simplify the process of customizing error messages by providing a consistent set of parameters.
class Article(models.Model):
...
class Meta:
constraints = [
...
models.UniqueConstraint(
...
# Use the `model_class` default param
violation_error_message=_('%(model_class)s with this Name already exists in this Folder.')
),
]
What are your thoughts on this idea? I appreciate your comments and discussions!
Thank you!