My favorites | Sign in
Project Home Downloads Wiki Issues Source
READ-ONLY: This project has been archived. For more information see this post.
Search
for
  Advanced search   Search tips   Subscriptions
Issue 38: [has patch] add_related_count() can accept related querysets, not related model.
1 person starred this issue and may be notified of changes. Back to list
Status:  Chatting
Owner:  ----


 
Reported by mocksoul, Dec 5, 2008
This makes it much more usable. I'll show why.

Old fashion:

Model.tree.add_related_count(Model.objects.all(), AnotherModel, 'rel_col', 
'cnt', cumulative=True) makes this query:

SELECT (SELECT COUNT(*) FROM `another_model` WHERE (
    `rel_col_id` IN
    (
        SELECT m2.`id`
        FROM `model` m2
        WHERE m2.`mptt_tree_id` = `model`.`mptt_tree_id`
          AND m2.`mptt_left` BETWEEN `model`.`mptt_left`
                              AND `model`.`mptt_right`
    )
)) AS `cnt`, `col1`, `colN` FROM `model`

Good, but we cant change add more difficult subquery. My patch allows to 
use related querysets instead of related model (which being determined 
automatically).

Model.tree.add_related_count(Model.objects.all(), AnotherModel.objects.all
(), 'rel_col', 'cnt', cumulative=True) makes exactly the same query. But 
this:

Model.tree.add_related_count(Model.objects.all(), 
AnotherModel.objects.filter(field=1).filter(field=2), 'rel_col', 'cnt', 
cumulative=True) makes this:

SELECT (SELECT COUNT(*) FROM `another_model` WHERE `field` = 1 AND `field` 
= 2 AND (
    `field` = 2 AND
    `field` = 
    `rel_col_id` IN
    (
        SELECT m2.`id`
        FROM `model` m2
        WHERE m2.`mptt_tree_id` = `model`.`mptt_tree_id`
          AND m2.`mptt_left` BETWEEN `model`.`mptt_left`
                              AND `model`.`mptt_right`
    )
)) AS `cnt`, `col1`, `colN` FROM `model`


In my case: I have categories, tasks and users. With my patch I'm able to 
fill task counts for specified user in all categories :). Even more! Using 
non-documented "having" ability in django orm queries, I can select all 
categories which have >0 tasks for specified user. E.g.:

qs = AnotherModel.objects.filter(field=1).filter(field=2), 'rel_col', 
'cnt', cumulative=True)
qs.query.having.append('%s > %s' % (connection.ops.quote_name('cnt'), 0))

Which will have a result:

SELECT (SELECT COUNT(*) FROM `another_model` WHERE `field` = 1 AND `field` 
= 2 AND (
    `field` = 2 AND
    `field` = 
    `rel_col_id` IN
    (
        SELECT m2.`id`
        FROM `model` m2
        WHERE m2.`mptt_tree_id` = `model`.`mptt_tree_id`
          AND m2.`mptt_left` BETWEEN `model`.`mptt_left`
                              AND `model`.`mptt_right`
    )
)) AS `cnt`, `col1`, `colN` FROM `model` HAVING `cnt` > 0


All of these examples are for cumulative queries. But also apply to non-
cumulative queries as well. Woohooo! :)
more_usable_add_related_count.patch
2.8 KB   View   Download
Dec 5, 2008
#1 mocksoul
btw, I was thinking that such mptt technique will not be available with django orm. 
Nice :).
Dec 5, 2008
#2 mocksoul
Oh yes, templatetags should be fixed for this patch.
Dec 5, 2008
#3 mocksoul
This will fix templatetags, althouth with no ability to utilize my patch features.

=== modified file 'mptt/utils.py'
--- mptt/utils.py       2008-12-05 00:17:36 +0000
+++ mptt/utils.py       2008-12-05 23:16:07 +0000
@@ -128,7 +128,7 @@
     """
     if rel_cls and rel_field and count_attr:
         children = node._tree_manager.add_related_count(
-            node.get_children(), rel_cls, rel_field, count_attr, cumulative)
+            node.get_children(), rel_cls.objects.all(), rel_field, count_attr, 
cumulative)
     else:
         children = node.get_children()
     return itertools.chain(node.get_ancestors(), [node], children)
Sep 3, 2010
Project Member #4 craig.ds@gmail.com
mocksoul

Could this be accomplished with annotate() in Django 1.1+ ?

Thanks
Status: Chatting
Sep 7, 2010
#5 matjaz.c...@gmail.com
Indeed it looks like annotate would provide similar/same functionality but the performance/queries should be tested - as to which implementation (this patch or annotate) gives better performance.
I hope mocksoul is still interested in this and can shed a bit of light on this matter.

Powered by Google Project Hosting