feat: requests detail view - stage 2: backend разработка
Этап 2 разработки включает: ✅ Создан RequestDetailView класс в views_front.py: - Наследуется от LoginRequiredMixin, TemplateView - Загружает данные о заявлении через API (/api/v1/requests/{pk}/) - Загружает комментарии к заявлению - Проверяет права доступа (обрабатывает 404, 403) - Форматирует даты для отображения ✅ Обновлены URLs (urls_front.py): - Добавлен маршрут: path('<int:pk>/', RequestDetailView.as_view(), name='request_detail') - Импортирован RequestDetailView ✅ Обновлен шаблон request_detail.html: - Раскомментированы комментарии (были закрыты) - Добавлена обработка ошибок (404, 403) - Оформлено отображение заявления и комментариев - Включен функционал добавления комментариев � URLs в notification_signals.py уже правильные (проверено) Готово для следующего этапа 3: Frontend разработка
This commit is contained in:
parent
92b3b0725a
commit
f19862ec6b
@ -2,6 +2,7 @@
|
||||
from django.urls import path
|
||||
from .views_front import (
|
||||
RequestsView,
|
||||
RequestDetailView,
|
||||
request_comments,
|
||||
request_comment_add,
|
||||
)
|
||||
@ -10,6 +11,7 @@ app_name = "requests"
|
||||
|
||||
urlpatterns = [
|
||||
path("", RequestsView.as_view(), name="request_list"),
|
||||
path("<int:pk>/", RequestDetailView.as_view(), name="request_detail"),
|
||||
path("comments/<int:pk>/", request_comments, name="request_comments"),
|
||||
path(
|
||||
"comments/<int:pk>/add/",
|
||||
|
||||
@ -274,6 +274,81 @@ class RequestsView(LoginRequiredMixin, TemplateView):
|
||||
return ctx
|
||||
|
||||
|
||||
class RequestDetailView(LoginRequiredMixin, TemplateView):
|
||||
"""
|
||||
Детальный просмотр заявления.
|
||||
|
||||
Загружает одно заявление и его комментарии через API.
|
||||
Может быть использовано как для отдельной страницы, так и для модального окна.
|
||||
|
||||
GET /requests/{pk}/:
|
||||
- Загружает заявление через GET /api/v1/requests/{pk}/
|
||||
- Загружает комментарии через GET /api/v1/requests/{pk}/comments/
|
||||
- Проверяет права доступа (делает ошибку если нет прав)
|
||||
|
||||
Контекст:
|
||||
- request_obj: dict с данными заявления
|
||||
- comments: list[dict] с комментариями
|
||||
- can_process: bool - может ли пользователь обрабатывать заявку
|
||||
- error: str - описание ошибки (если она была)
|
||||
- error_code: int - HTTP код ошибки
|
||||
"""
|
||||
|
||||
template_name = "requests_app/request_detail.html"
|
||||
|
||||
def get_context_data(self, pk: int, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""
|
||||
Загружает данные заявления и комментарии.
|
||||
|
||||
Args:
|
||||
pk: ID заявления
|
||||
|
||||
Returns:
|
||||
Dict с контекстом для шаблона
|
||||
"""
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
request = self.request
|
||||
api = get_api_client(request)
|
||||
|
||||
# Загружаем основные данные заявления
|
||||
ok, data, status = _api_unpack(api.get(f"v1/requests/{pk}/"))
|
||||
|
||||
if not ok:
|
||||
# Обработка ошибок (404, 403 и т.д.)
|
||||
error_msg = data.get("detail", f"HTTP {status}")
|
||||
if isinstance(error_msg, list):
|
||||
error_msg = "; ".join(str(e) for e in error_msg)
|
||||
|
||||
ctx.update({
|
||||
"request_obj": None,
|
||||
"comments": [],
|
||||
"can_process": _user_can_process_requests(request.user),
|
||||
"error": error_msg,
|
||||
"error_code": status,
|
||||
})
|
||||
return ctx
|
||||
|
||||
request_data = data
|
||||
|
||||
# Загружаем комментарии
|
||||
comments = []
|
||||
ok_c, data_c, st_c = _api_unpack(api.get(f"v1/requests/{pk}/comments/"))
|
||||
if ok_c:
|
||||
results_c, _, _, _ = _parse_page_payload(data_c)
|
||||
comments = _format_datetime_fields(
|
||||
results_c,
|
||||
fields=("created_at", "updated_at")
|
||||
)
|
||||
|
||||
ctx.update({
|
||||
"request_obj": _format_datetime_fields([request_data], fields=("created_at", "updated_at", "decided_at"))[0],
|
||||
"comments": comments,
|
||||
"can_process": _user_can_process_requests(request.user),
|
||||
})
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
def request_comments(request: HttpRequest, pk: int) -> JsonResponse:
|
||||
"""Прокси: список комментариев (JSON) для заявки.
|
||||
Требует авторизации (используем ту же обёртку клиента, что и основная вью).
|
||||
|
||||
@ -8,7 +8,22 @@
|
||||
<div class="row gx-0">
|
||||
<div class="col-12">
|
||||
|
||||
{# — Шапка — #}
|
||||
{% if error %}
|
||||
{# — Ошибка при загрузке — #}
|
||||
<div class="alert alert-danger mb-3" role="alert">
|
||||
<i class="bi-exclamation-circle"></i>
|
||||
{% if error_code == 404 %}
|
||||
<strong>Заявление не найдено.</strong> Возможно, оно было удалено.
|
||||
{% elif error_code == 403 %}
|
||||
<strong>Доступ запрещен.</strong> Вы не можете просмотреть это заявление.
|
||||
{% else %}
|
||||
<strong>Ошибка при загрузке.</strong> {{ error }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href="{% url 'requests:request_list' %}" class="btn btn-secondary">
|
||||
<i class="bi-arrow-left"></i> К списку заявлений
|
||||
</a>
|
||||
{% elif request_obj %}
|
||||
<div class="section-header">
|
||||
<i class="bi-file-earmark-text fs-2 text-primary"></i>
|
||||
<h2 class="title mb-0">Детали заявления</h2>
|
||||
@ -150,7 +165,12 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</article> -->
|
||||
</article>
|
||||
{% else %}
|
||||
<div class="alert alert-info mb-3" role="alert">
|
||||
Загрузка...
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user