from django import forms from django.contrib import admin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin from django.contrib.auth.models import Group from django.db import models from django.utils.html import format_html from django.utils.translation import gettext_lazy as _, ngettext from rest_framework.authtoken.models import TokenProxy from unfold.admin import ModelAdmin, StackedInline from unfold.decorators import display from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm from unfold.contrib.filters.admin import RangeDateTimeFilter from apps.account.models import User, ClientUser, LocationHistory from utils.admin import project_admin_site from apps.account.admin.location import LocationHistoryInline # ========================================================= # 1. Base User Admin Form & Admin # ========================================================= class UserAdminCreationForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = User fields = ("fullname", "email") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if 'fullname' in self.fields: self.fields['fullname'].required = True if 'email' in self.fields: self.fields['email'].required = True def clean_email(self): email = self.cleaned_data.get('email') if User.objects.filter(email=email).exists(): raise forms.ValidationError(_("A user with this email already exists.")) return email class UserAdminChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = User def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if 'fullname' in self.fields: self.fields['fullname'].required = True if 'email' in self.fields: self.fields['email'].required = True class UserAdmin(ModelAdmin, BaseUserAdmin): form = UserAdminChangeForm add_form = UserAdminCreationForm change_password_form = AdminPasswordChangeForm compressed_fields = False list_display = ('fullname', 'email', 'user_type', 'is_staff', 'is_active', 'display_date_joined',) ordering = ("-id",) search_fields = ('email', 'fullname', 'username',) list_filter = [ "user_type", "is_active", "is_staff", ("last_login", RangeDateTimeFilter), ("date_joined", RangeDateTimeFilter), ] inlines = [LocationHistoryInline] add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': (('fullname', 'email'), 'phone_number', 'birthdate', 'gender', 'avatar', 'skill', 'info'), }), ) fieldsets = ( (None, { "fields": ( ("fullname", "email"), ("password",), ), }), (_("Profile Details"), { "classes": ["tab"], "fields": ( ("avatar",), ("phone_number", "gender"), ("birthdate", "language"), ("skill",), ("info",), ), }), (_("Access & Status"), { "classes": ["tab"], "fields": ( ("user_type",), ("is_active", "is_staff", "is_superuser"), ("groups", "user_permissions"), ), }), (_("Timestamps & Metadata"), { "classes": ["tab"], "fields": ( ("date_joined", "last_login"), ("deleted_at",), ), }), ) readonly_fields = ('date_joined', 'last_login') @display(description=_("Date Joined")) def display_date_joined(self, instance: User): return instance.date_joined.strftime("%Y-%m-%d %H:%M") if instance.date_joined else "-" class GroupAdmin(BaseGroupAdmin, ModelAdmin): list_display = ('name', 'permissions_count') search_fields = ('name',) ordering = ('name',) filter_horizontal = ('permissions',) fieldsets = ( (None, {'fields': ('name',)}), (_('Permissions'), {'fields': ('permissions',), 'classes': ['tab']}), ) @display(description=_("Permissions")) def permissions_count(self, obj): count = obj.permissions.count() return ngettext("{count} permission", "{count} permissions", count).format(count=count) if count > 0 else "-" # ========================================================= # 2. Registrations # ========================================================= try: admin.site.unregister(User) except admin.sites.NotRegistered: pass try: admin.site.register(User, UserAdmin) except admin.sites.AlreadyRegistered: pass project_admin_site.register(User, UserAdmin) project_admin_site.register(Group, GroupAdmin) try: admin.site.unregister(TokenProxy) except admin.sites.NotRegistered: pass