АРХИТЕКТУРНЫЙ РЕФАКТОРИНГ: ✅ Убрано дублирование логики Chat.participants vs ChatMembership.is_active ✅ Теперь единственный источник истины - ChatMembership.is_active ✅ Исправлен баг с изменением ролей (роли не отображались после изменения) ИЗМЕНЕНИЯ: Backend (viewsets.py): - get_queryset: мигрировано на memberships__is_active=True - create: убрано participants.add, только memberships - leave/remove_member: только is_active=False + left_at - add_member: восстанавливает is_active=True если был False - change_role: явно устанавливает is_active=True + left_at=None Backend (serializers.py): - Убрано поле participants из ChatDetailSerializer - get_participant_details: через memberships.filter(is_active=True) - get_participant_names: через memberships Backend (models.py): - get_participants(): только через ChatMembership.is_active=True - __str__(): получаем участников через memberships - participants помечен как устаревший (в комментариях) Backend (rules.py): - is_member_of_chat: только ChatMembership.is_active=True - has_send_messages_permission: убран fallback на participants Миграции: - Создана 0038: убирает 'owner' из choices, очищает help_text - Исправлены зависимости в requests_app/documents/feed 0010/0014/0006 (заменили __latest__ на конкретную версию 0037) - Создан management command migrate_participants_to_memberships (перенос данных participants → memberships) Frontend: - Добавлено оптимистичное обновление UI при изменении ролей - Детальное логирование для диагностики Тесты: - test_change_role_improved.py: проверка изменения ролей с задержкой - Обновлен test_chat_roles.py Удаление устаревшей документации: - Удалены старые отчеты из docs/ (73 файла) - Сохранены актуальные руководства ИСПРАВЛЕННЫЙ БАГ: До: При изменении роли is_active оставался False → membership не попадал в filter(is_active=True) → исчезал с фронтенда После: Явно устанавливаем is_active=True при любом действии с членством
Communications REST API
REST API для универсальной системы чатов Django.
Структура
communications/api/
├── __init__.py # Документация модуля
├── serializers.py # DRF serializers (Chat, Message, Poll)
├── viewsets.py # DRF ViewSets (CRUD операции)
└── urls.py # URL routing с DRF router
Установка
В текущем проекте (уже настроено):
# api/v1/urls.py
from communications.api.viewsets import ChatViewSet, MessageViewSet, PollViewSet
router.register(r"communications/chats", ChatViewSet, basename="chats")
router.register(r"communications/messages", MessageViewSet, basename="messages")
router.register(r"communications/polls", PollViewSet, basename="polls")
Для standalone использования:
# settings.py
INSTALLED_APPS = [
'rest_framework',
'communications',
]
# urls.py
from django.urls import path, include
from communications.api.urls import router as communications_router
urlpatterns = [
path('api/communications/', include(communications_router.urls)),
]
API Endpoints
Chats
GET /api/v1/communications/chats/- список чатовGET /api/v1/communications/chats/{id}/- детали чатаPOST /api/v1/communications/chats/- создать чатPOST /api/v1/communications/chats/{id}/pin/- закрепить/открепитьPOST /api/v1/communications/chats/{id}/notifications/- вкл/выкл уведомленияGET /api/v1/communications/chats/{id}/messages/- список сообщений (с автоотметкой)GET /api/v1/communications/chats/{id}/messages_around/- сообщения вокруг (с автоотметкой)
Messages
GET /api/v1/communications/messages/- список сообщенийGET /api/v1/communications/messages/{id}/- детали сообщенияPOST /api/v1/communications/messages/- отправить сообщениеPATCH /api/v1/communications/messages/{id}/- редактировать сообщениеDELETE /api/v1/communications/messages/{id}/- удалить сообщениеPOST /api/v1/communications/messages/{id}/forward/- переслатьPOST /api/v1/communications/messages/{id}/react/- реакцияPOST /api/v1/communications/messages/bulk_delete/- массовое удалениеGET /api/v1/communications/messages/search/- поиск
Polls
GET /api/v1/communications/polls/- список голосованийGET /api/v1/communications/polls/{id}/- детали голосованияPOST /api/v1/communications/polls/- создать голосованиеPOST /api/v1/communications/polls/{id}/vote/- проголосоватьPOST /api/v1/communications/polls/{id}/close_poll/- закрыть голосование
Serializers
Chat Serializers
ChatListSerializer- облегченный список чатовChatDetailSerializer- детальная информация о чатеChatMembershipSerializer- членство в чатеChatUserSettingsSerializer- настройки пользователя
Message Serializers
MessageListSerializer- список сообщенийMessageDetailSerializer- детали сообщенияMessageCreateSerializer- создание сообщенияMessageEditSerializer- редактированиеMessageAttachmentSerializer- вложенияMessageReactionSerializer- реакцииForwardMessageSerializer- пересылкаBulkDeleteSerializer- массовое удаление
Poll Serializers
PollSerializer- голосованиеPollOptionSerializer- варианты ответа
Новые поля (GenericFK)
Все serializers поддерживают универсальную систему с GenericForeignKey:
{
"id": 1,
"name": "Чат отдела",
# NEW: универсальные поля
"context_object_id": 5, # ID связанного объекта
"context_type": "department", # Тип объекта
"context_app": "employees", # Приложение
"flags": {"is_primary": true}, # JSON флаги
"extra_data": {}, # Дополнительные данные
"include_all_users": false, # Доступ для всех
# DEPRECATED: для обратной совместимости
"is_main": true,
"department": 5
}
Примеры использования
Получить список чатов:
import requests
response = requests.get(
'http://localhost:8000/api/v1/communications/chats/',
headers={'Authorization': 'Bearer <token>'}
)
chats = response.json()
Отправить сообщение:
response = requests.post(
'http://localhost:8000/api/v1/communications/messages/',
json={
'chat': 1,
'content': 'Привет!',
'message_type': 'text'
},
headers={'Authorization': 'Bearer <token>'}
)
Создать чат с GenericFK:
from communications.api.serializers import ChatDetailSerializer
from communications.models import Chat
from employees.models import Department
dept = Department.objects.get(id=5)
chat = Chat.objects.create(
name="Новый чат",
type="department",
context_object=dept, # GenericFK
flags={"is_primary": True}
)
Тестирование
# System check
python manage.py check
# Запуск тестов
python test_phase3.py
# Unit-тесты (если настроены)
pytest communications/tests/
История
- 11 марта 2026: Перенесен из
api/v1/communications/для автономности - Январь 2026: Миграция с FBV на ViewSets
- Фаза 3: Добавлена поддержка GenericFK (context_object, flags, extra_data)
Документация
Поддержка
- Обратная совместимость: ✅ Сохранена для
department,is_main - Django: 5.2.4+
- DRF: 3.14+
- Python: 3.12+