Kod źródłowy modułu poradnia.users.views

import re

from ajax_datatable import AjaxDatatableView
from atom.views import ActionMessageMixin, ActionView
from braces.views import LoginRequiredMixin, StaffuserRequiredMixin, UserFormKwargsMixin
from dal import autocomplete
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, RedirectView, TemplateView, UpdateView
from django_filters.views import FilterView

from poradnia.cases.models import Case, CaseUserObjectPermission
from poradnia.utils.mixins import ExprAutocompleteMixin

from .filters import UserFilter
from .forms import ProfileForm, UserForm
from .models import Profile, User
from .utils import PermissionMixin


[dokumentacja] class UserDetailView(PermissionRequiredMixin, DetailView): model = User slug_field = "username" slug_url_kwarg = "username" permission_required = "users.can_view_other" raise_exception = True
[dokumentacja] def has_permission(self, *args, **kwargs): if self.kwargs["username"] == self.request.user.username: return True return super().has_permission(*args, **kwargs)
def handle_no_permission(self): if self.request.user.is_authenticated: url = reverse( "users:user_info", kwargs={"username": self.kwargs["username"]} ) return HttpResponseRedirect(url) else: raise PermissionDenied
[dokumentacja] class UserInfoView(DetailView): model = User slug_field = "username" slug_url_kwarg = "username" template_name = "users/user_info.html" fields = ["picture", "profile"]
[dokumentacja] def get_queryset(self): queryset = super().get_queryset() return queryset.only(*self.fields)
[dokumentacja] class UserRedirectView(LoginRequiredMixin, RedirectView): permanent = False
[dokumentacja] def get_redirect_url(self): return reverse("users:detail", kwargs={"username": self.request.user.username})
[dokumentacja] class UserUpdateView(LoginRequiredMixin, UpdateView): form_class = UserForm # we already imported User in the view code above, remember? model = User # send the user back to their own page after a successful update
[dokumentacja] def get_success_url(self): return reverse("users:detail", kwargs={"username": self.request.user.username})
[dokumentacja] def get_object(self): # Only get the User record for the user making the request return User.objects.get(username=self.request.user.username)
[dokumentacja] class ProfileUpdateView(UserFormKwargsMixin, LoginRequiredMixin, UpdateView): form_class = ProfileForm model = Profile
[dokumentacja] def get_success_url(self): return reverse("users:detail", kwargs={"username": self.request.user.username})
[dokumentacja] def get_object(self): # Only get the User record for the user making the request return Profile.objects.get_or_create(user=self.request.user)[0]
[dokumentacja] class UserListView(StaffuserRequiredMixin, PermissionMixin, FilterView): model = User slug_field = "username" slug_url_kwarg = "username" filterset_class = UserFilter paginate_by = 25 IS_STAFF_FILTER = ( (_("All users"), {}), (_("Staff"), {"is_staff": True}), ((_("Clients"), {"is_staff": False})), ) def get_is_staff_choice(self): if "is_staff" not in self.request.GET: return 0 if not self.request.GET["is_staff"].isdigit(): return 0 num = int(self.request.GET["is_staff"]) if len(self.IS_STAFF_FILTER) < num: return 0 return num
[dokumentacja] def get_queryset(self, *args, **kwargs): qs = super().get_queryset(*args, **kwargs) qs = qs.filter(**self.IS_STAFF_FILTER[self.get_is_staff_choice()][1]) qs = qs.with_case_count() qs = qs.with_case_count_assigned() return qs
[dokumentacja] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["is_staff"] = dict( choices=enumerate(self.IS_STAFF_FILTER), selected=self.get_is_staff_choice() ) return context
[dokumentacja] class UserAutocomplete( PermissionMixin, ExprAutocompleteMixin, autocomplete.Select2QuerySetView ): model = User search_expr = [ "first_name__icontains", "last_name__icontains", "username__icontains", ]
[dokumentacja] class UserDeassignView( LoginRequiredMixin, PermissionRequiredMixin, ActionMessageMixin, ActionView, ): model = User slug_field = "username" slug_url_kwarg = "username" permission_required = "cases.can_assign" success_message = _("{subject} deassigned") template_name_suffix = "_deassign" raise_exception = True def get_success_url(self): return self.object.get_absolute_url() def action(self): self.count = int( Case.objects.filter(caseuserobjectpermission__user=self.object) .exclude(client=self.object) .distinct() .count() ) CaseUserObjectPermission.objects.filter(user=self.object).exclude( content_object__client=self.object ).delete() def get_success_message(self): return _("{object} deassigned from {count} cases").format( object=self.object, count=self.count )
[dokumentacja] class UserTableView(StaffuserRequiredMixin, PermissionMixin, TemplateView): """ View for displaying template with Users table. """ template_name = "users/user_table.html" def get_context_data(self, *args, **kwargs): context = super().get_context_data(**kwargs) context["header_label"] = mark_safe(_("Users search table")) context["ajax_datatable_url"] = reverse("users:users_table_ajax_data") return context
[dokumentacja] class UserAjaxDatatableView(StaffuserRequiredMixin, PermissionMixin, AjaxDatatableView): """ View to provide table list of all Users with ajax data. """ model = User title = _("Users") initial_order = [ ["username", "asc"], ] length_menu = [[20, 50, 100], [20, 50, 100]] search_values_separator = "|" column_defs = [ {"name": "pk", "title": "ID", "visible": False}, { "name": "username", "title": _("Username"), "visible": True, "searchable": True, "orderable": True, }, { "name": "nicename", "title": _("Nice Name"), "visible": True, "searchable": True, "orderable": True, }, { "name": "email", "title": _("Email"), "visible": True, "searchable": True, "orderable": True, }, { "name": "is_staff", "title": _("Staff"), "visible": True, "searchable": True, # (value, label) pairs. "choices": [(1, _("Yes")), (0, _("No"))], }, { "name": "case_count", "title": _("Client cases") + " (e.g. x, >y)", "visible": True, "searchable": True, "orderable": True, }, { "name": "case_assigned_sum", "title": _("Assigned cases sum") + " (e.g. x, >y)", "visible": True, "searchable": True, "orderable": True, }, { "name": "case_assigned_moderated", "title": _("Moderated"), "visible": True, "searchable": True, "orderable": True, }, { "name": "case_assigned_active", "title": _("Active_"), "visible": True, "searchable": True, "orderable": True, }, { "name": "case_assigned_closed", "title": _("Closed"), "visible": True, "searchable": True, "orderable": True, }, ] def get_initial_queryset(self, request=None): qs = super().get_initial_queryset(request) qs = qs.with_case_count() qs = qs.with_case_count_assigned() return qs
[dokumentacja] def filter_queryset_by_column(self, column_name, search_value, qs): """ Allow simple boolean expressions in case columns, e.g. >10. """ if ( column_name in [ "case_count", "case_assigned_sum", "case_assigned_moderated", "case_assigned_active", "case_assigned_closed", ] and search_value ): if ( self.search_values_separator and self.search_values_separator in search_value ): search_values = [ t.strip() for t in search_value.split(self.search_values_separator) ] else: search_values = [search_value.strip()] column_filters = Q() for val in search_values: match = re.match(r"^(?P<operator>[<>!=]=?)?\s*(?P<value>\d+)$", val) if match: operator = match.group("operator") value = int(match.group("value")) lookup = { ">": "__gt", ">=": "__gte", "<": "__lt", "<=": "__lte", "=": "", "!=": "", }.get(operator, "") # Handle `=` and `!=` separately - there's no builtin qs operator. if operator == "!=": column_filters |= ~Q(**{f"{column_name}{lookup}": value}) else: column_filters |= Q(**{f"{column_name}{lookup}": value}) if column_filters: return qs.filter(column_filters) return super().filter_queryset_by_column(column_name, search_value, qs)
def customize_row(self, row, obj): row["username"] = mark_safe( f'<a href="{obj.get_absolute_url()}">{obj.username}</a>' )