Search code examples
djangodjango-modelsqobject

Django Q object - Is it possible to put those two queries together even if one depends from another?


Does anyone knows if is possible to put together two Q object queries in only one.

Is the first time I need to use it and I am quite lost.

First query:

vendors = Vendor.objects.filter(Q(is_approved=True, user__is_active=True), user_profile__location__distance_lte=(pnt, D(km=1))
   ).annotate(distance=Distance("user_profile__location", pnt)).order_by("distance")

Second query:

vendors = vendors.filter(Q(vendor_max_delivery_distance__gte=Distance("user_profile__location", pnt)))

Can i make a function like a helper so I could call it whenever needs? Is it better to do it in models or contextprocessors?

Thank you very much in advance!!!


Solution

  • In the simplest sense, Q allows you to use OR criteria in your filter (the normal, comma separated criteria are ANDs). If that's what you're after, your first line should look something like

    Vendor.objects.filter(
        Q(is_approved=True) | Q(user__is_active=True),
        user_profile__location__distance_lte=(pnt, D(km=1))
    

    In pseudocode that means

    Vendor where (EITHER is_approved OR user__is_active) AND user..distance__lte(pnt, D(Km=1))

    (note the double underscore after lte)

    You can also filter based on annnotations, so you can extend the original query to include the second line, eg

    annotate(distance=...).filter(distance__gte=...)
    

    As the second filter doesn't need an OR statement, you don't actually need Q to process it, and it can have its own filter criteria after annotate.

    On a final note, it is quite possible to set up a query in a view ahead of time and only use it when necessary (django has lazy evaluation so it wont make database calls until required to). Setting it up in a model or context processor really depends on the use case. If you are just generating data to use as context in a view, then the view is probably a good place for it.