Mihail
Mihail

Reputation: 83

Django - was queryset filtered using some parameters or not

The question related to python - django framework, and probably to experienced django developers. Googled it for some time, also seeked in django queryset itself, but have no answer. Is it possible to know if queryset has been filtered and if so, get key value of filtered parameters? I'm developing web system with huge filter set, and I must predefine some user-background behavior if some filters had been affected.

Upvotes: 1

Views: 877

Answers (3)

Will Hardy
Will Hardy

Reputation: 14846

I agree with Willem Van Onsen, in that accessing the internals of the query object isn't guaranteed to work in the future. It's correct for now, but might change.

But going half-way down that path, you could use the following:

is_filtered_query = bool(' WHERE ' in str(queryset.query))

which will pretty much do the job!

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477607

Yes, but since to the best of my knowledge this is not documented, you probably should not use it. Furthermore it looks to me like bad design if you need to obtain this from a QuerySet.

For a QuerySet, for example qs, you can obtain the .query attribute, and then query for the .where attribute. The truthiness of that attribute checks if that node (this attribute is a WhereNode, which is a node in the syntax of the query) has children (these children are then individual WHERE conditions, or groups of such conditions), hence has done some filtering.

So for example:

qs = Model.objects.all()
bool(qs.query.where)   # --> False

qs = Model.objects.filter(foo='bar')
bool(qs.query.where)   # --> True

If you inspect the WhereNode, you can see the elements out of which it is composed, for example:

>>> qs.query.where
<WhereNode: (AND: <django.db.models.lookups.Exact object at 0x7f2c55615160>)>

and by looking to the children, we even can obtain details:

>>> qs.query.where.children[0]
>>> c1.lhs
Col(app_model, app.Model.foo)
>>> c1.lookup_name
'exact'
>>> c1.rhs
'bar'

But the notation is rather cryptic. Furthermore the WhereNode is not per se a conjunctive one (the AND), it can also be an disjunctive one (the OR), and it is not said that any filtering will be done (since the tests can trivially be true, like 1 > 0). We thus only query if there will be a non-empty WHERE in the SQL query. Not whether this query will restrict the queryset in any way (although you can of course inspect the WhereNode, and look if that holds).

Note that some constraints are not part of the WHERE, for example if you make a JOIN, you will perform an ON, but this is not a WHERE clause.

Since however the above is - to the best of my knowledge - not extenstively documented, it is probably not a good idea to depend on this, since that means that it can easily change, and thus no longer work.

Upvotes: 7

samwalton
samwalton

Reputation: 551

You can use the query attribute (i.e. queryset.query) to get the data used in the SQL query (the output isn't exactly valid SQL).

You can also use queryset.query.__dict__ to get that data in a dictionary format.

Upvotes: 2

Related Questions