# Refactoring team views
* refactors team views * split views.py into users.py and teams.py in users app * refactors method headers for _user_has_permission() * adds method and class comments and documentation to base view classes
This commit is contained in:
12
user/urls.py
12
user/urls.py
@@ -11,7 +11,9 @@ from user.autocomplete.share import ShareUserAutocomplete, ShareTeamAutocomplete
|
||||
from user.autocomplete.team import TeamAdminAutocomplete
|
||||
from user.views.api_token import APITokenView, new_api_token_view
|
||||
from user.views.propagate import PropagateUserView
|
||||
from user.views.views import *
|
||||
from user.views.teams import TeamIndexView, NewTeamView, TeamDetailModalView, EditTeamView, RemoveTeamView, \
|
||||
LeaveTeamView
|
||||
from user.views.users import UserDetailView, NotificationsView, ContactView
|
||||
|
||||
app_name = "user"
|
||||
urlpatterns = [
|
||||
@@ -22,11 +24,11 @@ urlpatterns = [
|
||||
path("token/api/new", new_api_token_view, name="api-token-new"),
|
||||
path("contact/<id>", ContactView.as_view(), name="contact"),
|
||||
path("team/", TeamIndexView.as_view(), name="team-index"),
|
||||
path("team/new", new_team_view, name="team-new"),
|
||||
path("team/new", NewTeamView.as_view(), name="team-new"),
|
||||
path("team/<id>", TeamDetailModalView.as_view(), name="team-data"),
|
||||
path("team/<id>/edit", edit_team_view, name="team-edit"),
|
||||
path("team/<id>/remove", remove_team_view, name="team-remove"),
|
||||
path("team/<id>/leave", leave_team_view, name="team-leave"),
|
||||
path("team/<id>/edit", EditTeamView.as_view(), name="team-edit"),
|
||||
path("team/<id>/remove", RemoveTeamView.as_view(), name="team-remove"),
|
||||
path("team/<id>/leave", LeaveTeamView.as_view(), name="team-leave"),
|
||||
|
||||
# Autocomplete urls
|
||||
path("atcmplt/share/u", ShareUserAutocomplete.as_view(), name="share-user-autocomplete"),
|
||||
|
||||
105
user/views/teams.py
Normal file
105
user/views/teams.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 05.11.25
|
||||
|
||||
"""
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import Http404, HttpRequest
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.utils.message_templates import TEAM_LEFT, TEAM_REMOVED, TEAM_EDITED, TEAM_ADDED
|
||||
from konova.views.base import BaseModalFormView
|
||||
from user.forms.modals.team import LeaveTeamModalForm, RemoveTeamModalForm, EditTeamModalForm, NewTeamModalForm
|
||||
from user.forms.team import TeamDataForm
|
||||
from user.models import Team
|
||||
from user.views.users import UserBaseView
|
||||
|
||||
|
||||
class TeamDetailModalView(LoginRequiredMixin, BaseModalFormView):
|
||||
_FORM_CLS = TeamDataForm
|
||||
_MODEL_CLS = Team
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
|
||||
class TeamIndexView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/team/index.html"
|
||||
_TAB_TITLE = _("Teams")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
context = {
|
||||
"teams": user.shared_teams,
|
||||
"tab_title": self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class BaseTeamView(LoginRequiredMixin, BaseModalFormView):
|
||||
_REDIRECT_URL = "user:team-index"
|
||||
_MODEL_CLS = Team
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# Nothing to check here - just pass the test
|
||||
return True
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# Nothing to check here - just pass the test
|
||||
return True
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
return reverse(self._REDIRECT_URL)
|
||||
|
||||
class NewTeamView(BaseTeamView):
|
||||
_FORM_CLS = NewTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_ADDED
|
||||
|
||||
class EditTeamView(BaseTeamView):
|
||||
_FORM_CLS = EditTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_EDITED
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
team = get_object_or_404(Team, id=kwargs.get("id"))
|
||||
user_is_admin = team.is_user_admin(user)
|
||||
if not user_is_admin:
|
||||
# If user is not an admin, we act as if there is no such team on the database
|
||||
raise Http404()
|
||||
return user_is_admin
|
||||
|
||||
|
||||
class RemoveTeamView(BaseTeamView):
|
||||
_FORM_CLS = RemoveTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_REMOVED
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
team_id = kwargs.get("id")
|
||||
team = get_object_or_404(Team, id=team_id)
|
||||
user_is_admin = team.is_user_admin(user)
|
||||
if not user_is_admin:
|
||||
raise Http404()
|
||||
return True
|
||||
|
||||
class LeaveTeamView(BaseTeamView):
|
||||
_FORM_CLS = LeaveTeamModalForm
|
||||
_MSG_SUCCESS = TEAM_LEFT
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
team_id = kwargs.get("id")
|
||||
team = get_object_or_404(self._MODEL_CLS, id=team_id)
|
||||
is_user_team_member = team.users.filter(id=user.id).exists()
|
||||
if not is_user_team_member:
|
||||
raise Http404()
|
||||
return True
|
||||
81
user/views/users.py
Normal file
81
user/views/users.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.base import BaseView, BaseModalFormView
|
||||
from user.forms.modals.user import UserContactForm
|
||||
from user.forms.user import UserNotificationForm
|
||||
from user.models import User
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import render, redirect
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
|
||||
|
||||
class UserBaseView(BaseView):
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
|
||||
class UserDetailView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/index.html"
|
||||
_TAB_TITLE = _("User settings")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
context = {
|
||||
"user": request.user,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class NotificationsView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/notifications.html"
|
||||
_TAB_TITLE = _("User notifications")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=None)
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(
|
||||
request,
|
||||
_("Notifications edited")
|
||||
)
|
||||
return redirect("user:detail")
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class ContactView(LoginRequiredMixin, BaseModalFormView):
|
||||
_FORM_CLS = UserContactForm
|
||||
_MODEL_CLS = User
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
@@ -1,206 +0,0 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse
|
||||
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.views.base import BaseView, BaseModalFormView
|
||||
from user.forms.modals.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
|
||||
from user.forms.modals.user import UserContactForm
|
||||
from user.forms.team import TeamDataForm
|
||||
from user.forms.user import UserNotificationForm
|
||||
from user.models import User, Team
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import login_required_modal
|
||||
|
||||
|
||||
class UserBaseView(BaseView):
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
return True
|
||||
|
||||
|
||||
class UserDetailView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/index.html"
|
||||
_TAB_TITLE = _("User settings")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
context = {
|
||||
"user": request.user,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class NotificationsView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/notifications.html"
|
||||
_TAB_TITLE = _("User notifications")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=None)
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def post(self, request: HttpRequest):
|
||||
user = request.user
|
||||
form = UserNotificationForm(user=user, data=request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(
|
||||
request,
|
||||
_("Notifications edited")
|
||||
)
|
||||
return redirect("user:detail")
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
class ContactView(LoginRequiredMixin, BaseModalFormView):
|
||||
def get(self, request: HttpRequest, id: str):
|
||||
""" Renders contact modal view of a users contact data
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The user's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
user = get_object_or_404(User, id=id)
|
||||
form = UserContactForm(request.POST or None, instance=user, request=request)
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
|
||||
class TeamDetailModalView(LoginRequiredMixin, BaseModalFormView):
|
||||
def get(self, request: HttpRequest, id: str):
|
||||
""" Renders team data
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The team's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
team = get_object_or_404(Team, id=id)
|
||||
form = TeamDataForm(request.POST or None, instance=team, request=request)
|
||||
context = {
|
||||
"form": form,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
def _user_has_permission(self, user):
|
||||
# No specific constraints
|
||||
return True
|
||||
|
||||
|
||||
class TeamIndexView(LoginRequiredMixin, UserBaseView):
|
||||
_TEMPLATE = "user/team/index.html"
|
||||
_TAB_TITLE = _("Teams")
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
user = request.user
|
||||
context = {
|
||||
"teams": user.shared_teams,
|
||||
"tab_title": self._TAB_TITLE,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, self._TEMPLATE, context)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def new_team_view(request: HttpRequest):
|
||||
form = NewTeamModalForm(request.POST or None, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("New team added"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def edit_team_view(request: HttpRequest, id: str):
|
||||
team = get_object_or_404(Team, id=id)
|
||||
user_is_admin = team.is_user_admin(request.user)
|
||||
if not user_is_admin:
|
||||
raise Http404()
|
||||
form = EditTeamModalForm(request.POST or None, instance=team, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("Team edited"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def remove_team_view(request: HttpRequest, id: str):
|
||||
team = get_object_or_404(Team, id=id)
|
||||
user_is_admin = team.is_user_admin(request.user)
|
||||
if not user_is_admin:
|
||||
raise Http404()
|
||||
form = RemoveTeamModalForm(request.POST or None, instance=team, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("Team removed"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def leave_team_view(request: HttpRequest, id: str):
|
||||
team = get_object_or_404(Team, id=id)
|
||||
user = request.user
|
||||
|
||||
is_user_team_member = team.users.filter(id=user.id).exists()
|
||||
if not is_user_team_member:
|
||||
messages.info(
|
||||
request,
|
||||
_("You are not a member of this team")
|
||||
)
|
||||
return redirect("user:team-index")
|
||||
|
||||
form = LeaveTeamModalForm(request.POST or None, instance=team, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
_("Left Team"),
|
||||
redirect_url=reverse("user:team-index")
|
||||
)
|
||||
Reference in New Issue
Block a user