Reputation: 493
How do I take a Django object and wrap it to become a QuerySet with one item?
m: SomeModel = SomeModel.objects.get(pk=8)
However, later functions expect m to be a QuerySet (even with a length of 1).
The answer below works for if you only need to wrap specific models, but is there a way to do something like the below pseudocode?
def generic_model2qs(m: Model) -> "QuerySet[Model]":
return m.get_model().objects.filter(pk=m.pk)
Does Django have something like a .get_model()
function?
Upvotes: 2
Views: 1525
Reputation: 493
One way to do this is something like the below function
def wrap_some_model(m: SomeModel) -> "QuerySet[SomeModel]":
return SomeModel.objects.filter(pk=m.pk)
However, this is not a generic case and would need to be re-implemented for each different model.
A more generic answer with hints from this answer for getting the model name from an unknown object that I have implemented for my own project:
def self_as_qs(s, model: Optional[models.Model] = None) -> "QuerySet[models.Model]":
"""
Takes the input and returns it wrapped in a QuerySet
:param s: the thing you want to transform
:param model: optional specification to stop errors when using potentially-heterogeneous (nested) Iterables
:return: A QuerySet representation of the input
"""
# since you can't create a generic empty QuerySet
generic_empty: QuerySet = model.objects.none() if model else SomeModel.objects.none()
if isinstance(s, QuerySet) and not model: # check inner QS if a model is specified
return s # it's already a QuerySet
if isinstance(s, Iterable):
# only works if all items are of the same model
n = generic_empty
for item in s:
n = n | self_as_qs(item, model) # handle nested lists
return n
if not s:
return generic_empty
if model and not isinstance(s, type(model.objects.all()[0])):
return generic_empty
# for future extensibility
m = type(s)
n = [s.pk]
return m.objects.filter(pk__in=n)
Notes:
|
operator, order and nested structures are not preserved when running on an Iterable (QuerySet, List, Tuple, etc…)generic_empty: QuerySet = model.objects.none() if model else SomeModel.objects.none()
is there to ensure you have an empty QuerySet to return if the program needs to do so. You need to specify some model that you actually have here (doesn't have to be relevant to anywhere else, though), as there doesn't seem to be any generic empty QuerySet generator.Upvotes: 2