feat: preview image task inputs in admin

This commit is contained in:
QiuSW
2026-07-20 08:58:34 +08:00
parent 2e222a2aef
commit 8eec0e3db7
9 changed files with 382 additions and 5 deletions
+107 -1
View File
@@ -14,9 +14,10 @@ from django.conf import settings
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.core.files.base import ContentFile
from django.core.management import call_command
from django.test import TestCase, override_settings
from django.urls import path
from django.urls import path, reverse
from django.utils import timezone
from rest_framework.response import Response
from rest_framework.test import APIClient
@@ -696,6 +697,111 @@ class ClientLatestReleaseApiTests(TestCase):
self.assertIn("size_bytes", download_fields)
class ImageGenerationTaskAdminTests(TestCase):
def setUp(self):
self.media_dir = tempfile.TemporaryDirectory()
self.addCleanup(self.media_dir.cleanup)
self.media_override = override_settings(MEDIA_ROOT=self.media_dir.name)
self.media_override.enable()
self.addCleanup(self.media_override.disable)
suffix = uuid.uuid4().hex[:8]
user_model = get_user_model()
self.admin_user = user_model.objects.create_superuser(
username=f"image-task-admin-{suffix}",
email=f"image-task-admin-{suffix}@example.com",
password="test-password",
)
self.user = user_model.objects.create_user(
username=f"image-task-user-{suffix}",
email=f"image-task-user-{suffix}@example.com",
password="test-password",
)
self.api_key, _raw_key = ApiKey.create_for_user(self.user, name="image-task-admin-test")
self.client.force_login(self.admin_user)
def create_task(self, *, status=ImageGenerationTask.Status.SUCCEEDED, result_url=""):
call_record = CallRecord.objects.create(
user=self.user,
api_key=self.api_key,
operation_type=CallRecord.OperationType.IMAGE,
alias="image-standard",
model_used="test-image-model",
resolution="1K",
prompt="生成商品主图",
points_cost=10,
status=CallRecord.Status.SUCCESS,
)
return ImageGenerationTask.objects.create(
user=self.user,
api_key=self.api_key,
call_record=call_record,
status=status,
request_hash=uuid.uuid4().hex + uuid.uuid4().hex,
result_url=result_url,
points_balance_after_charge=90,
)
def change_url(self, task):
return reverse("admin:api_imagegenerationtask_change", args=(task.pk,))
def add_input_image(self, task, *, ordinal, filename):
task_input = ImageGenerationTaskInput(
task=task,
ordinal=ordinal,
mime_type="image/png",
filename=filename,
)
task_input.image.save(filename, ContentFile(b"test-image"), save=True)
return task_input
def test_change_view_shows_ordered_input_and_result_thumbnails_with_modal_preview(self):
task = self.create_task(result_url="https://images.example.test/generated.png")
main = self.add_input_image(task, ordinal=0, filename="main.png")
reference = self.add_input_image(task, ordinal=1, filename="reference.png")
response = self.client.get(self.change_url(task))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "图片预览")
self.assertContains(response, "主图")
self.assertContains(response, "参考图 1")
self.assertContains(response, "生成结果")
self.assertContains(response, main.image.url)
self.assertContains(response, reference.image.url)
self.assertContains(response, task.result_url)
self.assertContains(response, "data-image-preview-dialog")
self.assertContains(response, "image-task-gallery.js")
self.assertContains(response, "双击查看大图")
def test_change_view_uses_legacy_single_input_image_as_main_image(self):
task = self.create_task()
task.input_image.save("legacy-main.png", ContentFile(b"legacy-image"), save=True)
response = self.client.get(self.change_url(task))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "主图")
self.assertContains(response, task.input_image.url)
self.assertNotContains(response, "参考图 1")
def test_change_view_handles_task_without_images_or_result(self):
task = self.create_task(status=ImageGenerationTask.Status.QUEUED)
response = self.client.get(self.change_url(task))
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'id="image-task-gallery-title"')
def test_change_view_requires_staff_access(self):
task = self.create_task()
self.client.force_login(self.user)
response = self.client.get(self.change_url(task))
self.assertEqual(response.status_code, 302)
@override_settings(
PAYMENT_CALLBACK_MODE="mock",
PAYMENT_MOCK_CALLBACK_SECRET="test-payment-callback-secret",