| 1634 | |
| 1635 | @deconstructible(path="django.db.models.When") |
| 1636 | class When(Expression): |
| 1637 | template = "WHEN %(condition)s THEN %(result)s" |
| 1638 | # This isn't a complete conditional expression, must be used in Case(). |
| 1639 | conditional = False |
| 1640 | |
| 1641 | def __init__(self, condition=None, then=None, **lookups): |
| 1642 | if lookups: |
| 1643 | if invalid_kwargs := PROHIBITED_FILTER_KWARGS.intersection(lookups): |
| 1644 | invalid_str = ", ".join(f"'{k}'" for k in sorted(invalid_kwargs)) |
| 1645 | raise TypeError(f"The following kwargs are invalid: {invalid_str}") |
| 1646 | if condition is None: |
| 1647 | condition, lookups = Q(**lookups), None |
| 1648 | elif getattr(condition, "conditional", False): |
| 1649 | condition, lookups = Q(condition, **lookups), None |
| 1650 | if condition is None or not getattr(condition, "conditional", False) or lookups: |
| 1651 | raise TypeError( |
| 1652 | "When() supports a Q object, a boolean expression, or lookups " |
| 1653 | "as a condition." |
| 1654 | ) |
| 1655 | if isinstance(condition, Q) and not condition: |
| 1656 | raise ValueError("An empty Q() can't be used as a When() condition.") |
| 1657 | super().__init__(output_field=None) |
| 1658 | self.condition = condition |
| 1659 | self.result = self._parse_expressions(then)[0] |
| 1660 | |
| 1661 | def __str__(self): |
| 1662 | return "WHEN %r THEN %r" % (self.condition, self.result) |
| 1663 | |
| 1664 | def __repr__(self): |
| 1665 | return "<%s: %s>" % (self.__class__.__name__, self) |
| 1666 | |
| 1667 | def get_source_expressions(self): |
| 1668 | return [self.condition, self.result] |
| 1669 | |
| 1670 | def set_source_expressions(self, exprs): |
| 1671 | self.condition, self.result = exprs |
| 1672 | |
| 1673 | def resolve_expression( |
| 1674 | self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False |
| 1675 | ): |
| 1676 | c = super().resolve_expression(query, allow_joins, reuse, summarize, for_save) |
| 1677 | if for_save and c.condition is not None: |
| 1678 | # Resolve condition with for_save=False, since it's used as a |
| 1679 | # filter. |
| 1680 | c.condition = self.condition.resolve_expression( |
| 1681 | query, allow_joins, reuse, summarize, for_save=False |
| 1682 | ) |
| 1683 | return c |
| 1684 | |
| 1685 | def get_source_fields(self): |
| 1686 | # We're only interested in the fields of the result expressions. |
| 1687 | return [self.result._output_field_or_none] |
| 1688 | |
| 1689 | def as_sql(self, compiler, connection, template=None, **extra_context): |
| 1690 | connection.ops.check_expression_support(self) |
| 1691 | template_params = extra_context |
| 1692 | sql_params = [] |
| 1693 | condition_sql, condition_params = compiler.compile(self.condition) |
no outgoing calls