2

Here is a scenario that I currently plan solving with .extra(where=...) call:

class CustomData(models.Model):
   data = models.CharField()
   target_type = models.ForeignKey(ContentType)
   target_object_id = models.PositiveInteger()
   target_object = GenericForeignKey('target_type', 'target_object_id')

# list of tuples with object ID and mixed content type ID [(1, 15), (2, 15), (3, 11), (4, 12), ...]
related_objects = get_list_of_objects(...)
releated_custom_data = CustomData.objects.extra(
      where=['(target_object_id, target_type_id) = ANY (VALUES %s)'], 
      params=str(related_objects)[1:-1]
)

Based on the django docs extra is getting deprecated in the future. Is there a sensible alternative for making a value pair filtering with the ORM?

Joshua
  • 1,128
  • 3
  • 17
  • 31
Peter Galfi
  • 374
  • 2
  • 9

1 Answers1

1

You can make a Q object that filters combinations of the two, like:

from django.db.models import Q

data = [(1, 15), (2, 15), (3, 11), (4, 12)]
q_filter = Q(
    *[Q(target_object_id=d1, target_type_id=d2) for d1, d2 in data],
    _connector=Q.OR
)

CustomData.objects.filter(q_filter)
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Thanks. That would work, but this obviously looses the benefits of using the ANY in PostgreSQL, which gives far better query performance than a series of OR clauses. Any thoughts? – Peter Galfi Jul 27 '20 at 09:18