On May 23, 11:43 am, akaariai <akaar...@gmail.com> wrote:

> I would guess you would get duplicate objects returned.

We programmers are usually very bad at guessing. So when in doubt,
check, don't guess ;)

> I think the
> query works as follows:
>   - Fetch all Blook's categories
>   - For those categories you fetch all the classifications (not only
> those which are related to Blook) and order by the position in there.

Not quite - cf the generated SQL below.

> So, you could get the same category multiple times ordered by
> positions not related to the blook <-> category connection.

That's not the case. Demonstration:

First, check that we do have categories shared by multiples blooks
(else it wouldn't mean much):

>>> for blook in blooks:
...     print blook, blook.categories.order_by("id").values_list("id",
flat=True)
...

#139 [533L, 534L, 535L, 536L, 537L, 538L, 539L, 540L, 541L, 542L,
543L, 544L, 545L, 546L, 547L]
#129 [534L, 535L, 537L, 539L, 540L, 542L, 543L, 544L, 545L, 546L,
547L]
#128 [534L]
#126 [533L, 534L, 535L, 536L, 537L, 538L, 539L, 540L, 541L, 542L,
543L, 544L, 545L, 546L, 547L]
#127 [533L, 534L, 535L, 536L, 537L, 538L, 539L, 540L, 541L, 542L,
543L, 544L, 545L, 546L, 547L]
#118 [534L]

Now check that for each blook, we have the same categories whether
sorted or unsorted:

>>> for blook in blooks:
...     cats = blook.categories.all()
...     scats = blook.sorted_categories
...     assert set(cats) == set(scats), "OOPS ??? %s" % blook
...

Well... No AssertionError raised, so it's correct.

> Maybe the above code does work correctly.

It does.

Custom ordering is possibly one of the most common use case for
"through" m2ms, so you can bet it works - else there would have been
quite some criticism about it ;)

> The interaction between
> multiple references to same reverse foreign key relation in single
> queryset is somewhat hard to remember. Could you post the generated
> SQL?

here you go - reformated for readability:

SELECT
  `blookcore_category`.`id`,
  `blookcore_category`.`label`
FROM
  `blookcore_category`
   LEFT OUTER JOIN `blookcore_classification`
   ON (`blookcore_category`.`id` =
`blookcore_classification`.`category_id`)
WHERE
   `blookcore_classification`.`blook_id` = 118
ORDER BY
   `blookcore_classification`.`position` ASC


I don't quite get why it uses a left outer join instead of the inner
join used when not adding the order by clause, but writing a working,
usable ORM is not exactly a piece of cake so I won't complain about
this ;). Anyway: the where clause still makes sure we only get the
relevant categories.

HTH

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to