mirror of
https://github.com/django/django.git
synced 2024-12-22 09:05:43 +00:00
Fixed #35103 -- Used provided error code and message when fields is set without a condition on UniqueConstraint.
This commit is contained in:
parent
1979b1403a
commit
e970bb7ca7
@ -690,11 +690,19 @@ class UniqueConstraint(BaseConstraint):
|
|||||||
queryset = queryset.exclude(pk=model_class_pk)
|
queryset = queryset.exclude(pk=model_class_pk)
|
||||||
if not self.condition:
|
if not self.condition:
|
||||||
if queryset.exists():
|
if queryset.exists():
|
||||||
if self.fields:
|
if (
|
||||||
# When fields are defined, use the unique_error_message() for
|
self.fields
|
||||||
# backward compatibility.
|
and self.violation_error_message
|
||||||
|
== self.default_violation_error_message
|
||||||
|
):
|
||||||
|
# When fields are defined, use the unique_error_message() as
|
||||||
|
# a default for backward compatibility.
|
||||||
|
validation_error_message = instance.unique_error_message(
|
||||||
|
model, self.fields
|
||||||
|
)
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
instance.unique_error_message(model, self.fields),
|
validation_error_message,
|
||||||
|
code=validation_error_message.code,
|
||||||
)
|
)
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
self.get_violation_error_message(),
|
self.get_violation_error_message(),
|
||||||
|
@ -282,27 +282,47 @@ PostgreSQL 15+.
|
|||||||
|
|
||||||
.. attribute:: UniqueConstraint.violation_error_code
|
.. attribute:: UniqueConstraint.violation_error_code
|
||||||
|
|
||||||
The error code used when ``ValidationError`` is raised during
|
The error code used when a ``ValidationError`` is raised during
|
||||||
:ref:`model validation <validating-objects>`. Defaults to ``None``.
|
:ref:`model validation <validating-objects>`.
|
||||||
|
|
||||||
This code is *not used* for :class:`UniqueConstraint`\s with
|
Defaults to :attr:`.BaseConstraint.violation_error_code`, when either
|
||||||
:attr:`~UniqueConstraint.fields` and without a
|
:attr:`.UniqueConstraint.condition` is set or :attr:`.UniqueConstraint.fields`
|
||||||
:attr:`~UniqueConstraint.condition`. Such :class:`~UniqueConstraint`\s have the
|
is not set.
|
||||||
same error code as constraints defined with :attr:`.Field.unique` or in
|
|
||||||
:attr:`Meta.unique_together <django.db.models.Options.constraints>`.
|
If :attr:`.UniqueConstraint.fields` is set without a
|
||||||
|
:attr:`.UniqueConstraint.condition`, defaults to the :attr:`Meta.unique_together
|
||||||
|
<django.db.models.Options.unique_together>` error code when there are multiple
|
||||||
|
fields, and to the :attr:`.Field.unique` error code when there is a single
|
||||||
|
field.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.2
|
||||||
|
|
||||||
|
In older versions, the provided
|
||||||
|
:attr:`.UniqueConstraint.violation_error_code` was not used when
|
||||||
|
:attr:`.UniqueConstraint.fields` was set without a
|
||||||
|
:attr:`.UniqueConstraint.condition`.
|
||||||
|
|
||||||
``violation_error_message``
|
``violation_error_message``
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
.. attribute:: UniqueConstraint.violation_error_message
|
.. attribute:: UniqueConstraint.violation_error_message
|
||||||
|
|
||||||
The error message used when ``ValidationError`` is raised during
|
The error message used when a ``ValidationError`` is raised during
|
||||||
:ref:`model validation <validating-objects>`. Defaults to
|
:ref:`model validation <validating-objects>`.
|
||||||
:attr:`.BaseConstraint.violation_error_message`.
|
|
||||||
|
|
||||||
This message is *not used* for :class:`UniqueConstraint`\s with
|
Defaults to :attr:`.BaseConstraint.violation_error_message`, when either
|
||||||
:attr:`~UniqueConstraint.fields` and without a
|
:attr:`.UniqueConstraint.condition` is set or :attr:`.UniqueConstraint.fields`
|
||||||
:attr:`~UniqueConstraint.condition`. Such :class:`~UniqueConstraint`\s show the
|
is not set.
|
||||||
same message as constraints defined with
|
|
||||||
:attr:`.Field.unique` or in
|
If :attr:`.UniqueConstraint.fields` is set without a
|
||||||
:attr:`Meta.unique_together <django.db.models.Options.constraints>`.
|
:attr:`.UniqueConstraint.condition`, defaults to the :attr:`Meta.unique_together
|
||||||
|
<django.db.models.Options.unique_together>` error message when there are
|
||||||
|
multiple fields, and to the :attr:`.Field.unique` error message when there is a
|
||||||
|
single field.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.2
|
||||||
|
|
||||||
|
In older versions, the provided
|
||||||
|
:attr:`.UniqueConstraint.violation_error_message` was not used when
|
||||||
|
:attr:`.UniqueConstraint.fields` was set without a
|
||||||
|
:attr:`.UniqueConstraint.condition`.
|
||||||
|
@ -358,6 +358,11 @@ Miscellaneous
|
|||||||
* ``HttpRequest.accepted_types`` is now sorted by the client's preference, based
|
* ``HttpRequest.accepted_types`` is now sorted by the client's preference, based
|
||||||
on the request's ``Accept`` header.
|
on the request's ``Accept`` header.
|
||||||
|
|
||||||
|
* :attr:`.UniqueConstraint.violation_error_code` and
|
||||||
|
:attr:`.UniqueConstraint.violation_error_message` are now always used when
|
||||||
|
provided. Previously, these were ignored when :attr:`.UniqueConstraint.fields`
|
||||||
|
were set without a :attr:`.UniqueConstraint.condition`.
|
||||||
|
|
||||||
* The :func:`~django.template.context_processors.debug` context processor is no
|
* The :func:`~django.template.context_processors.debug` context processor is no
|
||||||
longer included in the default project template.
|
longer included in the default project template.
|
||||||
|
|
||||||
|
@ -72,15 +72,13 @@ class GeneratedFieldVirtualProduct(models.Model):
|
|||||||
class UniqueConstraintProduct(models.Model):
|
class UniqueConstraintProduct(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
color = models.CharField(max_length=32, null=True)
|
color = models.CharField(max_length=32, null=True)
|
||||||
|
age = models.IntegerField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
constraints = [
|
constraints = [
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=["name", "color"],
|
fields=["name", "color"],
|
||||||
name="name_color_uniq",
|
name="name_color_uniq",
|
||||||
# Custom message and error code are ignored.
|
|
||||||
violation_error_code="custom_code",
|
|
||||||
violation_error_message="Custom message",
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -953,6 +953,41 @@ class UniqueConstraintTests(TestCase):
|
|||||||
ChildUniqueConstraintProduct(name=self.p1.name, color=self.p1.color),
|
ChildUniqueConstraintProduct(name=self.p1.name, color=self.p1.color),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_validate_unique_custom_code_and_message(self):
|
||||||
|
product = UniqueConstraintProduct.objects.create(
|
||||||
|
name="test", color="red", age=42
|
||||||
|
)
|
||||||
|
code = "custom_code"
|
||||||
|
message = "Custom message"
|
||||||
|
multiple_fields_constraint = models.UniqueConstraint(
|
||||||
|
fields=["color", "age"],
|
||||||
|
name="color_age_uniq",
|
||||||
|
violation_error_code=code,
|
||||||
|
violation_error_message=message,
|
||||||
|
)
|
||||||
|
single_field_constraint = models.UniqueConstraint(
|
||||||
|
fields=["color"],
|
||||||
|
name="color_uniq",
|
||||||
|
violation_error_code=code,
|
||||||
|
violation_error_message=message,
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(ValidationError, message) as cm:
|
||||||
|
multiple_fields_constraint.validate(
|
||||||
|
UniqueConstraintProduct,
|
||||||
|
UniqueConstraintProduct(
|
||||||
|
name="new-test", color=product.color, age=product.age
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.assertEqual(cm.exception.code, code)
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(ValidationError, message) as cm:
|
||||||
|
single_field_constraint.validate(
|
||||||
|
UniqueConstraintProduct,
|
||||||
|
UniqueConstraintProduct(name="new-test", color=product.color),
|
||||||
|
)
|
||||||
|
self.assertEqual(cm.exception.code, code)
|
||||||
|
|
||||||
@skipUnlessDBFeature("supports_table_check_constraints")
|
@skipUnlessDBFeature("supports_table_check_constraints")
|
||||||
def test_validate_fields_unattached(self):
|
def test_validate_fields_unattached(self):
|
||||||
Product.objects.create(price=42)
|
Product.objects.create(price=42)
|
||||||
|
Loading…
Reference in New Issue
Block a user