Files
photos.kennethreitz.org/core/admin.py
T
kennethreitz 0e4a3e1975 Add AI descriptions, tags, tag browsing, .dockerignore
- AI-generated title, description, and tags per image via GPT-4o-mini
  with structured output
- Tag model with word cloud browsing at /tags/ and /tags/<slug>/
- Tags in nav, image detail page, and search
- ai_describe management command with concurrent workers
- OpenAI API key and prompt configurable in SiteConfig admin
- .dockerignore to prevent 7GB Docker builds
- Search now covers ai_title, ai_description, and tag names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:29:16 -04:00

72 lines
2.2 KiB
Python

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from core.models import Camera, ExifData, Image, Lens, SiteConfig, Tag, User
@admin.register(SiteConfig)
class SiteConfigAdmin(admin.ModelAdmin):
list_display = ['site_title', 'tagline']
fieldsets = [
("Site", {'fields': ('site_title', 'tagline')}),
("AI", {'fields': ('openai_api_key', 'ai_prompt')}),
]
def has_add_permission(self, request):
return not SiteConfig.objects.exists()
def has_delete_permission(self, request, obj=None):
return False
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ['name', 'slug']
search_fields = ['name']
prepopulated_fields = {'slug': ('name',)}
@admin.register(User)
class UserAdmin(BaseUserAdmin):
list_display = ['username', 'email', 'date_joined', 'is_staff']
fieldsets = BaseUserAdmin.fieldsets + (
("Profile", {'fields': ('bio', 'avatar', 'website')}),
)
@admin.register(Camera)
class CameraAdmin(admin.ModelAdmin):
list_display = ['display_name', 'manufacturer', 'model', 'slug']
list_filter = ['manufacturer']
search_fields = ['manufacturer', 'model', 'display_name']
prepopulated_fields = {'slug': ('manufacturer', 'model')}
@admin.register(Lens)
class LensAdmin(admin.ModelAdmin):
list_display = ['display_name', 'manufacturer', 'model', 'max_aperture', 'slug']
list_filter = ['manufacturer']
search_fields = ['manufacturer', 'model', 'display_name']
prepopulated_fields = {'slug': ('manufacturer', 'model')}
class ExifDataInline(admin.StackedInline):
model = ExifData
extra = 0
readonly_fields = ['raw_data']
@admin.register(Image)
class ImageAdmin(admin.ModelAdmin):
list_display = ['title', 'user', 'visibility', 'is_processing', 'upload_date']
list_filter = ['visibility', 'is_processing']
search_fields = ['title', 'description', 'user__username']
inlines = [ExifDataInline]
@admin.register(ExifData)
class ExifDataAdmin(admin.ModelAdmin):
list_display = ['image', 'camera', 'lens', 'focal_length', 'aperture', 'iso', 'date_taken']
list_filter = ['camera', 'lens']
search_fields = ['image__title', 'camera__display_name', 'lens__display_name']