--- a/entity.py Thu Sep 22 09:56:20 2011 +0200
+++ b/entity.py Thu Sep 22 16:12:23 2011 +0200
@@ -32,6 +32,7 @@
Relation as RqlRelation)
from cubicweb import Unauthorized, typed_eid, neg_role
+from cubicweb.utils import support_args
from cubicweb.rset import ResultSet
from cubicweb.selectors import yes
from cubicweb.appobject import AppObject
@@ -140,22 +141,59 @@
cls.info('plugged %s mixins on %s', mixins, cls)
fetch_attrs = ('modification_date',)
- @classmethod
- def fetch_order(cls, attr, var):
- """class method used to control sort order when multiple entities of
- this type are fetched
- """
- return cls.fetch_unrelated_order(attr, var)
@classmethod
- def fetch_unrelated_order(cls, attr, var):
- """class method used to control sort order when multiple entities of
- this type are fetched to use in edition (eg propose them to create a
+ def cw_fetch_order(cls, select, attr, var):
+ """This class method may be used to control sort order when multiple
+ entities of this type are fetched through ORM methods. Its arguments
+ are:
+
+ * `select`, the RQL syntax tree
+
+ * `attr`, the attribute being watched
+
+ * `var`, the variable through which this attribute's value may be
+ accessed in the query
+
+ When you want to do some sorting on the given attribute, you should
+ modify the syntax tree accordingly. For instance:
+
+ .. sourcecode:: python
+
+ from rql import nodes
+
+ class Version(AnyEntity):
+ __regid__ = 'Version'
+
+ fetch_attrs = ('num', 'description', 'in_state')
+
+ @classmethod
+ def cw_fetch_order(cls, select, attr, var):
+ if attr == 'num':
+ func = nodes.Function('version_sort_value')
+ func.append(nodes.variable_ref(var))
+ sterm = nodes.SortTerm(func, asc=False)
+ select.add_sort_term(sterm)
+
+ The default implementation call
+ :meth:`~cubicweb.entity.Entity.cw_fetch_unrelated_order`
+ """
+ cls.cw_fetch_unrelated_order(select, attr, var)
+
+ @classmethod
+ def cw_fetch_unrelated_order(cls, select, attr, var):
+ """This class method may be used to control sort order when multiple entities of
+ this type are fetched to use in edition (e.g. propose them to create a
new relation on an edited entity).
+
+ See :meth:`~cubicweb.entity.Entity.cw_fetch_unrelated_order` for a
+ description of its arguments and usage.
+
+ By default entities will be listed on their modification date descending,
+ i.e. you'll get entities recently modified first.
"""
if attr == 'modification_date':
- return '%s DESC' % var
- return None
+ select.add_sort_var(var, asc=False)
@classmethod
def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
@@ -276,10 +314,34 @@
etypecls._fetch_restrictions(var, select, fetchattrs,
user, ordermethod, visited=visited)
if ordermethod is not None:
- orderterm = getattr(cls, ordermethod)(attr, var.name)
- if orderterm:
- var, order = orderterm.split()
- select.add_sort_var(select.get_variable(var), order=='ASC')
+ try:
+ cmeth = getattr(cls, ordermethod)
+ warn('[3.14] %s %s class method should be renamed to cw_%s'
+ % (cls.__regid__, ordermethod, ordermethod),
+ DeprecationWarning)
+ except AttributeError:
+ cmeth = getattr(cls, 'cw_' + ordermethod)
+ if support_args(cmeth, 'select'):
+ cmeth(select, attr, var)
+ else:
+ warn('[3.14] %s should now take (select, attr, var) and '
+ 'modify the syntax tree when desired instead of '
+ 'returning something' % cmeth, DeprecationWarning)
+ orderterm = cmeth(attr, var.name)
+ if orderterm is not None:
+ try:
+ var, order = orderterm.split()
+ except ValueError:
+ if '(' in orderterm:
+ self.error('ignore %s until %s is upgraded',
+ orderterm, cmeth)
+ orderterm = None
+ elif not ' ' in orderterm.strip():
+ var = orderterm
+ order = 'ASC'
+ if orderterm is not None:
+ select.add_sort_var(select.get_variable(var),
+ order=='ASC')
@classmethod
@cached