Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django case when else in filter

I need a similar code to this SQL:

SELECT * FROM tab WHERE a = CASE WHEN x IS NULL THEN b ELSE c END

my attempt, but to no success:

model.objects.filter(a=Q(Case(When(x__isnull=True, then='b'), default='c')))

when I try to run, I get this error:

Traceback (most recent call last):
  File "<input>", line 2, in <module>
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\query.py", line 904, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\query.py", line 923, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\sql\query.py", line 1340, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\sql\query.py", line 1371, in _add_q
    check_filterable=check_filterable,
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\sql\query.py", line 1249, in build_filter
    value = self.resolve_lookup_value(value, can_reuse, allow_joins, simple_col)
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\sql\query.py", line 1058, in resolve_lookup_value
    value = value.resolve_expression(self, **kwargs)
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\query_utils.py", line 95, in resolve_expression
    check_filterable=False,
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\sql\query.py", line 1371, in _add_q
    check_filterable=check_filterable,
  File "C:\projetos\xxx\venv\lib\site-packages\django\db\models\sql\query.py", line 1237, in build_filter
    arg, value = filter_expr
TypeError: cannot unpack non-iterable Case object
like image 835
Thales Gibbon Avatar asked Oct 25 '25 04:10

Thales Gibbon


1 Answers

You should not wrap this in a Q object, since a Q object is a condition, a Case is not something that can be True or False:

from django.db.models import Case, When

model.objects.filter(a=Case(When(x__isnull=True, then='b'), default='c'))

Note that you can replace x__isnull=True with simply x=None, which is slightly shorter:

from django.db.models import Case, When

model.objects.filter(a=Case(When(x=None, then='b'), default='c'))
like image 164
Willem Van Onsem Avatar answered Oct 26 '25 16:10

Willem Van Onsem