Мне удалось построить это динамически с помощью Q
fields = ['field_a', 'field_b', 'field_c', 'field_d']
q_query = reduce(operator.or_, (
(reduce(operator.and_, (
eval('Q({}__isnull={})'.format(f, False if f == field else True))
for f in fields
)))
for field in fields
))
MyModel.objects.filter(q_query)
Это создает объект Q с фильтрами AND, вложенными в фильтр OR, и выполняет запросы к этому
<Q: (
OR: (
AND: ('field_a__isnull', False), ('field_b__isnull', True), ('field_c__isnull', True), ('field_d__isnull', True)
), (
AND: ('field_a__isnull', True), ('field_b__isnull', False), ('field_c__isnull', True), ('field_d__isnull', True)
), (
AND: ('field_a__isnull', True), ('field_b__isnull', True), ('field_c__isnull', False), ('field_d__isnull', True)
), (
AND: ('field_a__isnull', True), ('field_b__isnull', True), ('field_c__isnull', True), ('field_d__isnull', False)
)
)>