30 from rql.stmts import Select |
30 from rql.stmts import Select |
31 from rql.nodes import (Not, VariableRef, Constant, make_relation, |
31 from rql.nodes import (Not, VariableRef, Constant, make_relation, |
32 Relation as RqlRelation) |
32 Relation as RqlRelation) |
33 |
33 |
34 from cubicweb import Unauthorized, typed_eid, neg_role |
34 from cubicweb import Unauthorized, typed_eid, neg_role |
|
35 from cubicweb.utils import support_args |
35 from cubicweb.rset import ResultSet |
36 from cubicweb.rset import ResultSet |
36 from cubicweb.selectors import yes |
37 from cubicweb.selectors import yes |
37 from cubicweb.appobject import AppObject |
38 from cubicweb.appobject import AppObject |
38 from cubicweb.req import _check_cw_unsafe |
39 from cubicweb.req import _check_cw_unsafe |
39 from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint |
40 from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint |
138 mixins += cls.__bases__[1:] |
139 mixins += cls.__bases__[1:] |
139 cls.__bases__ = tuple(mixins) |
140 cls.__bases__ = tuple(mixins) |
140 cls.info('plugged %s mixins on %s', mixins, cls) |
141 cls.info('plugged %s mixins on %s', mixins, cls) |
141 |
142 |
142 fetch_attrs = ('modification_date',) |
143 fetch_attrs = ('modification_date',) |
|
144 |
143 @classmethod |
145 @classmethod |
144 def fetch_order(cls, attr, var): |
146 def cw_fetch_order(cls, select, attr, var): |
145 """class method used to control sort order when multiple entities of |
147 """This class method may be used to control sort order when multiple |
146 this type are fetched |
148 entities of this type are fetched through ORM methods. Its arguments |
147 """ |
149 are: |
148 return cls.fetch_unrelated_order(attr, var) |
150 |
|
151 * `select`, the RQL syntax tree |
|
152 |
|
153 * `attr`, the attribute being watched |
|
154 |
|
155 * `var`, the variable through which this attribute's value may be |
|
156 accessed in the query |
|
157 |
|
158 When you want to do some sorting on the given attribute, you should |
|
159 modify the syntax tree accordingly. For instance: |
|
160 |
|
161 .. sourcecode:: python |
|
162 |
|
163 from rql import nodes |
|
164 |
|
165 class Version(AnyEntity): |
|
166 __regid__ = 'Version' |
|
167 |
|
168 fetch_attrs = ('num', 'description', 'in_state') |
|
169 |
|
170 @classmethod |
|
171 def cw_fetch_order(cls, select, attr, var): |
|
172 if attr == 'num': |
|
173 func = nodes.Function('version_sort_value') |
|
174 func.append(nodes.variable_ref(var)) |
|
175 sterm = nodes.SortTerm(func, asc=False) |
|
176 select.add_sort_term(sterm) |
|
177 |
|
178 The default implementation call |
|
179 :meth:`~cubicweb.entity.Entity.cw_fetch_unrelated_order` |
|
180 """ |
|
181 cls.cw_fetch_unrelated_order(select, attr, var) |
149 |
182 |
150 @classmethod |
183 @classmethod |
151 def fetch_unrelated_order(cls, attr, var): |
184 def cw_fetch_unrelated_order(cls, select, attr, var): |
152 """class method used to control sort order when multiple entities of |
185 """This class method may be used to control sort order when multiple entities of |
153 this type are fetched to use in edition (eg propose them to create a |
186 this type are fetched to use in edition (e.g. propose them to create a |
154 new relation on an edited entity). |
187 new relation on an edited entity). |
|
188 |
|
189 See :meth:`~cubicweb.entity.Entity.cw_fetch_unrelated_order` for a |
|
190 description of its arguments and usage. |
|
191 |
|
192 By default entities will be listed on their modification date descending, |
|
193 i.e. you'll get entities recently modified first. |
155 """ |
194 """ |
156 if attr == 'modification_date': |
195 if attr == 'modification_date': |
157 return '%s DESC' % var |
196 select.add_sort_var(var, asc=False) |
158 return None |
|
159 |
197 |
160 @classmethod |
198 @classmethod |
161 def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X', |
199 def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X', |
162 settype=True, ordermethod='fetch_order'): |
200 settype=True, ordermethod='fetch_order'): |
163 st = cls.fetch_rqlst(user, mainvar=mainvar, fetchattrs=fetchattrs, |
201 st = cls.fetch_rqlst(user, mainvar=mainvar, fetchattrs=fetchattrs, |
274 else: |
312 else: |
275 fetchattrs = etypecls.fetch_attrs |
313 fetchattrs = etypecls.fetch_attrs |
276 etypecls._fetch_restrictions(var, select, fetchattrs, |
314 etypecls._fetch_restrictions(var, select, fetchattrs, |
277 user, ordermethod, visited=visited) |
315 user, ordermethod, visited=visited) |
278 if ordermethod is not None: |
316 if ordermethod is not None: |
279 orderterm = getattr(cls, ordermethod)(attr, var.name) |
317 try: |
280 if orderterm: |
318 cmeth = getattr(cls, ordermethod) |
281 var, order = orderterm.split() |
319 warn('[3.14] %s %s class method should be renamed to cw_%s' |
282 select.add_sort_var(select.get_variable(var), order=='ASC') |
320 % (cls.__regid__, ordermethod, ordermethod), |
|
321 DeprecationWarning) |
|
322 except AttributeError: |
|
323 cmeth = getattr(cls, 'cw_' + ordermethod) |
|
324 if support_args(cmeth, 'select'): |
|
325 cmeth(select, attr, var) |
|
326 else: |
|
327 warn('[3.14] %s should now take (select, attr, var) and ' |
|
328 'modify the syntax tree when desired instead of ' |
|
329 'returning something' % cmeth, DeprecationWarning) |
|
330 orderterm = cmeth(attr, var.name) |
|
331 if orderterm is not None: |
|
332 try: |
|
333 var, order = orderterm.split() |
|
334 except ValueError: |
|
335 if '(' in orderterm: |
|
336 self.error('ignore %s until %s is upgraded', |
|
337 orderterm, cmeth) |
|
338 orderterm = None |
|
339 elif not ' ' in orderterm.strip(): |
|
340 var = orderterm |
|
341 order = 'ASC' |
|
342 if orderterm is not None: |
|
343 select.add_sort_var(select.get_variable(var), |
|
344 order=='ASC') |
283 |
345 |
284 @classmethod |
346 @classmethod |
285 @cached |
347 @cached |
286 def _rest_attr_info(cls): |
348 def _rest_attr_info(cls): |
287 mainattr, needcheck = 'eid', True |
349 mainattr, needcheck = 'eid', True |