From c6e60d1f3ebed2e499fe28dd33962601e09e7f00 Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Wed, 10 Dec 2025 15:33:58 +0300 Subject: [PATCH] Features: 1) Replace `ModelForm` with `UserChangeForm` in `UserForm`; 2) Add `add_form` and `change_password_form` to `UserAdmin`; 3) Add formfield override for `TextField` with `MarkdownWidget` in blog admin; 4) Add dropdown menu definitions in Unfold settings. Fixes: 1) Add missing import for `AdminPasswordChangeForm`, `UserCreationForm`, and `MarkdownWidget`. Extra: 1) Add `django-unfold-markdown` as a dependency in `uv.lock` and `pyproject.toml`; 2) Remove redundant dropdown configuration from Unfold settings. --- engine/blog/admin.py | 3 +++ engine/vibes_auth/admin.py | 3 +++ engine/vibes_auth/forms.py | 4 ++-- evibes/settings/unfold.py | 30 ++++++++++++++++++++---------- pyproject.toml | 1 + uv.lock | 15 +++++++++++++++ 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/engine/blog/admin.py b/engine/blog/admin.py index c5117a14..a9d790ee 100644 --- a/engine/blog/admin.py +++ b/engine/blog/admin.py @@ -1,6 +1,8 @@ from django.contrib.admin import register +from django.db.models import TextField from django_summernote.admin import SummernoteModelAdminMixin from unfold.admin import ModelAdmin +from unfold_markdown import MarkdownWidget from engine.blog.models import Post, PostTag from engine.core.admin import ActivationActionsMixin, FieldsetsMixin @@ -14,6 +16,7 @@ class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, ActivationActionsMixi filter_horizontal = ("tags",) date_hierarchy = "created" autocomplete_fields = ("tags",) + formfield_overrides = {TextField: {"widget": MarkdownWidget}} readonly_fields = ( "uuid", "slug", diff --git a/engine/vibes_auth/admin.py b/engine/vibes_auth/admin.py index 307c7cf4..2900440f 100644 --- a/engine/vibes_auth/admin.py +++ b/engine/vibes_auth/admin.py @@ -41,6 +41,7 @@ from engine.vibes_auth.models import ( ThreadStatus, User, ) +from unfold.forms import AdminPasswordChangeForm, UserCreationForm class BalanceInline(TabularInline): # type: ignore [type-arg] @@ -108,6 +109,8 @@ class UserAdmin(ActivationActionsMixin, BaseUserAdmin, ModelAdmin): # type: ign ordering = ("email",) readonly_fields = ("password",) form = UserForm + add_form = UserCreationForm + change_password_form = AdminPasswordChangeForm def get_queryset(self, request: HttpRequest) -> QuerySet[User]: qs = super().get_queryset(request) diff --git a/engine/vibes_auth/forms.py b/engine/vibes_auth/forms.py index fd224947..532f4938 100644 --- a/engine/vibes_auth/forms.py +++ b/engine/vibes_auth/forms.py @@ -1,10 +1,10 @@ -from django.forms import ModelForm +from unfold.forms import UserChangeForm from engine.core.widgets import JSONTableWidget from engine.vibes_auth.models import User -class UserForm(ModelForm): # type: ignore [type-arg] +class UserForm(UserChangeForm): # type: ignore [type-arg] class Meta: model = User fields = "__all__" diff --git a/evibes/settings/unfold.py b/evibes/settings/unfold.py index 9e4cb2fb..8bb37309 100644 --- a/evibes/settings/unfold.py +++ b/evibes/settings/unfold.py @@ -22,6 +22,26 @@ UNFOLD: dict[str, Any] = { "SITE_LOGO": "favicon.png", "SITE_ICON": "favicon.ico", "SITE_SYMBOL": "money", + "SITE_DROPDOWN": [ + { + "icon": "diamond", + "title": _("My site"), + "link": f"https://{STOREFRONT_DOMAIN}", + "attrs": { + "target": "_blank", + }, + }, + { + "icon": "health_metrics", + "title": _("Health"), + "link": reverse_lazy("health_check:health_check_home"), + }, + { + "title": _("Support"), + "icon": "contact_support", + "link": SUPPORT_CONTACT, + }, + ], "SHOW_LANGUAGES": True, "SHOW_VIEW_ON_SITE": False, "LOGIN": { @@ -63,11 +83,6 @@ UNFOLD: dict[str, Any] = { "icon": "dashboard", "link": reverse_lazy("admin:index"), }, - { - "title": _("Health"), - "icon": "health_metrics", - "link": reverse_lazy("health_check:health_check_home"), - }, { "title": _("Config"), "icon": "construction", @@ -108,11 +123,6 @@ UNFOLD: dict[str, Any] = { "icon": "book_2", "link": reverse_lazy("django-admindocs-docroot"), }, - { - "title": _("Support"), - "icon": "contact_support", - "link": SUPPORT_CONTACT, - }, ], }, { diff --git a/pyproject.toml b/pyproject.toml index 2cc153e6..0432b03f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ dependencies = [ "django-stubs==5.2.8", "django-summernote==0.8.20.0", "django-unfold==0.73.1", + "django-unfold-markdown==0.1.2", "django-widget-tweaks==1.5.0", "django-md-field==0.1.0", "djangorestframework==3.16.1", diff --git a/uv.lock b/uv.lock index 04fbe638..e9bb3e55 100644 --- a/uv.lock +++ b/uv.lock @@ -1095,6 +1095,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/89/4d5716871f9c7aea6c2a567ac297380efa870c4641641a87b45a7b8587c0/django_unfold-0.73.1-py3-none-any.whl", hash = "sha256:7241275b75f0784a28410afa6bb4660f427eb7b62d48726195b35374887f017d", size = 1216980, upload-time = "2025-12-09T09:11:27.761Z" }, ] +[[package]] +name = "django-unfold-markdown" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "django-unfold" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/c5/3d1e9d43fce9a0b646bf4f40fdce056af45cda39ede35a2d1cdebfb25ddc/django_unfold_markdown-0.1.2.tar.gz", hash = "sha256:6b4d8c627c08901fc6088a4aa85c357510fa4c9e55fcb2e81f2bdf10628076ec", size = 117597, upload-time = "2025-11-30T19:40:02.159Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/6d/c4ded7b49db7e4c8daddafb28b6ec377a5e435879e370e048537342e65c3/django_unfold_markdown-0.1.2-py3-none-any.whl", hash = "sha256:a9614d7eac13c0b6be1288dfe7750987cbb99810372803a880b90b07ee014ce0", size = 119709, upload-time = "2025-11-30T19:40:00.864Z" }, +] + [[package]] name = "django-widget-tweaks" version = "1.5.0" @@ -1351,6 +1364,7 @@ dependencies = [ { name = "django-stubs" }, { name = "django-summernote" }, { name = "django-unfold" }, + { name = "django-unfold-markdown" }, { name = "django-widget-tweaks" }, { name = "djangoql" }, { name = "djangorestframework" }, @@ -1456,6 +1470,7 @@ requires-dist = [ { name = "django-stubs", specifier = "==5.2.8" }, { name = "django-summernote", specifier = "==0.8.20.0" }, { name = "django-unfold", specifier = "==0.73.1" }, + { name = "django-unfold-markdown", specifier = "==0.1.2" }, { name = "django-widget-tweaks", specifier = "==1.5.0" }, { name = "djangoql", specifier = "==0.18.1" }, { name = "djangorestframework", specifier = "==3.16.1" },