Teams — URLs¶
Responsibilities¶
The Teams app URL configuration exposes the HTTP routes for:
- creating, reading, updating, deactivating, and reactivating teams
- listing all active teams in the current org
- listing the current user’s teams
- listing members of a specific team
- listing the current user’s teammates
- adding users to teams
- listing visible team membership pairs
- listing visible richer team membership rows
- updating membership role
- switching primary team membership
- deactivating and reactivating memberships
It is responsible for:
- mapping stable route paths to views
- naming routes for reverse lookups and tests
- grouping team and membership endpoints coherently
It is not responsible for:
- authorization logic
- business rules
- validation
- serialization behavior
Those concerns are handled by:
- permissions
- services
- serializers
- views
Route groups¶
Team routes¶
These routes expose team-level creation, discovery, detail, and lifecycle management.
teams/¶
- Name
teams-create- View
TeamCreateView- Methods
POST- Purpose
- Create a new team in the current organization
- Access
- Privileged org users only (
owner,admin,manager)
teams/all/¶
- Name
teams-all-in-org- View
AllTeamsInOrgView- Methods
GET- Purpose
- Return all active teams in the current organization
- Access
- Privileged org users only (
owner,admin,manager)
teams/my/¶
- Name
teams-my-in-org- View
MyTeamsInOrgView- Methods
GET- Purpose
- Return the active teams the current user belongs to in the current organization
teams/<int:team_id>/¶
- Name
teams-detail- View
TeamDetailView- Methods
GET- Purpose
- Return details for one team in the current organization
- Path params
team_id
teams/<int:team_id>/update/¶
- Name
teams-update- View
TeamUpdateView- Methods
PATCH- Purpose
- Update one team in the current organization
- Path params
team_id- Access
- Privileged org users only (
owner,admin,manager)
teams/<int:team_id>/deactivate/¶
- Name
teams-deactivate- View
TeamDeactivateView- Methods
POST- Purpose
- Deactivate one team in the current organization
- Path params
team_id- Access
- Privileged org users only (
owner,admin,manager)
teams/<int:team_id>/reactivate/¶
- Name
teams-reactivate- View
TeamReactivateView- Methods
POST- Purpose
- Reactivate one team in the current organization
- Path params
team_id- Access
- Privileged org users only (
owner,admin,manager)
Membership and visibility routes¶
These routes expose team-member visibility and membership management data.
teams/my/members/¶
- Name
teams-my-members-in-org- View
MyTeamMembersInOrgView- Methods
GET- Purpose
- Return users who share at least one team with the current user in the current org
teams/<int:team_id>/members/¶
- Name
teams-members-by-team- View
TeamMembersByTeamView- Methods
GET- Purpose
- Return active members of a specific team in the current org
- Path params
team_id
Visibility rules - Privileged org users can view any team in the org - Non-privileged users can only view teams they belong to
teams/<int:team_id>/members/add/¶
- Name
teams-membership-create- View
TeamMembershipCreateView- Methods
POST- Purpose
- Add a user to a specific team
- Path params
team_id- Access
- Privileged org users only (
owner,admin,manager)
teams/memberships/pairs/¶
- Name
teams-membership-pairs-in-org- View
TeamMembershipPairsInOrgView- Methods
GET- Purpose
- Return compact visible membership pairs (
team_id,user_id) in the current org
teams/memberships/¶
- Name
teams-memberships-in-org- View
TeamMembershipsInOrgView- Methods
GET- Purpose
- Return richer visible team membership rows in the current org
teams/memberships/<int:membership_id>/role/¶
- Name
teams-membership-role-update- View
TeamMembershipRoleUpdateView- Methods
PATCH- Purpose
- Change the role of a specific team membership
- Path params
membership_id- Access
- Privileged org users only (
owner,admin,manager)
teams/memberships/<int:membership_id>/primary/¶
- Name
teams-membership-primary-update- View
TeamMembershipPrimaryUpdateView- Methods
POST- Purpose
- Set a specific membership as the user’s primary team membership
- Path params
membership_id- Access
- Privileged org users only (
owner,admin,manager)
teams/memberships/<int:membership_id>/deactivate/¶
- Name
teams-membership-deactivate- View
TeamMembershipDeactivateView- Methods
POST- Purpose
- Deactivate a specific team membership
- Path params
membership_id- Access
- Privileged org users only (
owner,admin,manager)
teams/memberships/<int:membership_id>/reactivate/¶
- Name
teams-membership-reactivate- View
TeamMembershipReactivateView- Methods
POST- Purpose
- Reactivate a specific team membership
- Path params
membership_id- Access
- Privileged org users only (
owner,admin,manager)
URL relationships¶
flowchart TD
URLConf["teams/urls.py"]
TeamRoutes["Team routes"]
MembershipRoutes["Membership routes"]
URLConf --> TeamRoutes
URLConf --> MembershipRoutes
TeamRoutes --> TeamCreateView["TeamCreateView"]
TeamRoutes --> AllTeamsInOrgView["AllTeamsInOrgView"]
TeamRoutes --> MyTeamsInOrgView["MyTeamsInOrgView"]
TeamRoutes --> TeamDetailView["TeamDetailView"]
TeamRoutes --> TeamUpdateView["TeamUpdateView"]
TeamRoutes --> TeamDeactivateView["TeamDeactivateView"]
TeamRoutes --> TeamReactivateView["TeamReactivateView"]
MembershipRoutes --> MyTeamMembersInOrgView["MyTeamMembersInOrgView"]
MembershipRoutes --> TeamMembersByTeamView["TeamMembersByTeamView"]
MembershipRoutes --> TeamMembershipCreateView["TeamMembershipCreateView"]
MembershipRoutes --> TeamMembershipPairsInOrgView["TeamMembershipPairsInOrgView"]
MembershipRoutes --> TeamMembershipsInOrgView["TeamMembershipsInOrgView"]
MembershipRoutes --> TeamMembershipRoleUpdateView["TeamMembershipRoleUpdateView"]
MembershipRoutes --> TeamMembershipPrimaryUpdateView["TeamMembershipPrimaryUpdateView"]
MembershipRoutes --> TeamMembershipDeactivateView["TeamMembershipDeactivateView"]
MembershipRoutes --> TeamMembershipReactivateView["TeamMembershipReactivateView"]
¶
flowchart TD
URLConf["teams/urls.py"]
TeamRoutes["Team routes"]
MembershipRoutes["Membership routes"]
URLConf --> TeamRoutes
URLConf --> MembershipRoutes
TeamRoutes --> TeamCreateView["TeamCreateView"]
TeamRoutes --> AllTeamsInOrgView["AllTeamsInOrgView"]
TeamRoutes --> MyTeamsInOrgView["MyTeamsInOrgView"]
TeamRoutes --> TeamDetailView["TeamDetailView"]
TeamRoutes --> TeamUpdateView["TeamUpdateView"]
TeamRoutes --> TeamDeactivateView["TeamDeactivateView"]
TeamRoutes --> TeamReactivateView["TeamReactivateView"]
MembershipRoutes --> MyTeamMembersInOrgView["MyTeamMembersInOrgView"]
MembershipRoutes --> TeamMembersByTeamView["TeamMembersByTeamView"]
MembershipRoutes --> TeamMembershipCreateView["TeamMembershipCreateView"]
MembershipRoutes --> TeamMembershipPairsInOrgView["TeamMembershipPairsInOrgView"]
MembershipRoutes --> TeamMembershipsInOrgView["TeamMembershipsInOrgView"]
MembershipRoutes --> TeamMembershipRoleUpdateView["TeamMembershipRoleUpdateView"]
MembershipRoutes --> TeamMembershipPrimaryUpdateView["TeamMembershipPrimaryUpdateView"]
MembershipRoutes --> TeamMembershipDeactivateView["TeamMembershipDeactivateView"]
MembershipRoutes --> TeamMembershipReactivateView["TeamMembershipReactivateView"]
Routing style¶
The Teams app uses explicit path(...) routes rather than a router.
This is appropriate because:
- the number of endpoints is still moderate and well-bounded
- endpoints are not standard CRUD-only resources
- route names are heavily used in tests
- several membership routes are action-oriented rather than plain modelset actions
Current-org dependency¶
All team routes are scoped to the current organization and should be used with request org context already resolved.
That generally means requests include:
X-ORG-ID- optionally
X-ORG-SLUG
And the views rely on:
HasCurrentOrg
Without current-org context:
- requests may fail with
400or403 - or the view may never reach team-level logic
Reverse lookup examples¶
Team routes¶
reverse("teams-create")reverse("teams-all-in-org")reverse("teams-my-in-org")reverse("teams-detail", kwargs={"team_id": ...})reverse("teams-update", kwargs={"team_id": ...})reverse("teams-deactivate", kwargs={"team_id": ...})reverse("teams-reactivate", kwargs={"team_id": ...})
Membership routes¶
reverse("teams-my-members-in-org")reverse("teams-members-by-team", kwargs={"team_id": ...})reverse("teams-membership-create", kwargs={"team_id": ...})reverse("teams-membership-pairs-in-org")reverse("teams-memberships-in-org")reverse("teams-membership-role-update", kwargs={"membership_id": ...})reverse("teams-membership-primary-update", kwargs={"membership_id": ...})reverse("teams-membership-deactivate", kwargs={"membership_id": ...})reverse("teams-membership-reactivate", kwargs={"membership_id": ...})
URL design notes¶
1. teams/ prefix is kept stable¶
All routes are grouped under teams/ for consistency and discoverability.
This keeps the app easy to reason about and prevents route sprawl.
2. Team vs membership routes are separated¶
There is a natural split between:
- team management and listing routes
- membership visibility and management routes
That split mirrors the app structure:
views/teams.pyviews/memberships.py
3. Compact and rich membership endpoints both exist intentionally¶
The app exposes two membership list styles:
Compact¶
teams/memberships/pairs/
Rich¶
teams/memberships/
This avoids forcing every client to fetch heavier payloads when only graph-style IDs are needed.
4. Team-member visibility is addressed directly¶
The route:
teams/<team_id>/members/
is intentionally explicit and reads naturally from a client perspective.
It also keeps permission logic simple:
- resolve one team
- validate visibility
- return members
5. Management actions are explicit¶
Rather than hiding important team and membership mutations behind overloaded generic endpoints, the app uses explicit action routes such as:
teams/<team_id>/deactivate/teams/memberships/<membership_id>/primary/
This keeps intent clear and improves test readability.