diff --git a/apps/account/admin/location.py b/apps/account/admin/location.py
index 2b48d05..b25196d 100644
--- a/apps/account/admin/location.py
+++ b/apps/account/admin/location.py
@@ -26,6 +26,7 @@ class LocationHistoryInline(TabularInline):
class LocationHistoryAdmin(ModelAdmin):
list_display = ('user', 'display_location', 'country', 'city', 'selected_manually', 'ip', 'display_at_time')
+ list_display_links = ('user', 'display_location', 'country', 'city')
list_filter = [
('user', AutocompleteSelectFilter),
'country',
diff --git a/apps/account/admin/login_history.py b/apps/account/admin/login_history.py
index 0c57e2d..2ae576f 100644
--- a/apps/account/admin/login_history.py
+++ b/apps/account/admin/login_history.py
@@ -11,6 +11,7 @@ from utils.admin import project_admin_site
@admin.register(LoginHistory, site=project_admin_site)
class LoginHistoryAdmin(ModelAdmin):
list_display = ('user', 'ip', 'country', 'city', 'device_os', 'display_at_time')
+ list_display_links = ('user', 'ip', 'display_at_time')
list_filter = [
('user', AutocompleteSelectFilter),
'device_os',
diff --git a/apps/account/admin/notification.py b/apps/account/admin/notification.py
index cab1fc6..3870ded 100644
--- a/apps/account/admin/notification.py
+++ b/apps/account/admin/notification.py
@@ -9,6 +9,7 @@ from apps.account.models import User, Notification, NotificationTemplate
@admin.register(Notification, site=project_admin_site)
class NotificationAdmin(ModelAdmin):
list_display = ('title', 'user', 'notification_type', 'is_read', 'created_at')
+ list_display_links = ('title', 'user')
list_filter = ('is_read', 'notification_type', 'created_at')
search_fields = ('title', 'message', 'user__fullname', 'user__email')
list_editable = ('is_read',)
@@ -19,6 +20,7 @@ class NotificationAdmin(ModelAdmin):
@admin.register(NotificationTemplate, site=project_admin_site)
class NotificationTemplateAdmin(ModelAdmin):
list_display = ('name', 'notification_type', 'title', 'is_active')
+ list_display_links = ('name', 'title')
list_filter = ('is_active',)
search_fields = ('name', 'notification_type', 'title', 'body')
list_editable = ('is_active',)
diff --git a/apps/account/admin/role.py b/apps/account/admin/role.py
index 401c729..aa8036a 100644
--- a/apps/account/admin/role.py
+++ b/apps/account/admin/role.py
@@ -9,6 +9,7 @@ from utils.admin import project_admin_site
class RoleAdmin(ModelAdmin):
list_display = ('name', 'slug', 'is_default', 'is_system', 'users_count', 'updated_at')
+ list_display_links = ('name', 'slug')
list_filter = ('is_default', 'is_system')
search_fields = ('name', 'slug', 'description')
ordering = ('name',)
diff --git a/apps/account/admin/user.py b/apps/account/admin/user.py
index 510dfc8..198d569 100644
--- a/apps/account/admin/user.py
+++ b/apps/account/admin/user.py
@@ -56,8 +56,10 @@ class UserAdmin(ModelAdmin, BaseUserAdmin):
change_password_form = AdminPasswordChangeForm
compressed_fields = False
list_display = ('first_name', 'last_name', 'fullname', 'email', 'role', 'user_type', 'is_staff', 'is_active', 'display_date_joined',)
+ list_display_links = ('first_name', 'last_name', 'fullname', 'email')
ordering = ("-id",)
search_fields = ('email', 'first_name', 'last_name', 'fullname', 'username',)
+ filter_horizontal = ('groups', 'user_permissions')
list_filter = [
"role",
"user_type",
@@ -114,7 +116,8 @@ class UserAdmin(ModelAdmin, BaseUserAdmin):
"fields": (
("role", "user_type"),
("is_active", "is_staff", "is_superuser"),
- ("groups", "user_permissions"),
+ "groups",
+ "user_permissions",
),
}),
(_("Custom Permissions"), {
@@ -142,6 +145,7 @@ class UserAdmin(ModelAdmin, BaseUserAdmin):
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
list_display = ('name', 'permissions_count')
+ list_display_links = ('name',)
search_fields = ('name',)
ordering = ('name',)
filter_horizontal = ('permissions',)
diff --git a/apps/api/admin.py b/apps/api/admin.py
index 8dfacf5..fe55e02 100644
--- a/apps/api/admin.py
+++ b/apps/api/admin.py
@@ -10,6 +10,7 @@ from utils.admin import project_admin_site
@admin.register(AppVersion)
class AppVersionAdmin(ModelAdmin):
list_display = ['version', 'app_type', 'is_active', 'downloads_count', 'created_at']
+ list_display_links = ['version', 'app_type']
list_filter = ['app_type', 'is_active']
search_fields = ['version', 'description']
ordering = ['-created_at']
@@ -18,6 +19,7 @@ class AppVersionAdmin(ModelAdmin):
@admin.register(SupportMessage)
class SupportMessageAdmin(ModelAdmin):
list_display = ['sender_name', 'sender_email', 'subject', 'is_resolved', 'created_at']
+ list_display_links = ['sender_name', 'sender_email', 'subject']
list_filter = ['is_resolved', 'created_at']
search_fields = ['sender_name', 'sender_email', 'subject', 'message']
ordering = ['-created_at']
diff --git a/apps/chat/admin.py b/apps/chat/admin.py
index 198bd02..cd74efc 100644
--- a/apps/chat/admin.py
+++ b/apps/chat/admin.py
@@ -17,6 +17,7 @@ class ChatMessageInline(TabularInline):
@admin.register(ChatRoom, site=project_admin_site)
class ChatRoomAdmin(ModelAdmin):
list_display = ('id', 'title_display', 'room_type_badge', 'messages_count', 'created_at', 'updated_at')
+ list_display_links = ('id', 'title_display')
list_filter = ('room_type', 'created_at')
search_fields = ('title', 'participant_users__email', 'participant_institutions__name')
filter_horizontal = ('participant_users', 'participant_institutions')
@@ -42,6 +43,7 @@ class ChatRoomAdmin(ModelAdmin):
@admin.register(ChatMessage, site=project_admin_site)
class ChatMessageAdmin(ModelAdmin):
list_display = ('id', 'room', 'sender', 'sender_institution', 'content_preview', 'has_attachment', 'created_at')
+ list_display_links = ('id', 'room', 'sender', 'content_preview')
list_filter = ('created_at', 'sender_institution')
search_fields = ('content', 'sender__email', 'sender__fullname', 'room__title')
readonly_fields = ('created_at',)
diff --git a/apps/cms/admin.py b/apps/cms/admin.py
index 896f429..b187c6a 100644
--- a/apps/cms/admin.py
+++ b/apps/cms/admin.py
@@ -35,6 +35,7 @@ class PostAdmin(ModelAdmin):
'is_featured',
'publish_date',
)
+ list_display_links = ('title', 'post_type_badge', 'category', 'author')
list_filter = ('post_type', 'language', 'status', 'is_featured', 'category')
search_fields = ('title', 'excerpt', 'content', 'author__email', 'author__fullname')
prepopulated_fields = {'slug': ('title',)}
@@ -91,6 +92,7 @@ class PostAdmin(ModelAdmin):
@admin.register(PostCategory, site=project_admin_site)
class PostCategoryAdmin(ModelAdmin):
list_display = ('name', 'slug', 'language', 'created_at')
+ list_display_links = ('name', 'slug')
list_filter = ('language',)
search_fields = ('name', 'description')
prepopulated_fields = {'slug': ('name',)}
@@ -99,6 +101,7 @@ class PostCategoryAdmin(ModelAdmin):
@admin.register(PostTag, site=project_admin_site)
class PostTagAdmin(ModelAdmin):
list_display = ('name', 'slug')
+ list_display_links = ('name', 'slug')
search_fields = ('name',)
prepopulated_fields = {'slug': ('name',)}
@@ -106,6 +109,7 @@ class PostTagAdmin(ModelAdmin):
@admin.register(PostComment, site=project_admin_site)
class PostCommentAdmin(ModelAdmin):
list_display = ('author_display', 'post', 'status_badge', 'created_at')
+ list_display_links = ('author_display', 'post')
list_filter = ('status', 'created_at')
search_fields = ('author_name', 'author_email', 'content', 'post__title')
actions = ['approve_comments', 'mark_as_spam']
@@ -136,6 +140,7 @@ class PostCommentAdmin(ModelAdmin):
@admin.register(PostLike, site=project_admin_site)
class PostLikeAdmin(ModelAdmin):
list_display = ('user', 'post', 'created_at')
+ list_display_links = ('user', 'post')
search_fields = ('user__email', 'user__fullname', 'post__title')
readonly_fields = ('created_at',)
@@ -143,6 +148,7 @@ class PostLikeAdmin(ModelAdmin):
@admin.register(MediaAsset, site=project_admin_site)
class MediaAssetAdmin(ModelAdmin):
list_display = ('title', 'media_type', 'file_size', 'uploaded_by', 'created_at')
+ list_display_links = ('title', 'uploaded_by')
list_filter = ('media_type', 'created_at')
search_fields = ('title', 'uploaded_by__email')
readonly_fields = ('created_at',)
diff --git a/apps/diplomacy/admin.py b/apps/diplomacy/admin.py
index 08c454f..226db2b 100644
--- a/apps/diplomacy/admin.py
+++ b/apps/diplomacy/admin.py
@@ -6,6 +6,7 @@ from apps.diplomacy.models import RepresentativeReport
@admin.register(RepresentativeReport)
class RepresentativeReportAdmin(ModelAdmin):
list_display = ('title', 'representative', 'region_hub', 'period', 'centers_visited_count', 'status', 'reviewed_by', 'created_at')
+ list_display_links = ('title', 'representative', 'region_hub')
list_filter = ('status', 'region_hub', 'created_at')
search_fields = ('title', 'activities_summary', 'representative__email', 'representative__fullname', 'region_hub')
readonly_fields = ('created_at', 'updated_at')
diff --git a/apps/donations/admin.py b/apps/donations/admin.py
index 80ba094..c2d6e3e 100644
--- a/apps/donations/admin.py
+++ b/apps/donations/admin.py
@@ -13,6 +13,7 @@ class DonationTransactionInline(TabularInline):
@admin.register(DonationCampaign)
class DonationCampaignAdmin(ModelAdmin):
list_display = ('title', 'category', 'priority', 'target_amount', 'raised_amount', 'currency', 'is_active', 'is_featured', 'deadline')
+ list_display_links = ('title', 'category')
list_filter = ('category', 'priority', 'is_active', 'is_featured')
search_fields = ('title', 'description', 'organization_name', 'institution__name')
prepopulated_fields = {'slug': ('title',)}
@@ -22,6 +23,7 @@ class DonationCampaignAdmin(ModelAdmin):
@admin.register(DonationTransaction)
class DonationTransactionAdmin(ModelAdmin):
list_display = ('transaction_reference', 'campaign', 'donor_name', 'amount', 'currency', 'payment_status', 'created_at')
+ list_display_links = ('transaction_reference', 'campaign', 'donor_name')
list_filter = ('payment_status', 'currency', 'created_at')
search_fields = ('transaction_reference', 'donor_name', 'donor_email', 'campaign__title')
readonly_fields = ('transaction_reference', 'created_at')
diff --git a/apps/dynamic_forms/admin.py b/apps/dynamic_forms/admin.py
index 739c0e9..ab60b50 100644
--- a/apps/dynamic_forms/admin.py
+++ b/apps/dynamic_forms/admin.py
@@ -13,6 +13,7 @@ class FormResponseInline(TabularInline):
@admin.register(FormDefinition)
class FormDefinitionAdmin(ModelAdmin):
list_display = ('title', 'slug', 'is_active', 'is_public', 'target_role', 'created_at')
+ list_display_links = ('title', 'slug')
list_filter = ('is_active', 'is_public', 'created_at')
search_fields = ('title', 'description', 'slug')
prepopulated_fields = {'slug': ('title',)}
@@ -22,6 +23,7 @@ class FormDefinitionAdmin(ModelAdmin):
@admin.register(FormResponse)
class FormResponseAdmin(ModelAdmin):
list_display = ('form', 'user', 'workflow_status', 'reviewed_by', 'created_at')
+ list_display_links = ('form', 'user', 'workflow_status')
list_filter = ('workflow_status', 'form', 'created_at')
search_fields = ('form__title', 'user__email', 'user__fullname', 'admin_notes')
readonly_fields = ('created_at', 'updated_at')
diff --git a/apps/events/admin.py b/apps/events/admin.py
index 4452caa..f5368a6 100644
--- a/apps/events/admin.py
+++ b/apps/events/admin.py
@@ -24,6 +24,7 @@ class EventAdmin(ModelAdmin):
'is_active',
'is_featured',
)
+ list_display_links = ('title', 'organizer', 'display_category')
list_filter = ('category', 'location_type', 'is_active', 'is_featured', 'language', 'event_date')
search_fields = ('title', 'description', 'speaker_name', 'organizer__name', 'venue_address')
prepopulated_fields = {'slug': ('title',)}
@@ -71,6 +72,7 @@ class EventAdmin(ModelAdmin):
@admin.register(EventRegistration)
class EventRegistrationAdmin(ModelAdmin):
list_display = ('event', 'user', 'display_status', 'registered_at')
+ list_display_links = ('event', 'user', 'display_status')
list_filter = ('status', 'registered_at')
search_fields = ('event__title', 'user__email', 'user__fullname', 'notes')
diff --git a/apps/lms/admin.py b/apps/lms/admin.py
index 6913243..7506bcd 100644
--- a/apps/lms/admin.py
+++ b/apps/lms/admin.py
@@ -32,6 +32,7 @@ class QuizQuestionInline(StackedInline):
@admin.register(Course)
class CourseAdmin(ModelAdmin):
list_display = ('title', 'category', 'language', 'level', 'instructor_name', 'is_published', 'is_featured', 'created_at')
+ list_display_links = ('title', 'category', 'instructor_name')
list_filter = ('category', 'language', 'level', 'is_published', 'is_featured')
search_fields = ('title', 'description', 'instructor_name', 'organization_name')
prepopulated_fields = {'slug': ('title',)}
@@ -41,6 +42,7 @@ class CourseAdmin(ModelAdmin):
@admin.register(CourseModule)
class CourseModuleAdmin(ModelAdmin):
list_display = ('title', 'course', 'order', 'created_at')
+ list_display_links = ('title', 'course')
list_filter = ('course',)
search_fields = ('title', 'description', 'course__title')
inlines = [LessonInline]
@@ -49,6 +51,7 @@ class CourseModuleAdmin(ModelAdmin):
@admin.register(Lesson)
class LessonAdmin(ModelAdmin):
list_display = ('title', 'module', 'lesson_type', 'duration_minutes', 'order', 'is_preview')
+ list_display_links = ('title', 'module')
list_filter = ('lesson_type', 'is_preview', 'module__course')
search_fields = ('title', 'content', 'module__title', 'module__course__title')
inlines = [QuizQuestionInline]
@@ -57,6 +60,7 @@ class LessonAdmin(ModelAdmin):
@admin.register(QuizQuestion)
class QuizQuestionAdmin(ModelAdmin):
list_display = ('question_text', 'lesson', 'correct_option_index', 'order')
+ list_display_links = ('question_text', 'lesson')
list_filter = ('lesson__module__course',)
search_fields = ('question_text', 'explanation', 'lesson__title')
@@ -64,6 +68,7 @@ class QuizQuestionAdmin(ModelAdmin):
@admin.register(CourseEnrollment)
class CourseEnrollmentAdmin(ModelAdmin):
list_display = ('user', 'course', 'progress_percentage', 'enrolled_at', 'completed_at')
+ list_display_links = ('user', 'course')
list_filter = ('course', 'progress_percentage')
search_fields = ('user__email', 'user__fullname', 'course__title')
@@ -71,6 +76,7 @@ class CourseEnrollmentAdmin(ModelAdmin):
@admin.register(LessonProgress)
class LessonProgressAdmin(ModelAdmin):
list_display = ('user', 'lesson', 'is_completed', 'quiz_score', 'completed_at')
+ list_display_links = ('user', 'lesson')
list_filter = ('is_completed', 'lesson__module__course')
search_fields = ('user__email', 'user__fullname', 'lesson__title')
@@ -78,6 +84,7 @@ class LessonProgressAdmin(ModelAdmin):
@admin.register(DigitalCertificate)
class DigitalCertificateAdmin(ModelAdmin):
list_display = ('certificate_code', 'user', 'course', 'issue_date', 'final_score', 'is_revoked')
+ list_display_links = ('certificate_code', 'user', 'course')
list_filter = ('is_revoked', 'issue_date', 'course')
search_fields = ('certificate_code', 'user__email', 'user__fullname', 'course__title')
readonly_fields = ('uuid', 'created_at')
diff --git a/apps/meetings/admin.py b/apps/meetings/admin.py
index c55cd83..aefd8eb 100644
--- a/apps/meetings/admin.py
+++ b/apps/meetings/admin.py
@@ -17,6 +17,7 @@ class MeetingRequestAdmin(ModelAdmin):
'created_by',
'created_at',
)
+ list_display_links = ('title', 'requester_institution', 'recipient_institution', 'created_by')
list_filter = ('status', 'meeting_date', 'requester_institution', 'recipient_institution')
search_fields = (
'title',
diff --git a/apps/profiles/admin.py b/apps/profiles/admin.py
index fc3e862..f748122 100644
--- a/apps/profiles/admin.py
+++ b/apps/profiles/admin.py
@@ -46,6 +46,7 @@ class InstitutionAdmin(ModelAdmin):
'is_active',
'created_at',
)
+ list_display_links = ('name', 'type_badge', 'city', 'country')
list_filter = ('type', 'verification_status', 'is_featured', 'is_active', 'country')
search_fields = ('name', 'city', 'country', 'description', 'email', 'phone')
prepopulated_fields = {'slug': ('name',)}
@@ -107,6 +108,7 @@ class InstitutionAdmin(ModelAdmin):
@admin.register(InstitutionMember, site=project_admin_site)
class InstitutionMemberAdmin(ModelAdmin):
list_display = ('user', 'institution', 'role_badge', 'title', 'joined_at')
+ list_display_links = ('user', 'institution', 'title')
list_filter = ('role', 'joined_at')
search_fields = ('user__email', 'user__fullname', 'institution__name', 'title')
readonly_fields = ('joined_at',)
@@ -123,6 +125,7 @@ class InstitutionMemberAdmin(ModelAdmin):
@admin.register(InstitutionTimeline, site=project_admin_site)
class InstitutionTimelineAdmin(ModelAdmin):
list_display = ('institution', 'year', 'title', 'order', 'created_at')
+ list_display_links = ('institution', 'title', 'year')
search_fields = ('institution__name', 'title', 'description', 'year')
list_filter = ('created_at',)
@@ -130,6 +133,7 @@ class InstitutionTimelineAdmin(ModelAdmin):
@admin.register(InstitutionMedia, site=project_admin_site)
class InstitutionMediaAdmin(ModelAdmin):
list_display = ('institution', 'title', 'media_type', 'uploaded_at')
+ list_display_links = ('institution', 'title')
list_filter = ('media_type', 'uploaded_at')
search_fields = ('institution__name', 'title', 'caption')
@@ -137,5 +141,6 @@ class InstitutionMediaAdmin(ModelAdmin):
@admin.register(InstitutionFollower, site=project_admin_site)
class InstitutionFollowerAdmin(ModelAdmin):
list_display = ('user', 'institution', 'created_at')
+ list_display_links = ('user', 'institution')
search_fields = ('user__email', 'user__fullname', 'institution__name')
readonly_fields = ('created_at',)
diff --git a/apps/projects/admin.py b/apps/projects/admin.py
index e4f9fdc..db1a577 100644
--- a/apps/projects/admin.py
+++ b/apps/projects/admin.py
@@ -38,6 +38,7 @@ class ProjectAdmin(ModelAdmin):
'start_date',
'estimated_end_date',
)
+ list_display_links = ('title', 'owner_institution', 'category')
list_filter = ('status', 'category', 'owner_institution')
search_fields = ('title', 'description', 'owner_institution__name')
prepopulated_fields = {'slug': ('title',)}
@@ -87,6 +88,7 @@ class ProjectAdmin(ModelAdmin):
@admin.register(KanbanColumn, site=project_admin_site)
class KanbanColumnAdmin(ModelAdmin):
list_display = ('name', 'project', 'code', 'order', 'color')
+ list_display_links = ('name', 'project', 'code')
list_filter = ('project',)
search_fields = ('name', 'project__title')
@@ -94,6 +96,7 @@ class KanbanColumnAdmin(ModelAdmin):
@admin.register(KanbanTask, site=project_admin_site)
class KanbanTaskAdmin(ModelAdmin):
list_display = ('title', 'project', 'column', 'priority_badge', 'assignee', 'due_date', 'order')
+ list_display_links = ('title', 'project', 'column', 'assignee')
list_filter = ('priority', 'project', 'column')
search_fields = ('title', 'description', 'project__title', 'assignee__fullname')
@@ -110,6 +113,7 @@ class KanbanTaskAdmin(ModelAdmin):
@admin.register(ProjectDocument, site=project_admin_site)
class ProjectDocumentAdmin(ModelAdmin):
list_display = ('title', 'project', 'doc_type', 'uploaded_by', 'uploaded_at')
+ list_display_links = ('title', 'project')
list_filter = ('doc_type', 'uploaded_at')
search_fields = ('title', 'project__title')
readonly_fields = ('uploaded_at',)
diff --git a/apps/tickets/admin.py b/apps/tickets/admin.py
index 5dff847..b6e49cd 100644
--- a/apps/tickets/admin.py
+++ b/apps/tickets/admin.py
@@ -13,6 +13,7 @@ class TicketMessageInline(TabularInline):
@admin.register(Ticket)
class TicketAdmin(ModelAdmin):
list_display = ('tracking_code', 'subject', 'category', 'priority', 'status', 'user', 'institution', 'satisfaction_rating', 'created_at')
+ list_display_links = ('tracking_code', 'subject', 'user', 'institution')
list_filter = ('status', 'priority', 'category', 'created_at')
search_fields = ('tracking_code', 'subject', 'user__email', 'user__fullname', 'institution__name')
readonly_fields = ('tracking_code', 'created_at', 'updated_at', 'closed_at')
@@ -22,6 +23,7 @@ class TicketAdmin(ModelAdmin):
@admin.register(TicketMessage)
class TicketMessageAdmin(ModelAdmin):
list_display = ('ticket', 'sender', 'is_official_response', 'department_label', 'created_at')
+ list_display_links = ('ticket', 'sender')
list_filter = ('is_official_response', 'created_at')
search_fields = ('ticket__tracking_code', 'content', 'sender__email', 'sender__fullname')
readonly_fields = ('created_at',)
diff --git a/config/settings/base.py b/config/settings/base.py
index 6901afa..bac46e9 100644
--- a/config/settings/base.py
+++ b/config/settings/base.py
@@ -348,6 +348,10 @@ UNFOLD = {
"STYLES": [
lambda request: static("css/styles.css"),
],
+ "SCRIPTS": [
+ lambda request: static("js/admin_row_click.js"),
+ ],
+
"TABS": [
{
"page": "accounts",
diff --git a/templates/admin/base_site.html b/templates/admin/base_site.html
index 83e0b87..e49fe9f 100644
--- a/templates/admin/base_site.html
+++ b/templates/admin/base_site.html
@@ -7,7 +7,207 @@
{% endblock %}
{% block extrahead %}
+ {{ block.super }}
+ {% load static %}
+
+
+
+
{% if plausible_domain %}
{% endif %}
{% endblock %}
+
diff --git a/utils/admin.py b/utils/admin.py
index 62dc3eb..7f00592 100644
--- a/utils/admin.py
+++ b/utils/admin.py
@@ -27,6 +27,31 @@ def slugify(value):
# Unfold Imports
from unfold.sites import UnfoldAdminSite
+from unfold.admin import ModelAdmin
+
+# --- Enhance ModelAdmin to ensure clicking on items in changelists always navigates to change view ---
+_original_get_list_display_links = ModelAdmin.get_list_display_links
+
+def _smart_get_list_display_links(self, request, list_display):
+ # If list_display_links is explicitly set (or explicitly set to None), respect that choice
+ if self.list_display_links or self.list_display_links is None:
+ return self.list_display_links
+
+ # If not set, rather than only list_display[0] which might be empty or a non-text field,
+ # include all candidate primary identifier fields (excluding action checkboxes and editable fields)
+ editable = getattr(self, 'list_editable', ()) or ()
+ candidates = [
+ f for f in list_display
+ if f != 'action_checkbox' and f not in editable
+ ]
+ if not candidates:
+ return (list_display[0],) if list_display else ()
+
+ # Return primary candidate columns (up to first 4) so clicking on any main field navigates to details
+ return tuple(candidates[:4])
+
+ModelAdmin.get_list_display_links = _smart_get_list_display_links
+
# ---------------------------------------------------------