| 200 | ) |
| 201 | |
| 202 | def validate(self, model, instance, exclude=None, using=DEFAULT_DB_ALIAS): |
| 203 | queryset = model._default_manager.using(using) |
| 204 | replacement_map = instance._get_field_expression_map( |
| 205 | meta=model._meta, exclude=exclude |
| 206 | ) |
| 207 | replacements = {F(field): value for field, value in replacement_map.items()} |
| 208 | lookups = [] |
| 209 | for expression, operator in self.expressions: |
| 210 | if isinstance(expression, str): |
| 211 | expression = F(expression) |
| 212 | if exclude and self._expression_refs_exclude(model, expression, exclude): |
| 213 | return |
| 214 | rhs_expression = expression.replace_expressions(replacements) |
| 215 | if hasattr(expression, "get_expression_for_validation"): |
| 216 | expression = expression.get_expression_for_validation() |
| 217 | if hasattr(rhs_expression, "get_expression_for_validation"): |
| 218 | rhs_expression = rhs_expression.get_expression_for_validation() |
| 219 | lookup = PostgresOperatorLookup(lhs=expression, rhs=rhs_expression) |
| 220 | lookup.postgres_operator = operator |
| 221 | lookups.append(lookup) |
| 222 | queryset = queryset.filter(*lookups) |
| 223 | model_class_pk = instance._get_pk_val(model._meta) |
| 224 | if not instance._state.adding and instance._is_pk_set(model._meta): |
| 225 | queryset = queryset.exclude(pk=model_class_pk) |
| 226 | if not self.condition: |
| 227 | if queryset.exists(): |
| 228 | raise ValidationError( |
| 229 | self.get_violation_error_message(), code=self.violation_error_code |
| 230 | ) |
| 231 | else: |
| 232 | # Ignore constraints with excluded fields in condition. |
| 233 | if exclude and self._expression_refs_exclude( |
| 234 | model, self.condition, exclude |
| 235 | ): |
| 236 | return |
| 237 | if (self.condition & Exists(queryset.filter(self.condition))).check( |
| 238 | replacement_map, using=using |
| 239 | ): |
| 240 | raise ValidationError( |
| 241 | self.get_violation_error_message(), code=self.violation_error_code |
| 242 | ) |