diff --git a/CHANGELOG b/CHANGELOG index 44092915c0..82992ac1bd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +* Allow empty order clause +* Change editable tree attribute into boolean +* Send default order to clients * Replace advisory lock by SKIP LOCKED in queue pulling * Load WSGI middleware from configuration * Add help text to Dict keys diff --git a/doc/ref/models/models.rst b/doc/ref/models/models.rst index d06740ce30..fae92da415 100644 --- a/doc/ref/models/models.rst +++ b/doc/ref/models/models.rst @@ -443,10 +443,10 @@ Class methods: [ ('field name', 'ASC'), ('other field name', 'DESC'), ... ] The first element of the tuple is a field name of the model and the second - is the sort ordering as `ASC` for ascending or `DESC` for descending. This - second element may contain 'NULLS FIRST' or 'NULLS LAST' to sort null - values before or after non-null values. If neither is specified the default - behavior of the backend is used. + is the sort ordering as `ASC` for ascending, `DESC` for descending or empty + for a default order. This second element may contain 'NULLS FIRST' or + 'NULLS LAST' to sort null values before or after non-null values. If + neither is specified the default behavior of the backend is used. In case the field used is a :class:`fields.Many2One`, it is also possible to use the dotted notation to sort on a specific field from the target diff --git a/doc/topics/views/index.rst b/doc/topics/views/index.rst index cb04df8d82..9fb40e14c2 100644 --- a/doc/topics/views/index.rst +++ b/doc/topics/views/index.rst @@ -519,9 +519,7 @@ Each tree view must start with this tag. * ``on_write``: see form-attributes-on_write_. - * ``editable``: If it is set to ``top`` or ``bottom``, the list becomes - editable and the new record will be added on ``top`` or ``bottom`` of the - list. + * ``editable``: A boolean to specify if the list is editable. * ``sequence``: The name of the field that is used for sorting. This field must be an integer and it will be updated to match the new sort order diff --git a/trytond/ir/action.py b/trytond/ir/action.py index c9ca2ebcba..ca7b1dc1ec 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -10,6 +10,7 @@ from sql import Null from trytond.config import config from trytond.i18n import gettext from trytond.model.exceptions import ValidationError +from trytond.pyson import PYSONEncoder from ..model import ( ModelView, ModelStorage, ModelSQL, DeactivableMixin, fields, sequence_ordered) @@ -880,6 +881,8 @@ class ActionActWindow(ActionMixin, ModelSQL, ModelView): @classmethod def get_pyson(cls, windows, name): + pool = Pool() + encoder = PYSONEncoder() pysons = {} field = name[6:] defaults = { @@ -888,6 +891,12 @@ class ActionActWindow(ActionMixin, ModelSQL, ModelView): 'search_value': '[]', } for window in windows: + if not window.order and field == 'order': + if window.res_model: + defaults['order'] = encoder.encode( + getattr(pool.get(window.res_model), '_order', 'null')) + else: + defaults['order'] = 'null' pysons[window.id] = (getattr(window, field) or defaults.get(field, 'null')) return pysons diff --git a/trytond/ir/attachment.py b/trytond/ir/attachment.py index c9f92a100c..5aa85afdf6 100644 --- a/trytond/ir/attachment.py +++ b/trytond/ir/attachment.py @@ -54,7 +54,10 @@ class Attachment(ResourceMixin, ModelSQL, ModelView): @classmethod def __setup__(cls): super().__setup__() - cls._order.insert(0, ('create_date', 'DESC')) + cls._order = [ + ('create_date', 'DESC'), + ('id', 'DESC'), + ] @classmethod def __register__(cls, module_name): diff --git a/trytond/ir/ui/tree.rnc b/trytond/ir/ui/tree.rnc index b694f5f4cd..ba8c4f7134 100644 --- a/trytond/ir/ui/tree.rnc +++ b/trytond/ir/ui/tree.rnc @@ -5,7 +5,7 @@ tree = element tree { attlist.tree, | button)* } attlist.tree &= attribute on_write { text }? -attlist.tree &= attribute editable { "top" | "bottom" }? +attlist.tree &= attribute editable { "0" | "1" }? attlist.tree &= attribute sequence { text }? attlist.tree &= [ a:defaultValue = "0" ] attribute keyword_open { "0" | "1" }? diff --git a/trytond/ir/ui/tree.rng b/trytond/ir/ui/tree.rng index 0c5651fc08..5938647a92 100644 --- a/trytond/ir/ui/tree.rng +++ b/trytond/ir/ui/tree.rng @@ -27,8 +27,8 @@ editable - top - bottom + 0 + 1 diff --git a/trytond/ir/view/attachment_list.xml b/trytond/ir/view/attachment_list.xml index 4759271b97..cf5b577b80 100644 --- a/trytond/ir/view/attachment_list.xml +++ b/trytond/ir/view/attachment_list.xml @@ -1,7 +1,7 @@ - + diff --git a/trytond/ir/view/lang_list.xml b/trytond/ir/view/lang_list.xml index b50df81d07..2d06b1d064 100644 --- a/trytond/ir/view/lang_list.xml +++ b/trytond/ir/view/lang_list.xml @@ -1,7 +1,7 @@ - + diff --git a/trytond/ir/view/module_config_wizard_item_list.xml b/trytond/ir/view/module_config_wizard_item_list.xml index 51bfa46f7f..874988591c 100644 --- a/trytond/ir/view/module_config_wizard_item_list.xml +++ b/trytond/ir/view/module_config_wizard_item_list.xml @@ -1,7 +1,7 @@ - + diff --git a/trytond/ir/view/translation_list.xml b/trytond/ir/view/translation_list.xml index 9b5df31a33..0bbe31da57 100644 --- a/trytond/ir/view/translation_list.xml +++ b/trytond/ir/view/translation_list.xml @@ -1,7 +1,7 @@ - + diff --git a/trytond/model/fields/many2many.py b/trytond/model/fields/many2many.py index 0c68be0d4a..0191cc2175 100644 --- a/trytond/model/fields/many2many.py +++ b/trytond/model/fields/many2many.py @@ -455,6 +455,9 @@ class Many2Many(Field): definition['search_context'] = encoder.encode(self.search_context) definition['search_order'] = encoder.encode(self.search_order) definition['sortable'] &= hasattr(model, 'order_' + self.name) + definition['order'] = encoder.encode( + getattr(model, '_order', None) + if self.order is None else self.order) if self.size is not None: definition['size'] = encoder.encode(self.size) return definition diff --git a/trytond/model/fields/one2many.py b/trytond/model/fields/one2many.py index 660c391547..ff64418c84 100644 --- a/trytond/model/fields/one2many.py +++ b/trytond/model/fields/one2many.py @@ -352,4 +352,7 @@ class One2Many(Field): if self.size is not None: definition['size'] = encoder.encode(self.size) definition['sortable'] &= hasattr(model, 'order_' + self.name) + definition['order'] = encoder.encode( + getattr(model, '_order', None) + if self.order is None else self.order) return definition diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 13c0c41e77..13428154cb 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -188,7 +188,7 @@ class ModelSQL(ModelStorage): cls._sql_constraints.append( ('id_positive', Check(table, table.id >= 0), 'ir.msg_id_positive')) - cls._order = [('id', 'ASC')] + cls._order = [('id', None)] if issubclass(cls, ModelView): cls.__rpc__.update({ 'history_revisions': RPC(), @@ -1256,11 +1256,14 @@ class ModelSQL(ModelStorage): for oexpr, otype in order: fname, _, extra_expr = oexpr.partition('.') field = cls._fields[fname] - otype = otype.upper() - try: - otype, null_ordering = otype.split(' ', 1) - except ValueError: - null_ordering = None + if not otype: + otype, null_ordering = 'ASC', None + else: + otype = otype.upper() + try: + otype, null_ordering = otype.split(' ', 1) + except ValueError: + null_ordering = None Order = order_types[otype] NullOrdering = null_ordering_types[null_ordering] forder = field.convert_order(oexpr, tables, cls)