From 06c3ef658368d5cf6d5a776adaaa95a71035fd74 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 6 Jul 2019 04:09:44 -0400 Subject: [PATCH] Add source column inheritance and exclusions Signed-off-by: Roberto Rosario --- HISTORY.rst | 2 + docs/releases/3.3.rst | 2 + mayan/apps/navigation/classes.py | 91 ++++++++++++++++++++------------ 3 files changed, 61 insertions(+), 34 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 8ea2bef805..0fb21226a7 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -6,6 +6,8 @@ - Use Select2 widget for the document type selection form. - Backport the vertical main menu update. - Backport workflow preview refactor. GitLab issue #532. +- Add support for source column inheritance. +- Add support for source column exclusion. 3.2.5 (2019-07-05) ================== diff --git a/docs/releases/3.3.rst b/docs/releases/3.3.rst index 9edd482f8b..980763c0a0 100644 --- a/docs/releases/3.3.rst +++ b/docs/releases/3.3.rst @@ -18,6 +18,8 @@ Changes a browser refresh will also restore its state to match the selected view. - Backport workflow preview refactor. GitLab issue #532. +- Add support for source column inheritance. +- Add support for source column exclusion. Removals -------- diff --git a/mayan/apps/navigation/classes.py b/mayan/apps/navigation/classes.py index 1cc9b1c3af..a070bafa27 100644 --- a/mayan/apps/navigation/classes.py +++ b/mayan/apps/navigation/classes.py @@ -577,44 +577,63 @@ class SourceColumn(object): @classmethod def get_for_source(cls, context, source, exclude_identifier=False, only_identifier=False): + columns = [] + + source_classes = set() + + if hasattr(source, '_meta'): + source_classes.add(source._meta.model) + else: + source_classes.add(source) + try: - result = cls._registry[source] + columns.extend(cls._registry[source]) + except KeyError: + pass + + try: + # Might be an instance, try its class + columns.extend(cls._registry[source.__class__]) except KeyError: try: - # Might be an instance, try its class - result = cls._registry[source.__class__] + # Might be a subclass, try its root class + columns.extend(cls._registry[source.__class__.__mro__[-2]]) except KeyError: - try: - # Might be a subclass, try its root class - result = cls._registry[source.__class__.__mro__[-2]] - except KeyError: - try: - # Might be an inherited class insance, try its source class - result = cls._registry[source.source_ptr.__class__] - except (KeyError, AttributeError): - try: - # Try it as a queryset - result = cls._registry[source.model] - except AttributeError: - try: - # Special case for queryset items produced from - # .defer() or .only() optimizations - result = cls._registry[list(source._meta.parents.items())[0][0]] - except (AttributeError, KeyError, IndexError): - result = () - except TypeError: - # unhashable type: list - result = () + pass - result = SourceColumn.sort(columns=result) + try: + # Might be an inherited class instance, try its source class + columns.extend(cls._registry[source.source_ptr.__class__]) + except (KeyError, AttributeError): + pass + + try: + # Try it as a queryset + columns.extend(cls._registry[source.model]) + except AttributeError: + try: + # Special case for queryset items produced from + # .defer() or .only() optimizations + result = cls._registry[list(source._meta.parents.items())[0][0]] + except (AttributeError, KeyError, IndexError): + pass + else: + # Second level special case for model subclasses from + # .defer and .only querysets + # Examples: Workflow runtime proxy and index instances in 3.2.x + for column in result: + if not source_classes.intersection(set(column.exclude)): + columns.append(column) + + columns = SourceColumn.sort(columns=columns) if exclude_identifier: - result = [item for item in result if not item.is_identifier] + columns = [column for column in columns if not column.is_identifier] else: if only_identifier: - for item in result: - if item.is_identifier: - return item + for column in columns: + if column.is_identifier: + return column return None final_result = [] @@ -635,12 +654,12 @@ class SourceColumn(object): return result current_view_name = get_current_view_name(request=request) - for item in result: - if item.views: - if current_view_name in item.views: - final_result.append(item) + for column in columns: + if column.views: + if current_view_name in column.views: + final_result.append(column) else: - final_result.append(item) + final_result.append(column) return final_result @@ -655,6 +674,7 @@ class SourceColumn(object): self._label = label self.attribute = attribute self.empty_value = empty_value + self.exclude = () self.func = func self.is_attribute_absolute_url = is_attribute_absolute_url self.is_object_absolute_url = is_object_absolute_url @@ -697,6 +717,9 @@ class SourceColumn(object): self.label = self._label + def add_exclude(self, source): + self.exclude = self.exclude + (source,) + def get_absolute_url(self, obj): if self.is_object_absolute_url: return obj.get_absolute_url()