from django.contrib import admin
from django.utils.html import format_html
from django import forms
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.urls import reverse
from .models import Person, AccessLog, WithdrawalRequest
from .withdrawal_utils import process_withdrawal_approval, reject_withdrawal_request
class PersonAdminForm(forms.ModelForm):
class Meta:
model = Person
fields = '__all__'
widgets = {
'사진': forms.FileInput(attrs={
'style': 'border: 1px solid #ccc; padding: 5px; border-radius: 3px;'
})
}
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
form = PersonAdminForm
list_display = ['SEQUENCE', '이름', '소속', '직책', '연락처', 'user', '모든사람보기권한', '비밀번호설정필요', '가입일시', '사진']
list_filter = ['모든사람보기권한', '비밀번호설정필요', '소속', '직책']
search_fields = ['이름', '소속', '직책', '연락처', 'keyword1', '소개글']
readonly_fields = ['수정일시', '사진미리보기', '가입일시']
list_editable = ['SEQUENCE']
list_display_links = ['이름']
ordering = ['이름']
fieldsets = (
('기본 정보', {
'fields': ('이름', '연락처', 'user')
}),
('상세 정보', {
'fields': ('소속', '직책', '주소', '생년월일')
}),
('미디어', {
'fields': ('사진', '사진미리보기')
}),
('추가 정보', {
'fields': ('keyword1', '소개글')
}),
('설정', {
'fields': ('모든사람보기권한', '비밀번호설정필요', 'TITLE', 'SEQUENCE', '가입일시')
}),
)
class Media:
css = {
'all': ('admin/css/custom_admin.css',)
}
def 사진미리보기(self, obj):
if obj.사진:
return format_html(
'',
obj.사진.url
)
return "사진 없음"
사진미리보기.short_description = '사진 미리보기'
def 모든사람보기권한(self, obj):
if obj.모든사람보기권한:
return format_html('✓ 모든 사람 보기')
else:
return format_html('👤 회원가입자만 보기')
모든사람보기권한.short_description = '보기 권한'
def 비밀번호설정필요(self, obj):
if obj.비밀번호설정필요:
return format_html('⚠️ 비밀번호 설정 필요')
else:
return format_html('✓ 비밀번호 설정 완료')
비밀번호설정필요.short_description = '비밀번호 설정 상태'
def 수정일시(self, obj):
return obj.user.date_joined if obj.user else 'N/A'
수정일시.short_description = '수정일시'
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
def has_add_permission(self, request):
return request.user.is_superuser
def has_change_permission(self, request, obj=None):
return request.user.is_superuser
def has_view_permission(self, request, obj=None):
return request.user.is_superuser
@admin.register(AccessLog)
class AccessLogAdmin(admin.ModelAdmin):
list_display = ['timestamp', '사용자명', 'action_display', 'ip_address', '기기정보', '브라우저정보', 'description']
list_filter = ['action', 'timestamp', 'ip_address']
search_fields = ['user__username', 'person__이름', 'description', 'ip_address']
readonly_fields = ['timestamp', 'user', 'person', 'action', 'description', 'ip_address', 'user_agent', 'session_key', 'metadata', '변경사항_상세보기', '기기정보', '브라우저정보']
date_hierarchy = 'timestamp'
ordering = ['-timestamp']
# 페이지당 표시할 항목 수
list_per_page = 50
def 사용자명(self, obj):
if obj.person:
return format_html('{}', obj.person.이름)
elif obj.user:
return format_html('{}', obj.user.username)
else:
return format_html('익명')
사용자명.short_description = '사용자'
사용자명.admin_order_field = 'person__이름'
def action_display(self, obj):
action_colors = {
'LOGIN': '#28a745', # 초록
'LOGOUT': '#6c757d', # 회색
'SIGNUP': '#007bff', # 파랑
'PROFILE_UPDATE': '#ffc107', # 노랑
'PASSWORD_CHANGE': '#fd7e14', # 주황
'PHONE_VERIFICATION': '#20c997', # 청록
'SEARCH': '#6f42c1', # 보라
'VIEW_PROFILE': '#17a2b8', # 하늘
'MAIN_ACCESS': '#343a40', # 어두운 회색
'ERROR': '#dc3545', # 빨강
'OTHER': '#6c757d', # 회색
}
color = action_colors.get(obj.action, '#6c757d')
return format_html(
'{}',
color, obj.get_action_display()
)
action_display.short_description = '활동'
action_display.admin_order_field = 'action'
def 기기정보(self, obj):
if obj.metadata and 'device_info' in obj.metadata:
device_info = obj.metadata['device_info']
# 기기별 아이콘 추가
icons = {
'iPhone': '📱',
'iPad': '📱',
'Android 폰': '📱',
'Android 태블릿': '📱',
'Windows 10/11': '💻',
'Windows 8.1': '💻',
'Windows 7': '💻',
'Windows': '💻',
'Mac': '💻',
'Linux': '💻',
}
icon = icons.get(device_info, '🖥️')
return format_html('{} {}', icon, device_info)
return format_html('알 수 없음')
기기정보.short_description = '기기'
def 브라우저정보(self, obj):
if obj.metadata and 'browser_info' in obj.metadata:
browser_info = obj.metadata['browser_info']
# 브라우저별 색상 추가
colors = {
'Chrome': '#4285f4',
'Firefox': '#ff7139',
'Safari': '#1b88ca',
'Microsoft Edge': '#0078d4',
'Opera': '#ff1b2d',
}
color = colors.get(browser_info, '#6c757d')
return format_html(
'{}',
color, browser_info
)
return format_html('알 수 없음')
브라우저정보.short_description = '브라우저'
fieldsets = (
('기본 정보', {
'fields': ('timestamp', 'user', 'person', 'action', 'description')
}),
('접속 정보', {
'fields': ('ip_address', '기기정보', '브라우저정보', 'user_agent', 'session_key')
}),
('상세 변경사항', {
'fields': ('변경사항_상세보기',),
'classes': ('collapse',)
}),
('추가 정보 (JSON)', {
'fields': ('metadata',),
'classes': ('collapse',)
}),
)
def 변경사항_상세보기(self, obj):
"""변경사항을 보기 좋게 표시"""
if obj.action == 'PROFILE_UPDATE' and obj.metadata.get('field_changes'):
changes = obj.metadata['field_changes']
html_parts = ['