Улучшена обработка ошибок профиля и добавлена админка для LDAP:
1. Убраны редиректы из employee_edit и employee_edit_me - теперь всегда возвращается JSON 2. Добавлена проверка наличия ldap_dn перед обновлением через LDAP в обоих методах (me и partial_update) 3. Зарегистрирована модель LdapSyncState в админке для просмотра состояния синхронизации
This commit is contained in:
parent
8edc856636
commit
7950c40636
@ -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
|
||||
|
||||
@ -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) ----------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user