Skip to content

Add admin action for background KJV import#40

Draft
Copilot wants to merge 3 commits intomasterfrom
copilot/add-admin-action-import-kjv
Draft

Add admin action for background KJV import#40
Copilot wants to merge 3 commits intomasterfrom
copilot/add-admin-action-import-kjv

Conversation

Copy link
Contributor

Copilot AI commented Jan 8, 2026

Adds a one-click admin action to trigger the existing import_kjv management command in a background thread, preventing request timeouts during long-running imports.

Changes

python_anywhere_website/bible/admin.py:

  • Added import_kjv_action admin action that spawns daemon thread running call_command('import_kjv', clear=True)
  • Helper function _run_import_kjv() wraps command execution with exception logging
  • Action restricted to staff users via is_staff check and allowed_permissions = ('change',)
  • Registered in BibleBookAdmin.actions list
  • Uses Django messages framework for user feedback (INFO on success, ERROR on failure)

python_anywhere_website/bible/tests.py:

  • Added AdminActionTest with 4 test cases covering: staff-only access, thread startup, metadata configuration, and admin registration

Usage

Action appears in the BibleBook changelist actions dropdown. Selecting it triggers an immediate HTTP response with background import continuing asynchronously. Progress and errors logged to server logs.

# Admin action signature
def import_kjv_action(modeladmin, request, queryset):
    if not request.user.is_staff:
        modeladmin.message_user(request, "Only staff users may run...", level=messages.ERROR)
        return
    
    thread = threading.Thread(target=_run_import_kjv, args=(caller,), daemon=True)
    thread.start()
    modeladmin.message_user(request, "KJV import has been started...", level=messages.INFO)

Notes

Uses stdlib threading rather than production-grade task queue to avoid infrastructure dependencies. Database lock errors expected in test logs when background thread outlives test database teardown—properly caught and logged.

Original prompt

Modify python_anywhere_website/bible/admin.py to add an admin-only action that starts the existing KJV import management command in a background thread.

Details of the change:

  • Add a helper function _run_import_kjv(caller_name=None) that calls Django's call_command('import_kjv', clear=True) inside a try/except and logs exceptions. This helper is intended to run in a background thread.
  • Add an admin action import_kjv_action(modeladmin, request, queryset) which:
    • Verifies request.user.is_staff and returns an error message if not.
    • Starts a daemon threading.Thread(target=_run_import_kjv, args=(caller,)) and returns immediately.
    • Uses modeladmin.message_user with messages.INFO or messages.ERROR to inform the admin that the import was started or failed to start.
    • Sets import_kjv_action.short_description = "Import KJV Bible" and import_kjv_action.allowed_permissions = ('change',)
  • Register import_kjv_action in the BibleBookAdmin actions list so it appears in the admin changelist actions dropdown.
  • Keep existing admin configuration for BibleBookAdmin and BibleVerseAdmin (list_display, list_filter, etc.).

Implementation guidance:

  • Only modify python_anywhere_website/bible/admin.py in this PR.
  • Use Python standard library imports threading and logging; use django.contrib.messages for user feedback and django.core.management.call_command to run the import.
  • Avoid adding new dependencies.
  • Keep the import running with clear=True (same as calling python manage.py import_kjv --clear).

Why: This provides admins a one-click way to trigger the existing importer from the Django admin without blocking the request. For production-grade reliability a background worker should be used; this PR intentionally uses a lightweight background thread to avoid adding infra.

User to review: @bamaham93

Change file content (replace the existing file):

from django.contrib import admin, messages
from django.core.management import call_command
from .models import BibleBook, BibleVerse
import threading
import logging

logger = logging.getLogger(__name__)


def _run_import_kjv(caller_name=None):
    """
    Helper that runs the management command. Intended to run in a background thread.
    """
    try:
        logger.info("Admin-initiated KJV import started (user=%s)", caller_name)
        # Call the management command; use keyword arg for the --clear flag
        call_command('import_kjv', clear=True)
        logger.info("Admin-initiated KJV import completed (user=%s)", caller_name)
    except Exception:
        logger.exception("Admin-initiated KJV import failed (user=%s)", caller_name)


def import_kjv_action(modeladmin, request, queryset):
    """
    Admin action to start the KJV import in a background thread.
    - Visible in the actions dropdown on the BibleBook changelist.
    - Uses standard admin permissions (requires change permission).
    - Starts the import in a daemon thread and returns immediately.
    """
    # Limit to staff users as a safety check (admin actions normally require appropriate perms)
    if not request.user.is_staff:
        modeladmin.message_user(request, "Only staff users may run the KJV import.", level=messages.ERROR)
        return

    caller = getattr(request.user, 'username', str(request.user))
    try:
        thread = threading.Thread(target=_run_import_kjv, args=(caller,), daemon=True)
        thread.start()
        modeladmin.message_user(
            request,
            "KJV import has been started in the background. Check the server logs for progress and errors.",
            level=messages.INFO,
        )
    except Exception as exc:
        logger.exception("Failed to start KJV import thread (user=%s)", caller)
        modeladmin.message_user(request, f"Failed to start import: {exc}", level=messages.ERROR)


# Action metadata for admin UI
import_kjv_action.short_description = "Import KJV Bible"
import_kjv_action.allowed_permissions = ('change',)


@admin.register(BibleBook)
class BibleBookAdmin(admin.ModelAdmin):
    list_display = ['order', 'name', 'slug', 'testament', 'chapters']
    list_filter = ['testament']
    search_fields = ['name', 'slug']
    prepopulated_fields = {'slug': ('name',)}
    ordering = ['order']

    # Register the import action on the changelist actions dropdown
    actions = [import_kjv_action]


@admin.register(BibleVerse)
class BibleVerseAdmin(admin.ModelAdmin):
    list_display = ['book', 'chapter', 'verse', 'text_preview']
    list_filter = ['book', 'chapter']
    search_fields = ['text', 'book__name']
    ordering = ['book__order', 'chapter', 'verse']

    def text_preview(self, obj):
        return obj.text[:50] + '...' if len(obj.text) > 50 else obj.text
    text_preview.short_description = 'Text'

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits January 8, 2026 01:13
Co-authored-by: bamaham93 <57500397+bamaham93@users.noreply.github.com>
…imports

Co-authored-by: bamaham93 <57500397+bamaham93@users.noreply.github.com>
Copilot AI changed the title [WIP] Add admin-only action to start KJV import command Add admin action for background KJV import Jan 8, 2026
Copilot AI requested a review from bamaham93 January 8, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants