From 5ad2c894c26ef0bd29d09991b67462665e6d788c Mon Sep 17 00:00:00 2001 From: TatsatJha Date: Fri, 3 Apr 2026 11:02:48 -0700 Subject: [PATCH 1/5] try to add email field to the admin form, needs fixing --- hospexplorer/ask/admin.py | 55 ++++++++++++++++++++++++++++++--------- hospexplorer/ask/forms.py | 11 ++++++++ 2 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 hospexplorer/ask/forms.py diff --git a/hospexplorer/ask/admin.py b/hospexplorer/ask/admin.py index 35219fa..c375f40 100644 --- a/hospexplorer/ask/admin.py +++ b/hospexplorer/ask/admin.py @@ -1,6 +1,10 @@ import logging from django.contrib import admin +from django import forms +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User +from .forms import CustomUserCreationForm from ask.models import Conversation, TermsAcceptance, QARecord, SimWorkflow, WebsiteResource from ask.kb_connector import add_website_to_kb @@ -11,22 +15,39 @@ class QARecordInline(admin.TabularInline): model = QARecord extra = 0 - readonly_fields = ("question_text", "question_timestamp", "answer_text", "answer_timestamp", "is_error") - fields = ("question_text", "question_timestamp", "answer_text", "answer_timestamp", "is_error") + readonly_fields = ("question_text", "question_timestamp", + "answer_text", "answer_timestamp", "is_error") + fields = ("question_text", "question_timestamp", + "answer_text", "answer_timestamp", "is_error") @admin.register(Conversation) class ConversationAdmin(admin.ModelAdmin): - list_display = ("id", "llm_conversation_id", "title", "user", "qa_record_count", "created_at", "updated_at") + list_display = ("id", "llm_conversation_id", "title", "user", + "qa_record_count", "created_at", "updated_at") list_filter = ("user",) search_fields = ("title", "user__username") - readonly_fields = ("id", "llm_conversation_id", "qa_record_count", "created_at", "updated_at") + readonly_fields = ("id", "llm_conversation_id", + "qa_record_count", "created_at", "updated_at") def qa_record_count(self, obj): return obj.qa_records.count() qa_record_count.short_description = "Q&A Records" +class CustomUserAdmin(UserAdmin): + add_form = CustomUserCreationForm + email_field = forms.EmailField(required=True) + + add_fieldsets = ( + (None, {'fields': ('extra_field',)}), + ) + + +admin.site.unregister(User) +admin.site.register(User, CustomUserAdmin) + + @admin.register(TermsAcceptance) class TermsAcceptanceAdmin(admin.ModelAdmin): list_display = ("user", "terms_version", "accepted_at") @@ -47,10 +68,12 @@ def has_delete_permission(self, request, obj=None): @admin.register(QARecord) class QARecordAdmin(admin.ModelAdmin): - list_display = ["id", "user", "conversation", "truncated_question", "question_timestamp", "answer_timestamp", "is_error"] + list_display = ["id", "user", "conversation", "truncated_question", + "question_timestamp", "answer_timestamp", "is_error"] list_filter = ["question_timestamp", "user", "is_error"] search_fields = ["question_text", "answer_text", "user__username"] - readonly_fields = ["question_timestamp", "answer_timestamp", "answer_raw_response"] + readonly_fields = ["question_timestamp", + "answer_timestamp", "answer_raw_response"] raw_id_fields = ["user", "conversation"] date_hierarchy = "question_timestamp" @@ -61,7 +84,8 @@ def truncated_question(self, obj): @admin.register(SimWorkflow) class SimWorkflowAdmin(admin.ModelAdmin): - list_display = ("title", "workflow_id", "workflow_type", "is_active", "agent_endpoint", "updated_at") + list_display = ("title", "workflow_id", "workflow_type", + "is_active", "agent_endpoint", "updated_at") list_filter = ("is_active", "workflow_type") search_fields = ("title", "description", "workflow_id") actions = ["set_as_active"] @@ -87,12 +111,14 @@ class SimWorkflowAdmin(admin.ModelAdmin): @admin.action(description="Set selected workflow as active") def set_as_active(self, request, queryset): if queryset.count() != 1: - self.message_user(request, "Please select exactly one workflow to activate.", level="error") + self.message_user( + request, "Please select exactly one workflow to activate.", level="error") return workflow = queryset.first() workflow.is_active = True workflow.save() - self.message_user(request, f"'{workflow.title}' is now the active workflow.") + self.message_user( + request, f"'{workflow.title}' is now the active workflow.") # catches ValidationError from model constraints # and gives an admin message instead of a 500 error @@ -122,12 +148,13 @@ def delete_queryset(self, request, queryset): self.message_user(request, e.message, level="error") return - + @admin.register(WebsiteResource) class WebsiteResourceAdmin(admin.ModelAdmin): list_display = ("title", "url", "creator", "modified_at") search_fields = ("title", "url") - readonly_fields = ("created_at", "modified_at", "creator", "modifier", "mcp_kb_document_id") + readonly_fields = ("created_at", "modified_at", "creator", + "modifier", "mcp_kb_document_id") help_texts = { "title": "A short name to identify this website resource.", "description": "Optional details about what this website covers.", @@ -154,7 +181,9 @@ def save_model(self, request, obj, form, change): result = add_website_to_kb(obj.url) obj.mcp_kb_document_id = result.get("doc_id") obj.save(update_fields=["mcp_kb_document_id"]) - self.message_user(request, f"Website '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") + self.message_user( + request, f"Website '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") except Exception as e: logger.exception("Failed to send website to KB: %s", obj.url) - self.message_user(request, f"Website saved but failed to send to Knowledge Base: {e}", level="warning") + self.message_user( + request, f"Website saved but failed to send to Knowledge Base: {e}", level="warning") diff --git a/hospexplorer/ask/forms.py b/hospexplorer/ask/forms.py new file mode 100644 index 0000000..d132561 --- /dev/null +++ b/hospexplorer/ask/forms.py @@ -0,0 +1,11 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth import get_user_model + + +class CustomUserCreationForm(UserCreationForm): + email_field = forms.EmailField(required=True) + + class Meta: + model = get_user_model() + fields = ("username", "email_field",) From 2c7d5fd35053e2d1d9b8e7164ff44cb47d29a305 Mon Sep 17 00:00:00 2001 From: TatsatJha Date: Tue, 7 Apr 2026 10:17:31 -0700 Subject: [PATCH 2/5] attempt debugging --- hospexplorer/ask/admin.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hospexplorer/ask/admin.py b/hospexplorer/ask/admin.py index c375f40..998a03d 100644 --- a/hospexplorer/ask/admin.py +++ b/hospexplorer/ask/admin.py @@ -5,7 +5,6 @@ from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User from .forms import CustomUserCreationForm - from ask.models import Conversation, TermsAcceptance, QARecord, SimWorkflow, WebsiteResource from ask.kb_connector import add_website_to_kb @@ -39,8 +38,8 @@ class CustomUserAdmin(UserAdmin): add_form = CustomUserCreationForm email_field = forms.EmailField(required=True) - add_fieldsets = ( - (None, {'fields': ('extra_field',)}), + fieldsets = UserAdmin.add_fieldsets + ( + (None, {'fields': ('email_field',)}), ) From 3a63717c680363df09926e72e415b283ba5f2090 Mon Sep 17 00:00:00 2001 From: TatsatJha Date: Thu, 9 Apr 2026 10:55:14 -0700 Subject: [PATCH 3/5] fix errors and simplify --- hospexplorer/ask/admin.py | 16 +++++++++++----- hospexplorer/ask/forms.py | 11 ----------- 2 files changed, 11 insertions(+), 16 deletions(-) delete mode 100644 hospexplorer/ask/forms.py diff --git a/hospexplorer/ask/admin.py b/hospexplorer/ask/admin.py index 998a03d..5b02257 100644 --- a/hospexplorer/ask/admin.py +++ b/hospexplorer/ask/admin.py @@ -35,13 +35,19 @@ def qa_record_count(self, obj): class CustomUserAdmin(UserAdmin): - add_form = CustomUserCreationForm - email_field = forms.EmailField(required=True) - - fieldsets = UserAdmin.add_fieldsets + ( - (None, {'fields': ('email_field',)}), + add_fieldsets = ( + (None, { + 'classes': ('wide',), + 'fields': ('username', 'email', 'password1', 'password2'), + }), ) + def get_form(self, request, obj=None, **kwargs): + form = super().get_form(request, obj, **kwargs) + if obj is None: + form.base_fields['email'].required = True + return form + admin.site.unregister(User) admin.site.register(User, CustomUserAdmin) diff --git a/hospexplorer/ask/forms.py b/hospexplorer/ask/forms.py deleted file mode 100644 index d132561..0000000 --- a/hospexplorer/ask/forms.py +++ /dev/null @@ -1,11 +0,0 @@ -from django import forms -from django.contrib.auth.forms import UserCreationForm -from django.contrib.auth import get_user_model - - -class CustomUserCreationForm(UserCreationForm): - email_field = forms.EmailField(required=True) - - class Meta: - model = get_user_model() - fields = ("username", "email_field",) From 73a18df7b089c2e053f599f0e0293071ed702000 Mon Sep 17 00:00:00 2001 From: TatsatJha Date: Thu, 9 Apr 2026 11:01:10 -0700 Subject: [PATCH 4/5] remove unneeded changes --- hospexplorer/ask/admin.py | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/hospexplorer/ask/admin.py b/hospexplorer/ask/admin.py index 5b02257..be75ef2 100644 --- a/hospexplorer/ask/admin.py +++ b/hospexplorer/ask/admin.py @@ -1,10 +1,8 @@ import logging from django.contrib import admin -from django import forms from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User -from .forms import CustomUserCreationForm from ask.models import Conversation, TermsAcceptance, QARecord, SimWorkflow, WebsiteResource from ask.kb_connector import add_website_to_kb @@ -14,20 +12,16 @@ class QARecordInline(admin.TabularInline): model = QARecord extra = 0 - readonly_fields = ("question_text", "question_timestamp", - "answer_text", "answer_timestamp", "is_error") - fields = ("question_text", "question_timestamp", - "answer_text", "answer_timestamp", "is_error") + readonly_fields = ("question_text", "question_timestamp", "answer_text", "answer_timestamp", "is_error") + fields = ("question_text", "question_timestamp", "answer_text", "answer_timestamp", "is_error") @admin.register(Conversation) class ConversationAdmin(admin.ModelAdmin): - list_display = ("id", "llm_conversation_id", "title", "user", - "qa_record_count", "created_at", "updated_at") + list_display = ("id", "llm_conversation_id", "title", "user", "qa_record_count", "created_at", "updated_at") list_filter = ("user",) search_fields = ("title", "user__username") - readonly_fields = ("id", "llm_conversation_id", - "qa_record_count", "created_at", "updated_at") + readonly_fields = ("id", "llm_conversation_id", "qa_record_count", "created_at", "updated_at") def qa_record_count(self, obj): return obj.qa_records.count() @@ -73,12 +67,10 @@ def has_delete_permission(self, request, obj=None): @admin.register(QARecord) class QARecordAdmin(admin.ModelAdmin): - list_display = ["id", "user", "conversation", "truncated_question", - "question_timestamp", "answer_timestamp", "is_error"] + list_display = ["id", "user", "conversation", "truncated_question", "question_timestamp", "answer_timestamp", "is_error"] list_filter = ["question_timestamp", "user", "is_error"] search_fields = ["question_text", "answer_text", "user__username"] - readonly_fields = ["question_timestamp", - "answer_timestamp", "answer_raw_response"] + readonly_fields = ["question_timestamp", "answer_timestamp", "answer_raw_response"] raw_id_fields = ["user", "conversation"] date_hierarchy = "question_timestamp" @@ -89,8 +81,7 @@ def truncated_question(self, obj): @admin.register(SimWorkflow) class SimWorkflowAdmin(admin.ModelAdmin): - list_display = ("title", "workflow_id", "workflow_type", - "is_active", "agent_endpoint", "updated_at") + list_display = ("title", "workflow_id", "workflow_type", "is_active", "agent_endpoint", "updated_at") list_filter = ("is_active", "workflow_type") search_fields = ("title", "description", "workflow_id") actions = ["set_as_active"] @@ -116,14 +107,12 @@ class SimWorkflowAdmin(admin.ModelAdmin): @admin.action(description="Set selected workflow as active") def set_as_active(self, request, queryset): if queryset.count() != 1: - self.message_user( - request, "Please select exactly one workflow to activate.", level="error") + self.message_user(request, "Please select exactly one workflow to activate.", level="error") return workflow = queryset.first() workflow.is_active = True workflow.save() - self.message_user( - request, f"'{workflow.title}' is now the active workflow.") + self.message_user(request, f"'{workflow.title}' is now the active workflow.") # catches ValidationError from model constraints # and gives an admin message instead of a 500 error @@ -158,8 +147,7 @@ def delete_queryset(self, request, queryset): class WebsiteResourceAdmin(admin.ModelAdmin): list_display = ("title", "url", "creator", "modified_at") search_fields = ("title", "url") - readonly_fields = ("created_at", "modified_at", "creator", - "modifier", "mcp_kb_document_id") + readonly_fields = ("created_at", "modified_at", "creator", "modifier", "mcp_kb_document_id") help_texts = { "title": "A short name to identify this website resource.", "description": "Optional details about what this website covers.", @@ -186,9 +174,7 @@ def save_model(self, request, obj, form, change): result = add_website_to_kb(obj.url) obj.mcp_kb_document_id = result.get("doc_id") obj.save(update_fields=["mcp_kb_document_id"]) - self.message_user( - request, f"Website '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") + self.message_user(request, f"Website '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") except Exception as e: logger.exception("Failed to send website to KB: %s", obj.url) - self.message_user( - request, f"Website saved but failed to send to Knowledge Base: {e}", level="warning") + self.message_user(request, f"Website saved but failed to send to Knowledge Base: {e}", level="warning") From 31881038c2f2b4ae42eafc39f79e8f0e89c06300 Mon Sep 17 00:00:00 2001 From: TatsatJha Date: Fri, 24 Apr 2026 12:07:59 -0700 Subject: [PATCH 5/5] [HOP-55] remove whitespace edits --- hospexplorer/ask/admin.py | 52 ++++++++++++++------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/hospexplorer/ask/admin.py b/hospexplorer/ask/admin.py index 1d71b34..a449c45 100644 --- a/hospexplorer/ask/admin.py +++ b/hospexplorer/ask/admin.py @@ -28,8 +28,7 @@ def _delete_kb_document(self, request, obj): level="error", ) return False - self.message_user( - request, f"Removed '{obj.title}' from Knowledge Base.") + self.message_user(request, f"Removed '{obj.title}' from Knowledge Base.") return True def delete_model(self, request, obj): @@ -47,20 +46,16 @@ def delete_queryset(self, request, queryset): class QARecordInline(admin.TabularInline): model = QARecord extra = 0 - readonly_fields = ("question_text", "question_timestamp", - "answer_text", "answer_timestamp", "is_error") - fields = ("question_text", "question_timestamp", - "answer_text", "answer_timestamp", "is_error") + readonly_fields = ("question_text", "question_timestamp", "answer_text", "answer_timestamp", "is_error") + fields = ("question_text", "question_timestamp", "answer_text", "answer_timestamp", "is_error") @admin.register(Conversation) class ConversationAdmin(admin.ModelAdmin): - list_display = ("id", "llm_conversation_id", "title", "user", - "qa_record_count", "created_at", "updated_at") + list_display = ("id", "llm_conversation_id", "title", "user", "qa_record_count", "created_at", "updated_at") list_filter = ("user",) search_fields = ("title", "user__username") - readonly_fields = ("id", "llm_conversation_id", - "qa_record_count", "created_at", "updated_at") + readonly_fields = ("id", "llm_conversation_id", "qa_record_count", "created_at", "updated_at") def qa_record_count(self, obj): return obj.qa_records.count() @@ -106,12 +101,10 @@ def has_delete_permission(self, request, obj=None): @admin.register(QARecord) class QARecordAdmin(admin.ModelAdmin): - list_display = ["id", "user", "conversation", "truncated_question", - "question_timestamp", "answer_timestamp", "is_error"] + list_display = ["id", "user", "conversation", "truncated_question", "question_timestamp", "answer_timestamp", "is_error"] list_filter = ["question_timestamp", "user", "is_error"] search_fields = ["question_text", "answer_text", "user__username"] - readonly_fields = ["question_timestamp", - "answer_timestamp", "answer_raw_response"] + readonly_fields = ["question_timestamp", "answer_timestamp", "answer_raw_response"] raw_id_fields = ["user", "conversation"] date_hierarchy = "question_timestamp" @@ -122,8 +115,7 @@ def truncated_question(self, obj): @admin.register(SimWorkflow) class SimWorkflowAdmin(admin.ModelAdmin): - list_display = ("title", "workflow_id", "workflow_type", - "is_active", "agent_endpoint", "updated_at") + list_display = ("title", "workflow_id", "workflow_type", "is_active", "agent_endpoint", "updated_at") list_filter = ("is_active", "workflow_type") search_fields = ("title", "description", "workflow_id") actions = ["set_as_active"] @@ -149,14 +141,12 @@ class SimWorkflowAdmin(admin.ModelAdmin): @admin.action(description="Set selected workflow as active") def set_as_active(self, request, queryset): if queryset.count() != 1: - self.message_user( - request, "Please select exactly one workflow to activate.", level="error") + self.message_user(request, "Please select exactly one workflow to activate.", level="error") return workflow = queryset.first() workflow.is_active = True workflow.save() - self.message_user( - request, f"'{workflow.title}' is now the active workflow.") + self.message_user(request, f"'{workflow.title}' is now the active workflow.") # catches ValidationError from model constraints # and gives an admin message instead of a 500 error @@ -191,8 +181,7 @@ def delete_queryset(self, request, queryset): class WebsiteResourceAdmin(KBDeleteAdminMixin, admin.ModelAdmin): list_display = ("title", "url", "creator", "modified_at") search_fields = ("title", "url") - readonly_fields = ("created_at", "modified_at", "creator", - "modifier", "mcp_kb_document_id") + readonly_fields = ("created_at", "modified_at", "creator", "modifier", "mcp_kb_document_id") help_texts = { "title": "A short name to identify this website resource.", "description": "Optional details about what this website covers.", @@ -219,20 +208,17 @@ def save_model(self, request, obj, form, change): result = add_website_to_kb(obj.url) obj.mcp_kb_document_id = result.get("doc_id") obj.save(update_fields=["mcp_kb_document_id"]) - self.message_user( - request, f"Website '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") + self.message_user(request, f"Website '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") except Exception as e: logger.exception("Failed to send website to KB: %s", obj.url) - self.message_user( - request, f"Website saved but failed to send to Knowledge Base: {e}", level="warning") + self.message_user(request, f"Website saved but failed to send to Knowledge Base: {e}", level="warning") @admin.register(PDFResource) class PDFResourceAdmin(KBDeleteAdminMixin, admin.ModelAdmin): list_display = ("title", "file", "creator", "modified_at") search_fields = ("title",) - readonly_fields = ("created_at", "modified_at", "creator", - "modifier", "mcp_kb_document_id") + readonly_fields = ("created_at", "modified_at", "creator", "modifier", "mcp_kb_document_id") help_texts = { "title": "A short name to identify this PDF resource.", "description": "Optional details about what this PDF covers.", @@ -256,13 +242,11 @@ def save_model(self, request, obj, form, change): obj.file.open("rb") file_bytes = obj.file.read() obj.file.close() - result = add_pdf_to_kb( - file_bytes, obj.file.name.split("/")[-1], obj.title) + result = add_pdf_to_kb(file_bytes, obj.file.name.split("/")[-1], obj.title) obj.mcp_kb_document_id = result.get("doc_id") obj.save(update_fields=["mcp_kb_document_id"]) - self.message_user( - request, f"PDF '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") + self.message_user(request, f"PDF '{obj.title}' sent to Knowledge Base (doc_id={obj.mcp_kb_document_id}).") except Exception as e: logger.exception("Failed to send PDF to KB: %s", obj.file.name) - self.message_user( - request, f"PDF saved but failed to send to Knowledge Base: {e}", level="warning") + self.message_user(request, f"PDF saved but failed to send to Knowledge Base: {e}", level="warning") +