Brian Cray
Brian Cray

Reputation: 1275

Filter an evaluated QuerySet in Django

The requirement is for me to be able to access members of an evaluated QuerySet by a string attribute, in this case name. I don't like the idea of looping over a QuerySet as it seems like there is a more efficient way.

After I've called something like:

my_objects = MyObject.objects.all()

And I evaluate it with something like:

len(my_objects)

What is the best way to get a specific result by name from an evaluated QuerySet, in this case my_objects? Ideally I'd like to see something like my_objects.filter(foo='bar').

Note I'll need all of the results in the evaluated QuerySet during the course of the process, so that's why I have it in one initial query.

Upvotes: 3

Views: 2187

Answers (3)

djvg
djvg

Reputation: 14325

@aamir-rind's solution is great, but it only works if name is unique.

If name is not unique, you could, for example, collect the objects in a list:

# map name to list of objects
my_objects_dict = dict()
for obj in my_objects:
    key = obj.name
    if key not in my_objects_dict:
        my_objects_dict[key] = []
    my_objects_dict[key].append(obj)

If my_objects has not been evaluated yet, the loop will evaluate it. If my_objects has already been evaluated, e.g. as in my_objects = list(MyModel.objects.all()), it will not be evaluated again.

Upvotes: 0

Dmitriy Sintsov
Dmitriy Sintsov

Reputation: 4169

Evaluated queryset is a list. There is no indexation of list elements, so looping is required anyway. But evaluated queryset is assumed to be not so huge, max few hundreds of entries so looping is ok. Do not evaluate large querysets.

By the way, similar lists of objects are created by prefetch_related(). There is an implementation of ListQuerySet which supports many filters, ordering and distinct, making possible to run many (not all though) queries for such lists of objects:

https://github.com/Dmitri-Sintsov/django-jinja-knockout/blob/master/django_jinja_knockout/query.py

Upvotes: 0

Aamir Rind
Aamir Rind

Reputation: 39689

There is no direct way of doing this to get a object based on field value from queryset. But you can do one thing is to create a dictionary from queryset and set name as key (must be unique):

my_objects = MyObject.objects.all()
obj_dict = {obj.name: obj for obj in my_objects}
print obj_dict['any_name']

FYI: If you want to just retrieve a single object from table then you can use .get method:

obj = MyObject.objects.get(pk=id)
or
obj = MyObject.objects.get(name='unique_name')

Upvotes: 3

Related Questions