values () error in Django ORMDjango ORM has similar methods, <Model> .objects.values () and <Model> .objects.only (), values () and ʻonly ()`, but a little I was addicted to it, so as a memorandum.
The origin of this is that when I wrote a code like ↓, I got the following error.
president1 = Company.objects.values(*fields)[0].president
# =>error: AttributeError: 'dict' object has no attribute 'president'
Here, from the model Company, using thevalues ()method of Django ORM,
I'm trying to get the value of the president field of the first element of a queryset (like a Python list with an iterable data type that contains multiple objects) that was generated by extracting only certain fields ..
However, at runtime I got the error ʻAttribute Error:'dict' object has no attribute'president'`.
Even after reviewing the model definition, I found out that the field president does exist, but this is strange. difference between values () and only () was helpful.
values () returns ValuesQuerySet instead of QuerySetAccording to the reference article, the values () method returns an object of the data type ValuesQuerySet.
Based on QuerySet, it returns ** an array of elements converted from object fields into a dictionary (= ValuesQuerySet) **.
In other words, in the above code, I was trying to retrieve field data from the dictionary {'president':'xxx', ...} using .president, so I got an error.
Since it is a dictionary, using ['president'] means that no error occurred.
When you read the error message, it says 'dict' object. ..
returnsQuerySet`So, if you want QuerySet like this case, you can use ʻonly ()` [^ 1]. This time, the element is not a dictionary, but an instance of the class is returned properly, so no error occurs.
By the way, QuerySet is iterable, but be careful because the data type is different from list (because it is similar, I sometimes get hooked).
When converting a query set to a list, it can be converted with ** list (QuerySet object) **.
[^ 1]: Only specified fields can be extracted. Used for performance tuning. Conversely, you can use defer () to exclude the specified field.
Recommended Posts