Skip to content

Commit

Permalink
Integrate django unfold theme and dynamic settings
Browse files Browse the repository at this point in the history
  • Loading branch information
kdsuneraavinash committed Jan 29, 2025
1 parent 3302230 commit 5a14708
Show file tree
Hide file tree
Showing 14 changed files with 329 additions and 260 deletions.
114 changes: 114 additions & 0 deletions apps/dashboard/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
from django.contrib import admin
from django.contrib.sites.admin import SiteAdmin as BaseSiteAdmin
from django.contrib.sites.models import Site
from django.utils.translation import gettext_lazy as _
from django_celery_beat.admin import ClockedScheduleAdmin as BaseClockedScheduleAdmin
from django_celery_beat.admin import CrontabScheduleAdmin as BaseCrontabScheduleAdmin
from django_celery_beat.admin import PeriodicTaskAdmin as BasePeriodicTaskAdmin
from django_celery_beat.admin import PeriodicTaskForm, TaskSelectWidget
from django_celery_beat.models import (
ClockedSchedule,
CrontabSchedule,
IntervalSchedule,
PeriodicTask,
SolarSchedule,
)
from django_celery_results.admin import GroupResultAdmin as BaseGroupResultAdmin
from django_celery_results.admin import TaskResultAdmin as BaseTaskResultAdmin
from django_celery_results.models import GroupResult, TaskResult
from dynamic_preferences.admin import GlobalPreferenceAdmin as BaseGlobalPreferenceAdmin
from dynamic_preferences.models import GlobalPreferenceModel
from unfold.admin import ModelAdmin, UnfoldAdminSelectWidget, UnfoldAdminTextInputWidget
from unfold.decorators import display

# --------------------------------------------------------- Celery
# https://unfoldadmin.com/docs/integrations/django-celery-beat/

admin.site.unregister(PeriodicTask)
admin.site.unregister(IntervalSchedule)
admin.site.unregister(CrontabSchedule)
admin.site.unregister(SolarSchedule)
admin.site.unregister(ClockedSchedule)
admin.site.unregister(TaskResult)
admin.site.unregister(GroupResult)


class UnfoldTaskSelectWidget(UnfoldAdminSelectWidget, TaskSelectWidget):
pass


class UnfoldPeriodicTaskForm(PeriodicTaskForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["task"].widget = UnfoldAdminTextInputWidget()
self.fields["regtask"].widget = UnfoldTaskSelectWidget()


@admin.register(PeriodicTask)
class PeriodicTaskAdmin(BasePeriodicTaskAdmin, ModelAdmin):
form = UnfoldPeriodicTaskForm


@admin.register(IntervalSchedule)
class IntervalScheduleAdmin(ModelAdmin):
pass


@admin.register(CrontabSchedule)
class CrontabScheduleAdmin(BaseCrontabScheduleAdmin, ModelAdmin):
pass


@admin.register(SolarSchedule)
class SolarScheduleAdmin(ModelAdmin):
pass


@admin.register(ClockedSchedule)
class ClockedScheduleAdmin(BaseClockedScheduleAdmin, ModelAdmin):
pass


@admin.register(TaskResult)
class TaskResultAdmin(BaseTaskResultAdmin, ModelAdmin):
pass


@admin.register(GroupResult)
class GroupResultAdmin(BaseGroupResultAdmin, ModelAdmin):
pass


# --------------------------------------------------------- Site

admin.site.unregister(Site)


@admin.register(Site)
class SiteAdmin(BaseSiteAdmin, ModelAdmin):
pass


# --------------------------------------------------------- Preferences

admin.site.unregister(GlobalPreferenceModel)


@admin.register(GlobalPreferenceModel)
class GlobalPreferenceAdminAdmin(BaseGlobalPreferenceAdmin, ModelAdmin):
list_display = ["_verbose_name", "_section", "_raw_value", "default_value"]

def has_add_permission(self, request):
return False

@display(description=_("Value"))
def _raw_value(self, obj):
return obj.raw_value

@display(description=_("Name"))
def _verbose_name(self, obj):
return obj.verbose_name

@display(description=_("Section"), label=True)
def _section(self, obj):
return obj.section
3 changes: 3 additions & 0 deletions apps/dashboard/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
class DashboardConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.dashboard"

def ready(self):
from apps.dashboard import preferences # noqa
14 changes: 14 additions & 0 deletions apps/dashboard/preferences.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from dynamic_preferences.preferences import Section
from dynamic_preferences.registries import global_preferences_registry
from dynamic_preferences.types import BooleanPreference

general = Section("General")


@global_preferences_registry.register
class MaintenanceMode(BooleanPreference):
name = "maintenance_mode"
verbose_name = "Maintenance Mode"
help_text = "Whether the site is in maintenance mode"
default = False
section = general
20 changes: 16 additions & 4 deletions apps/users/admin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from config.admin import custom_admin_site
from django.contrib.auth.models import Group
from unfold.admin import ModelAdmin
from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm

User = get_user_model()


@admin.register(User, site=custom_admin_site)
class UserAdmin(BaseUserAdmin):
admin.site.unregister(Group)


@admin.register(User)
class UserAdmin(BaseUserAdmin, ModelAdmin):
form = UserChangeForm
add_form = UserCreationForm
change_password_form = AdminPasswordChangeForm


@admin.register(Group)
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
pass
63 changes: 0 additions & 63 deletions config/admin.py

This file was deleted.

81 changes: 67 additions & 14 deletions config/settings.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from collections import OrderedDict
from pathlib import Path

import environ # noqa
import structlog
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _

# Build paths inside the project like this: ROOT_DIR / 'subdir'.
Expand Down Expand Up @@ -64,8 +64,7 @@

# ---------------------------------------------------------- Apps ------------------------------------------------------
DJANGO_ADMIN_THEME_APPS = [
"admin_interface",
"colorfield",
"unfold",
]
DJANGO_APPS = [
"django.contrib.auth",
Expand All @@ -85,13 +84,12 @@
"dj_rest_auth",
"drf_spectacular",
"django_filters",
"constance",
"constance.backends.database",
"django_celery_results",
"django_celery_beat",
"anymail",
"drf_standardized_errors",
"import_export",
"dynamic_preferences",
]
LOCAL_APPS = [
"apps.dashboard.apps.DashboardConfig",
Expand Down Expand Up @@ -422,10 +420,6 @@
},
}

