Skip to content

Commit 4621fd5

Browse files
committed
fix(serializer): restore get_unique_together_constraints method signature
Extracted error message logic to a separate method.
1 parent ac4151e commit 4621fd5

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

rest_framework/serializers.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,33 +1427,20 @@ def get_extra_kwargs(self):
14271427

14281428
def get_unique_together_constraints(self, model):
14291429
"""
1430-
Returns iterator of (fields, queryset, condition_fields, condition, message, code),
1430+
Returns iterator of (fields, queryset, condition_fields, condition),
14311431
each entry describes an unique together constraint on `fields` in `queryset`
1432-
with respect of constraint's `condition`, optional custom `violation_error_message` and `violation_error_code`.
1432+
with respect of constraint's `condition`.
14331433
"""
14341434
for parent_class in [model] + list(model._meta.parents):
14351435
for unique_together in parent_class._meta.unique_together:
1436-
yield unique_together, model._default_manager, [], None, None, None
1436+
yield unique_together, model._default_manager, [], None
14371437
for constraint in parent_class._meta.constraints:
14381438
if isinstance(constraint, models.UniqueConstraint) and len(constraint.fields) > 1:
14391439
if constraint.condition is None:
14401440
condition_fields = []
14411441
else:
14421442
condition_fields = list(get_referenced_base_fields_from_q(constraint.condition))
1443-
1444-
violation_error_message = constraint.get_violation_error_message()
1445-
default_error_message = constraint.default_violation_error_message % {"name": constraint.name}
1446-
if violation_error_message == default_error_message:
1447-
violation_error_message = None
1448-
1449-
yield (
1450-
constraint.fields,
1451-
model._default_manager,
1452-
condition_fields,
1453-
constraint.condition,
1454-
violation_error_message,
1455-
getattr(constraint, "violation_error_code", None)
1456-
)
1443+
yield (constraint.fields, model._default_manager, condition_fields, constraint.condition)
14571444

14581445
def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs):
14591446
"""
@@ -1486,7 +1473,7 @@ def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs
14861473

14871474
# Include each of the `unique_together` and `UniqueConstraint` field names,
14881475
# so long as all the field names are included on the serializer.
1489-
for unique_together_list, queryset, condition_fields, condition, *__ in self.get_unique_together_constraints(model):
1476+
for unique_together_list, queryset, condition_fields, condition in self.get_unique_together_constraints(model):
14901477
unique_together_list_and_condition_fields = set(unique_together_list) | set(condition_fields)
14911478
if model_fields_names.issuperset(unique_together_list_and_condition_fields):
14921479
unique_constraint_names |= unique_together_list_and_condition_fields
@@ -1582,6 +1569,17 @@ def get_validators(self):
15821569
self.get_unique_for_date_validators()
15831570
)
15841571

1572+
def _get_constraint_violation_error_message(self, constraint):
1573+
"""
1574+
Returns the violation error message for the UniqueConstraint,
1575+
or None if the message is the default.
1576+
"""
1577+
violation_error_message = constraint.get_violation_error_message()
1578+
default_error_message = constraint.default_violation_error_message % {"name": constraint.name}
1579+
if violation_error_message == default_error_message:
1580+
return None
1581+
return violation_error_message
1582+
15851583
def get_unique_together_validators(self):
15861584
"""
15871585
Determine a default set of validators for any unique_together constraints.
@@ -1608,10 +1606,15 @@ def get_unique_together_validators(self):
16081606
for name, source in field_sources.items():
16091607
source_map[source].append(name)
16101608

1609+
unique_constraint_by_fields = {
1610+
constraint.fields: constraint for constraint in self.Meta.model._meta.constraints
1611+
if isinstance(constraint, models.UniqueConstraint)
1612+
}
1613+
16111614
# Note that we make sure to check `unique_together` both on the
16121615
# base model class, but also on any parent classes.
16131616
validators = []
1614-
for unique_together, queryset, condition_fields, condition, message, code in self.get_unique_together_constraints(self.Meta.model):
1617+
for unique_together, queryset, condition_fields, condition in self.get_unique_together_constraints(self.Meta.model):
16151618
# Skip if serializer does not map to all unique together sources
16161619
unique_together_and_condition_fields = set(unique_together) | set(condition_fields)
16171620
if not set(source_map).issuperset(unique_together_and_condition_fields):
@@ -1634,13 +1637,17 @@ def get_unique_together_validators(self):
16341637
)
16351638

16361639
field_names = tuple(source_map[f][0] for f in unique_together)
1640+
1641+
constraint = unique_constraint_by_fields.get(tuple(unique_together), None)
1642+
violation_error_message = self._get_constraint_violation_error_message(constraint) if constraint else None
1643+
16371644
validator = UniqueTogetherValidator(
16381645
queryset=queryset,
16391646
fields=field_names,
16401647
condition_fields=tuple(source_map[f][0] for f in condition_fields),
16411648
condition=condition,
1642-
message=message,
1643-
code=code,
1649+
message=violation_error_message,
1650+
code=getattr(constraint, 'violation_error_code', None),
16441651
)
16451652
validators.append(validator)
16461653
return validators

0 commit comments

Comments
 (0)