Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 3m50s
CI/CD Pipeline / Run Tests (push) Successful in 3m57s
CI/CD Pipeline / Build Docker Images (push) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (push) Has been skipped
CI/CD Pipeline / Deploy to Server (push) Has been skipped
182 lines
5.6 KiB
Python
182 lines
5.6 KiB
Python
"""Admin configuration for user app."""
|
||
|
||
from contextlib import suppress
|
||
|
||
from django.contrib import admin
|
||
from django.contrib.admin.sites import NotRegistered
|
||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||
from django.contrib.auth.models import Group
|
||
from django.utils.html import format_html
|
||
from django.utils.translation import gettext_lazy as _
|
||
|
||
from apps.core.models import BackgroundJob
|
||
from apps.user.models import Profile, User
|
||
|
||
try:
|
||
from django_celery_beat.models import (
|
||
ClockedSchedule,
|
||
CrontabSchedule,
|
||
IntervalSchedule,
|
||
PeriodicTask,
|
||
SolarSchedule,
|
||
)
|
||
except ImportError: # pragma: no cover - optional dependency import guard
|
||
ClockedSchedule = None
|
||
CrontabSchedule = None
|
||
IntervalSchedule = None
|
||
PeriodicTask = None
|
||
SolarSchedule = None
|
||
|
||
try:
|
||
from rest_framework_simplejwt.token_blacklist.models import (
|
||
BlacklistedToken,
|
||
OutstandingToken,
|
||
)
|
||
except ImportError: # pragma: no cover - optional dependency import guard
|
||
BlacklistedToken = None
|
||
OutstandingToken = None
|
||
|
||
|
||
def _unregister(model) -> None:
|
||
if model is None:
|
||
return
|
||
|
||
with suppress(NotRegistered):
|
||
admin.site.unregister(model)
|
||
|
||
|
||
_unregister(User)
|
||
|
||
|
||
class ProfileInline(admin.StackedInline):
|
||
"""Inline для профиля пользователя."""
|
||
|
||
model = Profile
|
||
extra = 0
|
||
max_num = 1
|
||
can_delete = False
|
||
verbose_name_plural = "Профиль"
|
||
fk_name = "user"
|
||
fields = ["first_name", "mid_name", "last_name", "bio", "avatar", "date_of_birth"]
|
||
|
||
|
||
@admin.register(User)
|
||
class UserAdmin(BaseUserAdmin):
|
||
"""Admin для пользователей без групп."""
|
||
|
||
inlines = [ProfileInline]
|
||
list_display = [
|
||
"username",
|
||
"email",
|
||
"phone",
|
||
"is_verified_badge",
|
||
"is_active_badge",
|
||
"is_staff",
|
||
"created_at",
|
||
]
|
||
list_filter = ["is_staff", "is_superuser", "is_active", "is_verified", "created_at"]
|
||
search_fields = ["username", "email", "phone"]
|
||
ordering = ["-created_at"]
|
||
list_per_page = 50
|
||
date_hierarchy = "created_at"
|
||
|
||
fieldsets = (
|
||
(None, {"fields": ("username", "password")}),
|
||
(_("Personal info"), {"fields": ("email", "phone")}),
|
||
(
|
||
_("Permissions"),
|
||
{
|
||
"fields": (
|
||
"is_active",
|
||
"is_staff",
|
||
"is_superuser",
|
||
"is_verified",
|
||
"user_permissions",
|
||
),
|
||
"classes": ("collapse",),
|
||
},
|
||
),
|
||
(
|
||
_("Important dates"),
|
||
{"fields": ("last_login", "date_joined", "created_at", "updated_at")},
|
||
),
|
||
)
|
||
|
||
add_fieldsets = (
|
||
(
|
||
None,
|
||
{
|
||
"classes": ("wide",),
|
||
"fields": (
|
||
"username",
|
||
"email",
|
||
"password1",
|
||
"password2",
|
||
"is_staff",
|
||
"is_active",
|
||
),
|
||
},
|
||
),
|
||
)
|
||
|
||
readonly_fields = ["created_at", "updated_at", "last_login", "date_joined"]
|
||
actions = ["verify_users", "unverify_users", "activate_users", "deactivate_users"]
|
||
|
||
def is_verified_badge(self, obj):
|
||
if obj.is_verified:
|
||
return format_html(
|
||
'<span style="color: white; background: #28a745; padding: 3px 10px; border-radius: 3px;">✓</span>'
|
||
)
|
||
return format_html(
|
||
'<span style="color: white; background: #dc3545; padding: 3px 10px; border-radius: 3px;">✗</span>'
|
||
)
|
||
|
||
is_verified_badge.short_description = "Верифицирован"
|
||
is_verified_badge.admin_order_field = "is_verified"
|
||
|
||
def is_active_badge(self, obj):
|
||
if obj.is_active:
|
||
return format_html(
|
||
'<span style="color: white; background: #28a745; padding: 3px 10px; border-radius: 3px;">Активен</span>'
|
||
)
|
||
return format_html(
|
||
'<span style="color: white; background: #dc3545; padding: 3px 10px; border-radius: 3px;">Неактивен</span>'
|
||
)
|
||
|
||
is_active_badge.short_description = "Статус"
|
||
is_active_badge.admin_order_field = "is_active"
|
||
|
||
@admin.action(description="Верифицировать выбранных пользователей")
|
||
def verify_users(self, request, queryset):
|
||
updated = queryset.update(is_verified=True)
|
||
self.message_user(request, f"Верифицировано {updated} пользователей")
|
||
|
||
@admin.action(description="Снять верификацию")
|
||
def unverify_users(self, request, queryset):
|
||
updated = queryset.update(is_verified=False)
|
||
self.message_user(request, f"Снята верификация у {updated} пользователей")
|
||
|
||
@admin.action(description="Активировать пользователей")
|
||
def activate_users(self, request, queryset):
|
||
updated = queryset.update(is_active=True)
|
||
self.message_user(request, f"Активировано {updated} пользователей")
|
||
|
||
@admin.action(description="Деактивировать пользователей")
|
||
def deactivate_users(self, request, queryset):
|
||
updated = queryset.update(is_active=False)
|
||
self.message_user(request, f"Деактивировано {updated} пользователей")
|
||
|
||
|
||
for model in (
|
||
Group,
|
||
BackgroundJob,
|
||
OutstandingToken,
|
||
BlacklistedToken,
|
||
PeriodicTask,
|
||
CrontabSchedule,
|
||
IntervalSchedule,
|
||
SolarSchedule,
|
||
ClockedSchedule,
|
||
):
|
||
_unregister(model)
|