22

I have a queryset(which is filtered actually) as below

posts = [<Post: published>, <Post: needs>, <Post: be>, <Post: issues>, <Post: to>, <Post: tags>]

But i need to filter the above queryset manually with the some field coming from another table/place etc.

so i had filtered something like below

custom_list = []

for rec in posts:
    if 'string_or_field' in rec.tags.all():
        custom_list.extend(rec)

        or

custom_list = [rec for rec in posts if 'string_or_field' in rec.tags.all()]

So as we can observe above we are creating a list by filtering a queryset, but i want the result as a queryset.

So is there any way to convert the list to queryset object ?

Shiva Krishna Bavandla
  • 25,548
  • 75
  • 193
  • 313
  • Why exactly do you need an actual queryset? The point of duck-typing is that you should be able to use any list-like construct. – Daniel Roseman Sep 04 '13 at 08:38
  • yes actually i need a queryset to perform some operations since it is an object, but i got a list as above , so want to convert the resultant list to queryset – Shiva Krishna Bavandla Sep 04 '13 at 13:03

4 Answers4

17

Actually i had found one way by googling, but this may take a lot of time for querying/generating results if there are huge number of records

custom_list = [rec.id for rec in posts if 'string_or_field' in rec.tags.all()]

querset = MyModel.objects.filter(id__in=custom_list)
Shiva Krishna Bavandla
  • 25,548
  • 75
  • 193
  • 313
17

You can query the Tag object first and filter Post with those ids:

tags = Tag.objects.filter(field_name='string_or_field')
posts = Post.objects.filter(tags__in=tags)
Paulo Almeida
  • 7,803
  • 28
  • 36
  • If you need the queryset to be sorted in the same order as the list, see https://stackoverflow.com/a/61686789/303056 – Leopd Sep 06 '22 at 23:54
6

The previous answers are correct if each list item already exists in the database, but sometimes this is not the case. In this case you can create a queryset stub based on the list and implement queryset-methods and queryset-properties as needed.

class ListAsQuerySet(list):

    def __init__(self, *args, model, **kwargs):
        self.model = model
        super().__init__(*args, **kwargs)

    def filter(self, *args, **kwargs):
        return self  # filter ignoring, but you can impl custom filter

    def order_by(self, *args, **kwargs):
        return self

qs = ListAsQuerySet(custom_list, model=Post)
Ilya Petukhov
  • 682
  • 7
  • 12
4

Here's a simple util that you can run to produce a QS from a list:

def list_to_queryset(model, data):
    from django.db.models.base import ModelBase

    if not isinstance(model, ModelBase):
        raise ValueError(
            "%s must be Model" % model
        )
    if not isinstance(data, list):
        raise ValueError(
            "%s must be List Object" % data
        )

    pk_list = [obj.pk for obj in data]
    return model.objects.filter(pk__in=pk_list)
alias51
  • 8,178
  • 22
  • 94
  • 166