#22268: values_list() on a ManyToManyField returns extra None's when iterated 
over.
-------------------------------------+-------------------------------------
     Reporter:  k_sze                |                    Owner:
         Type:  Bug                  |  anubhav9042
    Component:  Database layer       |                   Status:  assigned
  (models, ORM)                      |                  Version:  master
     Severity:  Normal               |               Resolution:
     Keywords:  orm, values_list,    |             Triage Stage:  Accepted
  ManyToManyField                    |      Needs documentation:  0
    Has patch:  0                    |  Patch needs improvement:  0
  Needs tests:  0                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------

Comment (by k_sze):

 Actually the whole behaviour of `values()` and `values_list()` seems to be
 wrong once you mix M2M fields into the picture. I just tried creating more
 Class and Student objects:

 {{{
 # New student, Joe Blo
 >>> joe_blo = Student(surname='Blo', given_name='Joe')
 >>> joe_blo.save()

 # New class, Discrete Mathematics
 >>> discrete_math = Class(name='Discrete Mathematics', school=concordia)
 >>> discrete_math.save()

 # Enroll both john_smith and joe_blo in discrete_math
 discrete_math.students.add(joe_blo)
 discrete_math.students.add(john_smith)
 }}}

 First, let's look at `values()` queries:
 {{{
 >>> Class.objects.values()
 [{u'id': 1, 'name': u'Software Engineering', 'school_id': 1}, {u'id': 2,
 'name': u'Computer Engineering', 'school_id': 1}, {u'id': 4, 'name':
 u'Discrete Mathematics', 'school_id': 1}]
 }}}
 That's 3 dictionaries because we now have 3 Class objects. That seems
 fine. On the other hand, why don't students appear here?

 {{{
 >>> Class.objects.values('name', 'students')
 [{'students': 1, 'name': u'Software Engineering'}, {'students': None,
 'name': u'Computer Engineering'}, {'students': 1, 'name': u'Discrete
 Mathematics'}, {'students': 2, 'name': u'Discrete Mathematics'}]
 }}}
 That's 4 dictionaries even though we only have 3 Class objects (soen,
 coen, and discrete_math). Can you imagine what would happen if the Class
 object had more M2M fields? The number of dictionaries returned would
 probably explode exponentially! Why aren't the students combined into a
 tuple or a list? Shouldn't it be 3 dictionaries like this:
 {{{
 [
     {'students': (1,), 'name': u'Software Engineering'},
     {'students': (,), 'name': u'Computer Engineering'}, # Note the empty
 tuple for students, instead of None
     {'students': (1, 2), 'name': u'Discrete Mathematics'},
 ]
 }}}

 Now, let's look at `values_list()` queries:
 {{{
 >>> Class.objects.values_list()
 [(1, 1, u'Software Engineering'), (2, 1, u'Computer Engineering'), (4, 1,
 u'Discrete Mathematics')]
 }}}
 3 tuples. Again, this seems fine except for the fact that students aren't
 included.

 {{{
 >>> Class.objects.values_list('name', 'students')
 [(u'Software Engineering', 1), (u'Computer Engineering', None),
 (u'Discrete Mathematics', 1), (u'Discrete Mathematics', 2)]
 }}}
 4 tuples even though we have 3 Class objects only! Shouldn't this be 3
 tuples like this:
 {{{
 [
     (u'Software Engineering', (1,)),
     (u'Computer Engineering', (,)), # Note the empty tuple instead of None
     (u'Discrete Mathematics', (1, 2)),
 ]
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/22268#comment:15>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/063.b2d7eb0d7fa81b5101b3633481cc1673%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to