Author: floguy
Date: Sun Sep 21 03:32:27 2008
New Revision: 30
Modified:
trunk/things/__init__.py
trunk/things/fields.py
trunk/things/options.py
Log:
Added OrderCountField, which applies to either a ManyToManyField, or to a
ForeignKey's RelatedManager, which does the required work to add an
aggregate query and allow for ordering by that.
Modified: trunk/things/__init__.py
==============================================================================
--- trunk/things/__init__.py (original)
+++ trunk/things/__init__.py Sun Sep 21 03:32:27 2008
@@ -1,6 +1,6 @@
from things.options import ModelThing, BaseThing
from things.sites import ThingSite, site
-from things.fields import OrderField
+from things.fields import OrderField, OrderCountField
def autodiscover():
"""
Modified: trunk/things/fields.py
==============================================================================
--- trunk/things/fields.py (original)
+++ trunk/things/fields.py Sun Sep 21 03:32:27 2008
@@ -1,5 +1,8 @@
from django.template import defaultfilters
from django.core.urlresolvers import reverse
+from django.db.models import ManyToManyField
+from django.db.models.options import FieldDoesNotExist
+from django.db import connection
__all__ = ('OrderField', )
@@ -14,6 +17,7 @@
class OrderField(BaseField):
parent = None
field_name = None
+ modifies_query_set = False
def __init__(self, verbose_name_asc=None, verbose_name_desc=None,
url_asc=None, url_desc=None, field_url=None):
@@ -74,4 +78,46 @@
self.parent.name_prefix, self.field_url),
kwargs={
'url_prefix': self.parent.url_prefix,
- })
\ No newline at end of file
+ })
+
+class OrderCountField(OrderField):
+ modifies_query_set = True
+
+ def _get_aggregate_name(self):
+ return '%s_count' % self.field_name
+ aggregate_name = property(_get_aggregate_name)
+
+ def modify_query_set(self, qs):
+ qn = connection.ops.quote_name
+ try:
+ parent_field = self.parent.opts.get_field(self.field_name)
+ m2m = True
+ except FieldDoesNotExist:
+ m2m = False
+ self_table = qn(self.parent.opts.db_table)
+ if m2m:
+ related_table = qn(parent_field.m2m_db_table())
+ related_column_name = qn(parent_field.m2m_column_name())
+ else:
+ # Need to instantiate the model, since we can't access
RelatedManager
+ # instances unless it's through an instance instead of a class.
+ dummy_stupid = self.parent.model()
+ related_manager = getattr(dummy_stupid, self.field_name)
+ related_table = related_manager.model._meta.db_table
+ children = related_manager.all().query.where.children
+ related_column_name = None
+ for child in children:
+ if child[0] == related_table:
+ related_column_name = child[1]
+ break
+ if related_column_name is None:
+ raise ValueError("Could not determine relationship on
related name %s" % self.field_name)
+ related_table = qn(related_table)
+ related_column_name = qn(related_column_name)
+
+ SQL = """
+ SELECT COUNT(*)
+ FROM %(related_table)s
+ WHERE %(related_table)s.%(related_column_name)s = %(self_table)s.id
+ """ % locals()
+ return qs.extra(select={self.aggregate_name: SQL})
\ No newline at end of file
Modified: trunk/things/options.py
==============================================================================
--- trunk/things/options.py (original)
+++ trunk/things/options.py Sun Sep 21 03:32:27 2008
@@ -7,7 +7,7 @@
from django.template.loader import select_template
from django.core.urlresolvers import reverse
from django.db.models import Q
-from things.fields import BaseField
+from things.fields import BaseField, OrderCountField
DETAIL_RE = re.compile('^(\d+)/$')
@@ -59,7 +59,10 @@
pre = ''
if descending == True:
pre = '-'
- items = items.order_by('%s%s' % (pre, field.field_name))
+ if isinstance(field, OrderCountField):
+ items = items.order_by('%s%s' % (pre,
field.aggregate_name))
+ else:
+ items = items.order_by('%s%s' % (pre, field.field_name))
templates = ['%s/%s' % (self.template_dir, template_name,),
'%s/list.html' % self.template_dir, 'things/list.html']
t = select_template(templates)
@@ -129,13 +132,15 @@
return patterns('', *tmp_urls)
def get_query_set(self):
- raise NotImplementedError
+ query_set = self.model._default_manager.all()
+ for field_name, field in self.fields.iteritems():
+ if field.modifies_query_set:
+ query_set = field.modify_query_set(query_set)
+ return query_set
class ModelThing(BaseThing):
def __init__(self, model):
self.model = model
self.opts = model._meta
super(ModelThing, self).__init__()
-
- def get_query_set(self):
- return self.model._default_manager.all()
\ No newline at end of file
+
\ No newline at end of file
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"pinax-updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/pinax-updates?hl=en
-~----------~----~----~----~------~----~------~--~---