# ---------------------------------------------------------- Django Constance ------------------------------------------
CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend"
CONSTANCE_CONFIG: OrderedDict = OrderedDict()

# ---------------------------------------------------------- Django Toolbar --------------------------------------------
USE_DEBUG_TOOLBAR = env.bool("USE_DEBUG_TOOLBAR", default=DEBUG)
if USE_DEBUG_TOOLBAR:
Expand Down Expand Up @@ -470,12 +464,71 @@
IMPORT_EXPORT_SKIP_ADMIN_CONFIRM = False

# ---------------------------------------------------------- Django Admin Interface ------------------------------------
ADMIN_MODELS = [
["Authentication/Authorization", ("Group", "User")],
["Background Tasks", ("PeriodicTask", "TaskResult", "GroupResult")],
["Site Settings", ("Theme", "Site", "Config")],
]
LIST_PER_PAGE = 20
UNFOLD = {
"SITE_TITLE": "Administration",
"SITE_HEADER": "IXD Labs",
"SITE_URL": "https://example.com",
"SIDEBAR": {
"navigation": [
{
"title": _("Authentication/Authorization"),
"items": [
{
"title": _("Groups"),
"icon": "person",
"link": reverse_lazy("admin:auth_group_changelist"),
},
{
"title": _("Users"),
"icon": "group",
"link": reverse_lazy("admin:users_user_changelist"),
},
],
},
{
"title": _("Background Tasks"),
"items": [
{
"title": _("Periodic Task"),
"icon": "event_repeat",
"link": reverse_lazy("admin:django_celery_beat_periodictask_changelist"),
},
{
"title": _("Task Result"),
"icon": "source_notes",
"link": reverse_lazy("admin:django_celery_results_groupresult_changelist"),
},
{
"title": _("Group Result"),
"icon": "source_notes",
"link": reverse_lazy("admin:django_celery_results_taskresult_changelist"),
},
],
},
{
"title": _("Site Settings"),
"items": [
{
"title": _("Site"),
"icon": "globe",
"link": reverse_lazy("admin:sites_site_changelist"),
},
{
"title": _("Config"),
"icon": "manufacturing",
"link": reverse_lazy("admin:dynamic_preferences_globalpreferencemodel_changelist"),
},
{
"title": _("API Documentation"),
"icon": "api",
"link": reverse_lazy("api_docs"),
},
],
},
],
},
}

# ---------------------------------------------------------- Celery ----------------------------------------------------

Expand Down
6 changes: 3 additions & 3 deletions config/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
from django.views.generic import RedirectView
from drf_spectacular import views as spec_views
from rest_framework.routers import DefaultRouter

from apps.dashboard.views import DashboardView
from config.admin import custom_admin_site
from config.schema import SpectacularRapiDocView

spectacular_api_view = spec_views.SpectacularAPIView.as_view()
Expand All @@ -21,8 +21,8 @@
# TODO: Register API views here
# Admin site URLs
path("custom-admin/dashboard", DashboardView.as_view(), name="dashboard"),
path("custom-admin/", custom_admin_site.urls),
path("", RedirectView.as_view(pattern_name="custom_admin:index")),
path("custom-admin/", admin.site.urls),
path("", RedirectView.as_view(pattern_name="admin:index")),
# API documentation URLs
path("api-schema/", spectacular_api_view, name="schema"),
path("api/docs/", spectacular_api_docs_view, name="api_docs"),
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ dj-rest-auth==7.0.1
djangorestframework-simplejwt==5.4.0

# ---------------------------------------- Django Admin
django-admin-interface==0.29.4
django-unfold==0.46.0
django-import-export==4.3.4

# ---------------------------------------- Third-Party Integrations
django-anymail==12.0
sentry-sdk==2.20.0
django-constance[database]==4.3.1
django-dynamic-preferences==1.17.0
django-storages[boto3]==1.14.4
celery==5.4.0
django-celery-results==2.5.1
Expand Down
Loading

0 comments on commit 5a14708

Please sign in to comment.