From f713632fdd60e058a30e944e6e878a0dff6b01e1 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 24 Nov 2025 11:02:51 +0000 Subject: [PATCH] Refactor Condition, Finding, and Structure tables: remove legacy `primary` field from displayed fields to streamline data representation. --- atlas/models.py | 71 ++++++++++++++++++++++++++++++++++++------------- atlas/tables.py | 6 ++--- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/atlas/models.py b/atlas/models.py index 0bd4eebd..3676456f 100644 --- a/atlas/models.py +++ b/atlas/models.py @@ -110,13 +110,24 @@ class SynMixin(object): # abstract = True def __str__(self) -> str: - # Use getattr to avoid AttributeError if the model no longer - # defines `primary` (we are migrating some models away from the - # old primary/synonym fields). - if getattr(self, "primary", False): - return self.name - else: - return f"{self.name} [syn]" + # Determine whether this record should be displayed as the + # canonical/primary entry. Prefer the new canonical FK pattern + # (`canonical is None` means this object is the master). Fallback + # to legacy `primary` boolean when present. + # If the model supports canonical FK, consider canonical==None as + # the primary/master entry. For models without canonical (legacy + # edge-cases), treat the instance as primary by default. + if hasattr(self, "canonical"): + try: + if self.canonical is None or self.canonical == self: + return self.name + return f"{self.name} [syn]" + except Exception: + # defensive fallback + return f"{self.name} [syn]" + + # No canonical support: assume primary + return self.name def get_old_str(self) -> str: # Prefer using a model-specific get_synonyms (e.g. Condition.get_synonyms) @@ -124,9 +135,18 @@ class SynMixin(object): syns = self.get_synonyms() except Exception: syns = None + # If the model supports canonical, only canonical==None entries + # should be rendered as the primary name. For models without + # canonical, treat instance as primary. + if hasattr(self, "canonical"): + try: + is_primary = self.canonical is None or self.canonical == self + except Exception: + is_primary = False + else: + is_primary = True - # Use getattr for safety when models no longer have `primary`. - if getattr(self, "primary", False): + if is_primary: if syns is None: synonyms_field = getattr(self, "synonym", None) if synonyms_field is None or (hasattr(synonyms_field, "count") and synonyms_field.count() == 0): @@ -138,8 +158,8 @@ class SynMixin(object): return self.name synonyms = ",".join([i.name for i in syns]) return f"{self.name} ({synonyms})" - else: - return f"{self.name} [syn]" + + return f"{self.name} [syn]" def get_synonym(self): # Return a readable synonym string. For models that implement @@ -148,8 +168,13 @@ class SynMixin(object): syns = self.get_synonyms() except Exception: syns = None - if getattr(self, "primary", False): - return "[Primary]" + # If canonical is present and this instance is the master, mark Primary + if hasattr(self, "canonical"): + try: + if self.canonical is None or self.canonical == self: + return "[Primary]" + except Exception: + pass if syns is None: synonyms_field = getattr(self, "synonym", None) @@ -158,13 +183,18 @@ class SynMixin(object): # If the old M2M exists, prefer those marked primary if such a # attribute exists on the related objects. try: - s = synonyms_field.filter(primary=True).values_list("name", flat=True) - except Exception: + # Select all synonym names; legacy `primary` flag removed. s = synonyms_field.values_list("name", flat=True) + except Exception: + s = [] return ", ".join(s) # prefer primary names among synonyms if present - primary_names = [i.name for i in syns if getattr(i, "primary", False)] + primary_names = [] + for i in syns: + # Prefer items that are canonical/master in the group + if getattr(i, "canonical", None) is None: + primary_names.append(i.name) if primary_names: return ", ".join(primary_names) return ", ".join([i.name for i in syns]) @@ -174,8 +204,13 @@ class SynMixin(object): syns = self.get_synonyms() except Exception: syns = None - if getattr(self, "primary", False): - return "[Primary]" + # Prefer canonical/master check + if hasattr(self, "canonical"): + try: + if self.canonical is None or self.canonical == self: + return "[Primary]" + except Exception: + pass if syns is None: # fall back to all M2M synonyms (not just primary) for models diff --git a/atlas/tables.py b/atlas/tables.py index 60eabac8..333c64ed 100755 --- a/atlas/tables.py +++ b/atlas/tables.py @@ -276,7 +276,7 @@ class ConditionTable(SelectionTable): class Meta(SelectionTable.Meta): model = Condition template_name = "django_tables2/bootstrap4.html" - fields = ("primary", "subspecialty", "rcr_curriculum_map", "rcr_curriculum") + fields = ("subspecialty", "rcr_curriculum_map", "rcr_curriculum") sequence = ("name",) @@ -312,7 +312,7 @@ class FindingTable(SelectionTable): class Meta(SelectionTable.Meta): model = Finding template_name = "django_tables2/bootstrap4.html" - fields = ("name", "primary") + fields = ("name",) sequence = ("name",) @@ -339,7 +339,7 @@ class StructureTable(SelectionTable): class Meta(SelectionTable.Meta): model = Structure template_name = "django_tables2/bootstrap4.html" - fields = ("name", "primary") + fields = ("name",) sequence = ("name",)