Улучшена обработка ошибок профиля и добавлена админка для LDAP:

1. Убраны редиректы из employee_edit и employee_edit_me - теперь всегда возвращается JSON
2. Добавлена проверка наличия ldap_dn перед обновлением через LDAP в обоих методах (me и partial_update)
3. Зарегистрирована модель LdapSyncState в админке для просмотра состояния синхронизации
This commit is contained in:
admin i 2025-12-02 10:13:17 +03:00
parent 8edc856636
commit 7950c40636
2 changed files with 47 additions and 103 deletions

View File

@ -17,6 +17,7 @@ from .models import (
EmployeeDepartment,
Position,
Skill,
LdapSyncState,
)
# =========================
@ -278,3 +279,45 @@ class PermissionAdmin(admin.ModelAdmin):
list_display = ("name", "codename", "content_type")
list_filter = ("content_type",)
search_fields = ("name", "codename")
@admin.register(LdapSyncState)
class LdapSyncStateAdmin(admin.ModelAdmin):
"""Админка для просмотра состояния синхронизации LDAP."""
list_display = (
"model",
"object_pk",
"ldap_dn_short",
"ldap_guid",
"last_sync_dir",
"updated_at",
)
list_filter = ("model", "last_sync_dir")
search_fields = ("object_pk", "ldap_dn", "ldap_guid")
readonly_fields = (
"model",
"object_pk",
"ldap_dn",
"ldap_guid",
"last_ldap_modify_ts",
"last_django_modify_ts",
"last_sync_dir",
"data_hash",
"updated_at",
)
def ldap_dn_short(self, obj):
"""Показываем сокращенную версию DN для удобства."""
if obj.ldap_dn:
return obj.ldap_dn[:50] + "..." if len(obj.ldap_dn) > 50 else obj.ldap_dn
return "-"
ldap_dn_short.short_description = "LDAP DN"
def has_add_permission(self, request):
"""Запрещаем создание вручную."""
return False
def has_delete_permission(self, request, obj=None):
"""Разрешаем удаление для очистки."""
return True

View File

@ -546,58 +546,8 @@ def employee_edit(request, pk: int):
except Exception:
data = {"detail": resp.text}
accepts = (request.headers.get("Accept") or "").lower()
is_ajax = request.headers.get("X-Requested-With") == "XMLHttpRequest"
wants_json = "application/json" in accepts or is_ajax
if wants_json:
return JsonResponse(data or {}, status=resp.status)
if resp.ok:
messages.success(request, "Профиль сотрудника обновлён")
redirect_url = request.META.get("HTTP_REFERER") or reverse(
"employees:employee_profile",
args=(pk,),
)
return redirect(redirect_url)
else:
# При ошибке валидации показываем детали
if resp.status == 400 and isinstance(data, dict):
# Собираем все ошибки валидации
error_messages = []
for field, errors in data.items():
if field == 'detail':
error_messages.append(str(errors))
elif isinstance(errors, list):
field_name = field.replace('_', ' ').title()
for error in errors:
if isinstance(error, dict):
err_str = error.get('string', error)
error_messages.append(f"{field_name}: {err_str}")
else:
error_messages.append(f"{field_name}: {error}")
else:
field_name = field.replace('_', ' ').title()
error_messages.append(f"{field_name}: {errors}")
if error_messages:
for msg in error_messages:
messages.error(request, msg)
else:
messages.error(request, "Ошибка валидации данных")
else:
detail = ""
if isinstance(data, dict):
detail = data.get("detail") or data.get("error") or ""
error_msg = (
detail
or f"Не удалось обновить сотрудника (HTTP {resp.status})"
)
messages.error(request, error_msg)
# Возвращаем на страницу профиля сотрудника
profile_url = reverse("employees:employee_detail", args=(pk,))
return redirect(profile_url)
# Всегда возвращаем JSON без редиректа
return JsonResponse(data or {}, status=resp.status)
# ---------- EDIT ME ----------
@ -692,57 +642,8 @@ def employee_edit_me(request):
except Exception:
data = {"detail": resp.text}
accepts = (request.headers.get("Accept") or "").lower()
is_ajax = request.headers.get("X-Requested-With") == "XMLHttpRequest"
wants_json = "application/json" in accepts or is_ajax
if wants_json:
return JsonResponse(data or {}, status=resp.status)
if resp.ok:
messages.success(request, "Профиль обновлён")
redirect_url = (
request.META.get("HTTP_REFERER")
or reverse("employees:profile")
)
return redirect(redirect_url)
else:
# При ошибке валидации показываем детали
if resp.status == 400 and isinstance(data, dict):
# Собираем все ошибки валидации
error_messages = []
for field, errors in data.items():
if field == 'detail':
error_messages.append(str(errors))
elif isinstance(errors, list):
field_name = field.replace('_', ' ').title()
for error in errors:
if isinstance(error, dict):
err_str = error.get('string', error)
error_messages.append(f"{field_name}: {err_str}")
else:
error_messages.append(f"{field_name}: {error}")
else:
field_name = field.replace('_', ' ').title()
error_messages.append(f"{field_name}: {errors}")
if error_messages:
for msg in error_messages:
messages.error(request, msg)
else:
messages.error(request, "Ошибка валидации данных")
else:
detail = ""
if isinstance(data, dict):
detail = data.get("detail") or data.get("error") or ""
error_msg = (
detail or f"Не удалось обновить профиль (HTTP {resp.status})"
)
messages.error(request, error_msg)
# Возвращаем на страницу профиля (где есть форма редактирования)
profile_url = reverse("employees:profile")
return redirect(profile_url)
# Всегда возвращаем JSON без редиректа
return JsonResponse(data or {}, status=resp.status)
# ---------- CREATE (staff) ----------