Chat — Views¶
Overview¶
The view layer in the chat app exposes the HTTP API for chat workflows.
It is responsible for:
- listing conversations
- creating conversations
- listing message history
- uploading attachments
- marking conversations as read
- listing and managing participants
- editing and deleting messages
The view layer should remain thin.
Its job is to:
- authenticate the request
- resolve org context where needed
- validate request payloads
- call service functions
- translate service errors into HTTP responses
- return serialized data
Business workflow logic belongs in services, not in views.
View structure¶
The chat views are split into focused modules:
views/conversations.pyviews/messages.pyviews/attachments.pyviews/participants.pyviews/read_state.py
This structure mirrors the service and serializer layers and makes the API easier to understand.
views/conversations.py¶
This module exposes conversation list and creation endpoints.
Main endpoints¶
- internal org conversation list
- customer org conversation list
- create conversation
Responsibilities¶
- enforce authentication
- enforce org or customer-org scoping
- validate conversation creation payloads
- call conversation services
- serialize conversation responses
Main view classes¶
ConversationsInOrgViewConversationsInCustomerOrgViewCreateConversationView
Internal conversation list¶
This endpoint lists conversations for the current internal org.
Responsibilities¶
- require
HasCurrentOrg - list conversations for
request.org - return frontend-friendly conversation summaries
Response shape¶
Typically includes:
- conversation metadata
- unread count
- participant count
- last message preview
Customer conversation list¶
This endpoint lists conversations for the current customer org.
Responsibilities¶
- require
HasCurrentCustomerOrg - list conversations for
request.customer_org - return frontend-friendly conversation summaries
Create conversation¶
This endpoint creates a conversation from the internal side.
Responsibilities¶
- require internal org scope
- validate
customer_org_id - call conversation creation service
- return created conversation
Business rule¶
The view does not decide whether the customer org is linked.
That is handled in the service layer.
views/messages.py¶
This module exposes message history and message mutation endpoints.
Main endpoints¶
- list messages
- edit message
- delete message
Main view classes¶
MessagesViewEditMessageViewDeleteMessageView
List messages¶
Returns paginated message history for a conversation.
Responsibilities¶
- ensure user is a valid participant
- read pagination inputs such as:
limitbefore- call message listing service
- return:
itemsnext_before
Pagination model¶
The endpoint uses cursor-like pagination by timestamp.
The backend returns messages in oldest-to-newest order within the returned page.
Why this matters¶
This is especially useful for chat UIs because the frontend can:
- load recent messages
- request older history when scrolling upward
Edit message¶
Allows the sender to edit a message.
Responsibilities¶
- validate payload
- call message edit service
- translate validation and permission errors
- return updated message
Business rules¶
The sender-only rule is enforced in services, not in the view.
Delete message¶
Soft-deletes a message.
Responsibilities¶
- call message delete service
- translate validation and permission errors
- return updated message payload
Business rules¶
Only the sender may delete their own message.
The delete is soft-delete, not hard-delete.
views/attachments.py¶
This module exposes attachment upload.
Main endpoint¶
- upload attachment to a conversation
Main view class¶
UploadAttachmentView
Responsibilities¶
- require authentication
- parse multipart/form-data
- call attachment upload service
- map service errors to HTTP responses
- return serialized attachment metadata
Why this matters¶
This endpoint supports the upload-first workflow:
- upload file
- receive attachment ID
- send message later using that attachment ID
This is especially helpful for web and mobile clients.
views/participants.py¶
This module exposes participant membership endpoints.
Main endpoints¶
- list participants
- add participant
- remove participant
Main view classes¶
ListParticipantsViewAddParticipantViewRemoveParticipantView
List participants¶
Returns active participants in a conversation.
Responsibilities¶
- require authentication
- ensure requester is an active participant
- return participant metadata
Typical response data¶
- user id
- username
- display name
- role
- last read timestamp
- join timestamp
Add participant¶
Adds or reactivates a participant in a conversation.
Responsibilities¶
- validate request payload
- call participant add service
- map permission and validation errors
- return created or reactivated participant
Business rules¶
The service layer decides:
- whether the actor may add participants
- whether the target user belongs to an allowed org side
Remove participant¶
Removes a participant by setting is_active=False.
Responsibilities¶
- require authentication
- call participant removal service
- return success response
Notes¶
This is a deactivation operation, not a hard delete.
views/read_state.py¶
This module exposes read-state operations.
Main endpoint¶
- mark a conversation as read
Main view class¶
MarkReadView
Responsibilities¶
- require authentication
- call read-state service
- update participant read cursor
- return updated timestamp
Why this matters¶
This endpoint powers unread counts and allows the frontend to sync the user’s read position.
Permissions and scoping¶
The chat app uses a mix of:
- authentication
- org scoping
- participant-based service checks
Common permission patterns¶
Internal conversation endpoints¶
Use:
IsAuthenticatedHasCurrentOrg
Customer conversation endpoints¶
Use:
IsAuthenticatedHasCurrentCustomerOrg
Participant-scoped endpoints¶
Most message, attachment, participant, and read-state endpoints use:
IsAuthenticated
Then participant access is enforced by services.
Error handling¶
Views translate service-layer exceptions into HTTP responses.
Typical mappings include:
400 Bad Request- invalid payload
- invalid upload
-
invalid business input
-
403 Forbidden - user not allowed
- user not participant
-
sender-only action violation
-
404 Not Found - message not found
-
conversation not found
-
201 Created - conversation created
-
attachment uploaded
-
200 OK - list success
- edit/delete success
- mark read success
- participant add/remove success
This keeps services transport-agnostic and views responsible for HTTP semantics.
Core HTTP flows¶
Conversation list flow¶
Main steps¶
- authenticate request
- resolve org context
- call conversation list service
- serialize list items
- return response
Mermaid flow¶
flowchart TD
A[GET conversations] --> B[Auth + org scope]
B --> C[Conversation service]
C --> D[ConversationListSerializer]
D --> E[HTTP 200 response]
¶
flowchart TD
A[GET conversations] --> B[Auth + org scope]
B --> C[Conversation service]
C --> D[ConversationListSerializer]
D --> E[HTTP 200 response]Create conversation flow¶
Main steps¶
- authenticate request
- resolve internal org context
- validate request payload
- call create conversation service
- serialize conversation
- return response
Mermaid flow¶
flowchart TD
A[POST create conversation] --> B[Auth + HasCurrentOrg]
B --> C[ConversationCreateSerializer]
C --> D[create_conversation service]
D --> E[ConversationSerializer]
E --> F[HTTP 201 response]
¶
flowchart TD
A[POST create conversation] --> B[Auth + HasCurrentOrg]
B --> C[ConversationCreateSerializer]
C --> D[create_conversation service]
D --> E[ConversationSerializer]
E --> F[HTTP 201 response]Message history flow¶
Main steps¶
- authenticate request
- read limit and before
- call list messages service
- serialize message list
- return items and next_before
Mermaid flow
flowchart TD
A[GET messages] --> B[Auth]
B --> C[Read query params]
C --> D[list_messages service]
D --> E[MessageSerializer]
E --> F[Return items + next_before]
¶
flowchart TD
A[GET messages] --> B[Auth]
B --> C[Read query params]
C --> D[list_messages service]
D --> E[MessageSerializer]
E --> F[Return items + next_before]Attachment upload flow¶
Main steps¶
- authenticate request
- parse multipart payload
- call upload attachment service
- serialize attachment
- return 201 response
Mermaid flow¶
flowchart TD
A[POST upload attachment] --> B[Auth]
B --> C[Parse multipart file]
C --> D[upload_attachment service]
D --> E[MessageAttachmentSerializer]
E --> F[HTTP 201 response]
¶
flowchart TD
A[POST upload attachment] --> B[Auth]
B --> C[Parse multipart file]
C --> D[upload_attachment service]
D --> E[MessageAttachmentSerializer]
E --> F[HTTP 201 response]Edit message flow¶
Main steps¶
- authenticate request
- validate edit payload
- call edit message service
- serialize updated message
- return response
Mermaid flow¶
flowchart TD
A[POST edit message] --> B[Auth]
B --> C[MessageEditSerializer]
C --> D[edit_message service]
D --> E[MessageSerializer]
E --> F[HTTP 200 response]
¶
flowchart TD
A[POST edit message] --> B[Auth]
B --> C[MessageEditSerializer]
C --> D[edit_message service]
D --> E[MessageSerializer]
E --> F[HTTP 200 response]Delete message flow¶
Main steps¶
- authenticate request
- call delete message service
- serialize updated message
- return response
Mermaid flow¶
flowchart TD
A[POST delete message] --> B[Auth]
B --> C[delete_message service]
C --> D[MessageSerializer]
D --> E[HTTP 200 response]
Participant management flow¶
Add participant¶
- authenticate request
- validate add payload
- call participant add service
- serialize participant
- return response
Remove participant¶
- authenticate request
- call remove participant service
- return success response
Mermaid flow¶
flowchart TD
A[POST add participant] --> B[Auth]
B --> C[AddParticipantSerializer]
C --> D[add_participant service]
D --> E[ParticipantSerializer]
E --> F[HTTP 200 response]
¶
flowchart TD
A[POST add participant] --> B[Auth]
B --> C[AddParticipantSerializer]
C --> D[add_participant service]
D --> E[ParticipantSerializer]
E --> F[HTTP 200 response]Read-state flow¶
Main steps¶
- authenticate request
- call mark read service
- return updated read timestamp
Mermaid flow¶
flowchart TD
A[POST mark read] --> B[Auth]
B --> C[mark_conversation_read service]
C --> D[Return last_read_at]
D --> E[HTTP 200 response]
¶
flowchart TD
A[POST mark read] --> B[Auth]
B --> C[mark_conversation_read service]
C --> D[Return last_read_at]
D --> E[HTTP 200 response]Responsibilities by layer¶
View layer owns¶
- request parsing
- serializer invocation
- permission wiring
- HTTP status mapping
- response construction
Service layer owns¶
- conversation rules
- participant checks
- message workflows
- attachment lifecycle
- unread/read logic
- notification hooks
Serializer layer owns¶
- payload validation
- response shaping
Consumer layer owns¶
- realtime websocket delivery
- websocket event parsing
- channel-layer broadcasting
What views do not do¶
Views do not:
- compute unread counts directly
- determine participant eligibility directly
- attach uploaded files directly
- persist messages directly
- enforce sender-only edit/delete directly
- send notifications directly
- broadcast websocket events
Those responsibilities belong to:
- services
- consumers
Frontend readiness¶
The view split is an important step toward frontend readiness.
It gives you:
- clear endpoint ownership
- cleaner API contracts
- more stable response shapes
- easier mapping between REST and websocket responsibilities
- simpler documentation for web and mobile teams
REST responsibilities for frontend¶
REST should handle:
- conversation list
- initial conversation history
- pagination
- upload attachment
- mark read
- participant management
- edit/delete actions
Websocket responsibilities for frontend¶
Websocket should handle:
- realtime incoming messages
- typing indicators
- future live edits/deletes/read updates if added
Design principles¶
Thin controllers¶
Views should orchestrate, not own workflow logic.
Explicit endpoint boundaries¶
Each endpoint group should map clearly to one domain area:
- conversations
- messages
- attachments
- participants
- read state
Stable response contracts¶
Views should return predictable shapes for frontend integration.
Service-driven behavior¶
All business decisions should come from services.
Best practices¶
- keep views small and explicit
- use dedicated serializers for write actions
- map service exceptions cleanly to HTTP responses
- keep participant validation out of inline view code
- keep org-scoped endpoints explicit
- avoid duplicating workflow logic across views and consumers
Future extensions¶
Possible future view improvements include:
- message create via REST in addition to websocket
- conversation detail endpoint
- conversation close/reopen endpoints
- archive or mute conversation endpoints
- message search endpoint
- attachment list endpoint
- presence/read receipt endpoints
Summary¶
The chat view layer exposes the HTTP API for:
- conversations
- messages
- attachments
- participants
- read state
It ensures the app is:
- cleanly structured
- easy to test
- easier to document
- much more ready for frontend integration