| 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 |
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! :)
Dec 5, 2008
#1
mocksoul
Dec 5, 2008
Oh yes, templatetags should be fixed for this patch.
Dec 5, 2008
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
mocksoul Could this be accomplished with annotate() in Django 1.1+ ? Thanks
Status:
Chatting
Sep 7, 2010
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.
Dec 18, 2010
Migrated to https://github.com/django-mptt/django-mptt/issues#issue/62 |