@@ -1427,20 +1427,33 @@ def get_extra_kwargs(self):
14271427
14281428 def get_unique_together_constraints (self , model ):
14291429 """
1430- Returns iterator of (fields, queryset, condition_fields, condition),
1430+ Returns iterator of (fields, queryset, condition_fields, condition, message, code ),
14311431 each entry describes an unique together constraint on `fields` in `queryset`
1432- with respect of constraint's `condition`.
1432+ with respect of constraint's `condition`, optional custom `violation_error_message` and `violation_error_code` .
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
1436+ yield unique_together , model ._default_manager , [], None , None , 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- yield (constraint .fields , model ._default_manager , condition_fields , 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+ )
14441457
14451458 def get_uniqueness_extra_kwargs (self , field_names , declared_fields , extra_kwargs ):
14461459 """
@@ -1473,7 +1486,7 @@ def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs
14731486
14741487 # Include each of the `unique_together` and `UniqueConstraint` field names,
14751488 # so long as all the field names are included on the serializer.
1476- for unique_together_list , queryset , condition_fields , condition in self .get_unique_together_constraints (model ):
1489+ for unique_together_list , queryset , condition_fields , condition , * __ in self .get_unique_together_constraints (model ):
14771490 unique_together_list_and_condition_fields = set (unique_together_list ) | set (condition_fields )
14781491 if model_fields_names .issuperset (unique_together_list_and_condition_fields ):
14791492 unique_constraint_names |= unique_together_list_and_condition_fields
@@ -1598,7 +1611,7 @@ def get_unique_together_validators(self):
15981611 # Note that we make sure to check `unique_together` both on the
15991612 # base model class, but also on any parent classes.
16001613 validators = []
1601- for unique_together , queryset , condition_fields , condition in self .get_unique_together_constraints (self .Meta .model ):
1614+ for unique_together , queryset , condition_fields , condition , message , code in self .get_unique_together_constraints (self .Meta .model ):
16021615 # Skip if serializer does not map to all unique together sources
16031616 unique_together_and_condition_fields = set (unique_together ) | set (condition_fields )
16041617 if not set (source_map ).issuperset (unique_together_and_condition_fields ):
@@ -1626,6 +1639,8 @@ def get_unique_together_validators(self):
16261639 fields = field_names ,
16271640 condition_fields = tuple (source_map [f ][0 ] for f in condition_fields ),
16281641 condition = condition ,
1642+ message = message ,
1643+ code = code ,
16291644 )
16301645 validators .append (validator )
16311646 return validators
0 commit comments