I have a pattern in my project where I need to re-use filtering logic for returning multiple results and a single result (depending on the input and needs of the caller). I'd like to make some generic function that takes a QuerySet as its input and either returns the only item in it or raises an exception like Model.objects.get()
does if the number of results is not 1.
def single_result_from_qset(qset: "QuerySet") -> Any:
"""TODO: make this work somehow"""
if len(qset) > 1:
raise qset.MultipleObjectsReturned
try:
return qset[0]
except IndexError: # this is not unreachable, no matter what PyCharm tells you
raise qset.DoesNotExist
The problem I have with the above code I've tried arises when I need to raise an error. Instead of raising the error I asked it to, I get an AttributeError
because neither MultipleObjectsReturned
nor DoesNotExist
are attributes of a QuerySet
. How do I raise these errors from the objects the QuerySet is acting on?
As a bonus question, what is the proper type signature for the function definition?
The better solution is to use .get()
from QuerySet
rather than implement a new helper function. .get()
returns and throws exactly what I was asking the above helper function to do.
Instead of calling rabbit = single_result_from_qset(search_animals_by_meat("Haßenpferrer))
, I can use rabbit = search_animals_by_meat("Haßenpferrer).get()
.
search_animals_by_meat(q: str) -> "QuerySet[Animal]"
could be a wrapper for something like Animals.objects.filter(meat_name__icontains=q)
or a far more complex filtering scheme.