Django values_list vs values

242,305

Solution 1

The values() method returns a QuerySet containing dictionaries:

<QuerySet [{'comment_id': 1}, {'comment_id': 2}]>

The values_list() method returns a QuerySet containing tuples:

<QuerySet [(1,), (2,)]>

If you are using values_list() with a single field, you can use flat=True to return a QuerySet of single values instead of 1-tuples:

<QuerySet [1, 2]>

Solution 2

values()

Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable.

values_list()

Returns a QuerySet that returns list of tuples, rather than model instances, when used as an iterable.

distinct()

distinct are used to eliminate the duplicate elements.

Example:

>>> list(Article.objects.values_list('id', flat=True)) # flat=True will remove the tuples and return the list   
[1, 2, 3, 4, 5, 6]

>>> list(Article.objects.values('id'))
[{'id':1}, {'id':2}, {'id':3}, {'id':4}, {'id':5}, {'id':6}]

Solution 3

You can get the different values with:

set(Article.objects.values_list('comment_id', flat=True))

Solution 4

The best place to understand the difference is at the official documentation on values / values_list. It has many useful examples and explains it very clearly. The django docs are very user freindly.

Here's a short snippet to keep SO reviewers happy:

values

Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable.

And read the section which follows it:

value_list

This is similar to values() except that instead of returning dictionaries, it returns tuples when iterated over.

Share:
242,305

Related videos on Youtube

Hassan Baig
Author by

Hassan Baig

All I know is that I know nothing

Updated on December 11, 2020

Comments

  • Hassan Baig
    Hassan Baig over 3 years

    In Django, what's the difference between the following two:

    Article.objects.values_list('comment_id', flat=True).distinct()
    

    vs

    Article.objects.values('comment_id').distinct()
    

    My goal is to get a list of unique comment ids under each Article. I've read the documentation (and in fact have used both approaches). The results overtly seem similar.

    • dnaranjo
      dnaranjo about 8 years
      With values_list you can do if self.id in Article.objects.values_list('comment_id', flat=True): while using values you need to access the dictionary
    • Sayse
      Sayse about 8 years
      @dnaranjo - You could but why not just do Article.objects.filter(comment_id=self.id).exists()?
    • dnaranjo
      dnaranjo about 8 years
      That's an answer for a different question
  • Hassan Baig
    Hassan Baig about 8 years
    Oh and no difference among the two vis-a-vis how distinct() is used huh?
  • Alasdair
    Alasdair about 8 years
    No, I don't think distinct() works any differently. The important thing is which data structure that you want to work with.
  • Hassan Baig
    Hassan Baig over 7 years
    So it's a list of dictionaries that's returned in case of values
  • Abhijit Ghate
    Abhijit Ghate almost 6 years
    The values() returns a QuerySet and not a list. Although the object returned by values() looks like a list, it doesn't behave like one in some cases. For example, it won't be json serializable unless we convert it into a `list'
  • Alasdair
    Alasdair almost 6 years
    @AbhijitGhate good point, I've updated the answer to make that clearer.
  • inostia
    inostia about 5 years
    You can easily convert the return from values_list to a true Python list by just using the list function: list(Article.objects.values_list('comment_id', flat=True).distinct())
  • oz19
    oz19 over 4 years
    Just to clarify: distinct() eliminates the duplicate elements from query results, not from database.
  • enchance
    enchance over 4 years
    As mentioned, if your tuple has 1 value then you can use flat=True. But if it has 2 values such as [('name', 'Jim')] you can use dict([('name', 'Jim')]) which converts it to a dictionary with key-value pairs: {'name': 'Jim'}. Very useful.
  • l0b0
    l0b0 about 4 years
    @inostia In Django 2.2 I get "Error in argument:" when trying to convert using list()
  • Alasdair
    Alasdair about 4 years
    @l0b0 the issue is probably in the queryset itself, not the list() call. We can’t help with that in the comments here. If you’re still sick please open a new question and include the code, models and full traceback of the error.
  • l0b0
    l0b0 about 4 years
    Turns out set() does work, so I'm just using that.
  • Alexander Suraphel
    Alexander Suraphel almost 4 years
    This will be way slower than using distinct() to eliminate duplicates at database level.
  • Elektordi
    Elektordi over 3 years
    Also, using set() will force a query on the whole table, when a QuerySet (returned by distinct()) will stream data only when needed.