DEV Community

Benji 🍙
Benji 🍙

Posted on

Using xyz.objects.get() with Q unexpectedly returns multiple objects

Using get() with Q in Django raises MultipleObjectsReturned. For context this was a method I wrote at work:

from django.db import models
# ...
def get_foobar(a, b):
    try:
        return Foobar.objects.get(
            models.Q(foo=a) | models.Q(bar__in=[a, b])
        )
    except DoesNotExist:
        return None
Enter fullscreen mode Exit fullscreen mode

Which translate in SQL to:

SELECT * FROM foobar
WHERE foo = 'a' OR bar IN ('a', 'b')
LIMIT 1
Enter fullscreen mode Exit fullscreen mode

And this works fine. Until it probably won't. To mitigate this you can instead return just the latest entry:

from django.db import models
# ...
def get_foobar(a, b):
    try:
        return Foobar.objects.filter(
            models.Q(foo=a) | models.Q(bar__in=[a, b])
        ).latest("created_at")
    except DoesNotExist:
        return None
Enter fullscreen mode Exit fullscreen mode

Or, append distinct(). But I wanted to return None explicitly so I stuck with the above.

Top comments (0)