2

Let's say I have the following piece of code:

criteria = {'description': 'tt', 'hostname': '2'}
filters = Q()
{filters.add(Q(**{k+'__icontains': v}), Q.AND) for k,v in criteria.items()}

I can't figure out how to avoid doubling the outcome:

{<Q: (AND: ('description__icontains', 'tt'), ('hostname__icontains', '2'))>,
 <Q: (AND: ('description__icontains', 'tt'), ('hostname__icontains', '2'))>}

I understand I should shift Q.AND somewhere, shouldn't I?

sophros
  • 14,672
  • 11
  • 46
  • 75
ZmuA
  • 151
  • 1
  • 13
  • 2
    Are you sure the outcome is doubled, and you're not just seeing the same Q object, `filters`, printed twice? Can you show us what `str(filters)` looks like after this code? – Wander Nauta Jul 13 '21 at 08:56
  • That was the right track. `str(filters)` gives: `(AND: ('description__icontains', 'tt'), ('hostname__icontains', '2'))` Thanks Wander! – ZmuA Jul 13 '21 at 10:02

1 Answers1

0

It looks like you're inspecting the resulting set from the set comprehension, which lists the same Q object (filters) twice, after it's been modified. That's actually not a problem - you don't use that resulting set anywhere - but it does look a bit surprising.

As an alternative, it should be possible to pass all the kwargs you want to Q() in one go:

criteria = {'description': 'tt', 'hostname': '2'}
filters = Q(**{k + '__icontains': v for k, v in criteria.items()})

That removes the need for the set comprehension.

Wander Nauta
  • 18,832
  • 1
  • 45
  • 62