How to get a list of queryset selected fields

1,498 views
Skip to first unread message

Todor Velichkov

unread,
Jun 15, 2017, 3:51:56 PM6/15/17
to Django users
That's it, I want to get a list of all fields which are going to be selected by a queryset, is it possible?

e.g.

qs = MyModel.objects.only('id', 'name')
select = qs.query.select #should be ['id','name']

PS. I notice there is a `qs.query.select`, but its empty. No idea if its the same as what I'm looking for, and how to use/fill it.
PS2. The method should return all fields, i.e. annotations too (if there are any).




Matthew Pava

unread,
Jun 15, 2017, 4:06:42 PM6/15/17
to django...@googlegroups.com

You may be looking for values.

MyModel.objects.all().values()

returns a QuerySet list of dictionaries with the field names as the keys.

 

You can specify which specific fields you want to return by passing them as arguments to values().

MyModel.objects.all().values('id', 'name')

Then you can use the first item in the QuerySet to retrieve all the keys.

MyModel.objects.all().values('id', 'name')[0].keys()

 

 

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#values

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/56059101-4006-4ab4-91dd-3a696e07f101%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Bruno Soares

unread,
Jun 15, 2017, 5:33:59 PM6/15/17
to Django users

Todor Velichkov

unread,
Jun 15, 2017, 5:35:45 PM6/15/17
to Django users
Hello, Matthew Pava, thank you for your answer.
This is probably the solution which I'm going to use if there isn't anything better, but overall I don't like this approach for a few reasons:

1) Dict keys are unordered, I would prefer to be ordered as requested (or as defined in the Model) I guess with some help from _meta.fields I can partially solve this)
2) . values() changes the queryset, I'm not sure if this won't have some side effects of the final result?
3) The whole approach of evaluating the queryset + picking the first item is just looking hacky. But as I already said If there is nothing better I will go for it.

Todor Velichkov

unread,
Jun 15, 2017, 5:47:43 PM6/15/17
to Django users
Hi, Bruno Soares, well values_list is not what I'm looking for, I'm searching for a list of field names, not field values.

Imagine you have a queryset you know nothing about it (how it gets generated) and you want to build a representation (table) of it. The first thing would be to render the table header, to do so you need to know what fields are selected + their order.

Matthew Pava

unread,
Jun 15, 2017, 7:12:26 PM6/15/17
to django...@googlegroups.com
I have done some digging into the QuerySet API, and I think I may have found what you are looking for:
MyModel.objects.all().query.get_meta().fields

You can access the fields that are deferred by using MyModel.objects.all().query.deferred_loading. Note that the deferred columns will still be retrieved from the database when requested.

You can also access annotations by using MyModel.objects.all().query.annotations, which is an OrderedDict.

In short, it doesn't look like there is an easy to way to simply access all the fields that are going to appear in your SELECT clause of your query from the query itself. You will need to process them.

And, you're right; selecting the first item in a queryset does seem hackish. You could even try this:
MyModel.objects.values().first()
which will return None if the queryset is empty, which doesn't have an attribute of .keys().


-----Original Message-----
From: django...@googlegroups.com [mailto:django...@googlegroups.com] On Behalf Of Todor Velichkov
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/7d3ecf53-ccad-4620-b34b-48c1788dba6a%40googlegroups.com.

Todor Velichkov

unread,
Jun 15, 2017, 9:42:43 PM6/15/17
to Django users, Matthe...@iss.com
query.get_meta().fields == query.model._meta.fields, i.e. all the model fields

As far as I understand from reading, deferred_loading is populated only when the queryset is deferred itself, but at the same time if I use .values(*some_fields) instead of .only(*some_fields), its empty again (i.e. its not working for queryset generated by .values()).

However I kept digging and I think I found something!

compiler.get_select()

Returns three values:
- a list of 3-tuples of (expression, (sql, params), alias)
- a klass_info structure,
- a dictionary of annotations

where this can be obtained by: queryset.query.get_compiler(using=queryset.db).get_select()

From what I have mange to test so farm its consistent against different types of querysets (deferred, values, +annotations, etc).

Thank you for the help so far Matthew.
Reply all
Reply to author
Forward
0 new messages