From 44b5f68c24b647bfd7972eb59c7b89bbcfde5c07 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sat, 29 Aug 2026 11:50:52 +0330 Subject: [PATCH] fix(transmitters): add slug and legacy_id to search and prevent empty string unique collision on legacy_id --- apps/hadis/models/transmitter.py | 7 +++++++ apps/hadis/serializers/serializers_admin.py | 14 +++++++++++--- apps/hadis/views/transmitter.py | 11 ++++++++--- apps/hadis/views_admin.py | 2 ++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/apps/hadis/models/transmitter.py b/apps/hadis/models/transmitter.py index 09e2062..cf8b06a 100644 --- a/apps/hadis/models/transmitter.py +++ b/apps/hadis/models/transmitter.py @@ -256,6 +256,13 @@ class Transmitters(LowercaseSlugMixin, models.Model): verbose_name_plural = _('Transmitters') ordering = ('full_name',) + def save(self, *args, **kwargs): + if not self.legacy_id or (isinstance(self.legacy_id, str) and not self.legacy_id.strip()): + self.legacy_id = None + if not self.legacy_number: + self.legacy_number = None + super().save(*args, **kwargs) + @property def share_link(self): if self.slug: diff --git a/apps/hadis/serializers/serializers_admin.py b/apps/hadis/serializers/serializers_admin.py index 143abbc..c4e4d80 100644 --- a/apps/hadis/serializers/serializers_admin.py +++ b/apps/hadis/serializers/serializers_admin.py @@ -931,9 +931,17 @@ class AdminTransmitterDetailSerializer(serializers.ModelSerializer): except ValueError: pass - # Handle empty/null values for optional integer fields - for field in ["legacy_number", "age_at_death", "generation"]: - if field in data and (data[field] == "" or data[field] is None or data[field] == "null" or data[field] == "undefined"): + # Handle empty/null values for optional fields (prevent unique constraint violations on empty strings) + for field in [ + "legacy_id", + "legacy_number", + "age_at_death", + "generation", + "birth_year_hijri", + "death_year_hijri", + "companion_type", + ]: + if field in data and (data[field] == "" or data[field] is None or data[field] == "null" or data[field] == "undefined" or (isinstance(data[field], str) and not data[field].strip())): data[field] = None return super().to_internal_value(data) diff --git a/apps/hadis/views/transmitter.py b/apps/hadis/views/transmitter.py index cb55d29..415f3d8 100644 --- a/apps/hadis/views/transmitter.py +++ b/apps/hadis/views/transmitter.py @@ -40,14 +40,19 @@ class TransmitterView(ListAPIView): madhhab_filter = self.request.query_params.get('madhhab', None) generation_filter = self.request.query_params.get('generation', None) - # 1. Apply search filter (Searching across name-related JSONFields) + # 1. Apply search filter (Searching across name-related JSONFields, slug, legacy_id) if search_query: - queryset = queryset.filter( + q_filter = ( Q(full_name__icontains=search_query) | Q(kunya__icontains=search_query) | Q(known_as__icontains=search_query) | - Q(nickname__icontains=search_query) + Q(nickname__icontains=search_query) | + Q(slug__icontains=search_query) | + Q(legacy_id__icontains=search_query) ) + if search_query.isdigit(): + q_filter |= Q(legacy_number=int(search_query)) | Q(generation=int(search_query)) + queryset = queryset.filter(q_filter) # 2. Apply categorical filters if status_filter: diff --git a/apps/hadis/views_admin.py b/apps/hadis/views_admin.py index e7bddcf..fb85148 100644 --- a/apps/hadis/views_admin.py +++ b/apps/hadis/views_admin.py @@ -281,6 +281,8 @@ class AdminTransmitterViewSet(ModelViewSet): | Q(origin__icontains=search_query) | Q(lived_in__icontains=search_query) | Q(died_in__icontains=search_query) + | Q(slug__icontains=search_query) + | Q(legacy_id__icontains=search_query) ) if search_query.isdigit(): q_filter |= Q(legacy_number=int(search_query)) | Q(generation=int(search_query))