From 30e6643b6e6e2ec084472e2b8d81e378e18f25ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Thu, 20 Nov 2025 12:57:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=B0?= =?UTF-8?q?=D1=82=20created=5Fat/updated=5Fat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Добавлены явные поля в EmployeeChangeForm для дат с виджетами datetime-local - Переопределен метод save_model для обхода auto_now/auto_now_add - Используется прямое обновление через queryset для изменения неизменяемых полей - Только superuser может редактировать эти поля --- backend/employees/admin.py | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/backend/employees/admin.py b/backend/employees/admin.py index 2da18193..9085e32b 100644 --- a/backend/employees/admin.py +++ b/backend/employees/admin.py @@ -68,6 +68,20 @@ class EmployeeChangeForm(forms.ModelForm): ), required=False, ) + + # Добавляем явные поля для дат, чтобы superuser мог их редактировать + created_at = forms.DateTimeField( + label="Дата создания", + required=False, + widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}), + help_text="Только для superuser" + ) + updated_at = forms.DateTimeField( + label="Дата обновления", + required=False, + widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}), + help_text="Только для superuser" + ) class Meta: model = Employee @@ -93,11 +107,24 @@ class EmployeeChangeForm(forms.ModelForm): "groups", "user_permissions", "last_login", + "created_at", + "updated_at", ) def clean_password(self): # Возвращаем исходное значение (хэш), даже если пользователь ничего не ввёл return self.initial.get("password") + + def save(self, commit=True): + user = super().save(commit=False) + # Если superuser изменил даты, применяем их + if self.cleaned_data.get('created_at'): + user.created_at = self.cleaned_data['created_at'] + if self.cleaned_data.get('updated_at'): + user.updated_at = self.cleaned_data['updated_at'] + if commit: + user.save() + return user # ========================= @@ -228,6 +255,34 @@ class EmployeeAdmin(DjangoUserAdmin): inlines = [EmployeeDepartmentInline,] + def save_model(self, request, obj, form, change): + """ + Переопределяем сохранение, чтобы superuser мог менять created_at/updated_at. + """ + # Если superuser изменил даты, временно отключаем auto_now + if request.user.is_superuser: + if 'created_at' in form.changed_data or 'updated_at' in form.changed_data: + # Сохраняем с update_fields, чтобы обойти auto_now + update_fields = [] + if 'created_at' in form.changed_data: + obj.created_at = form.cleaned_data['created_at'] + update_fields.append('created_at') + if 'updated_at' in form.changed_data: + obj.updated_at = form.cleaned_data['updated_at'] + update_fields.append('updated_at') + + # Сначала сохраняем объект без дат + super().save_model(request, obj, form, change) + + # Потом обновляем даты напрямую через queryset + if update_fields: + Employee.objects.filter(pk=obj.pk).update( + **{field: getattr(obj, field) for field in update_fields} + ) + return + + super().save_model(request, obj, form, change) + @admin.register(Position) class PositionAdmin(SimpleHistoryAdmin):