Source code for superdjango.contrib.accounts.profiles.views

# Imports

from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404, HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.utils.translation import ugettext_lazy as _
from superdjango.conf import SUPERDJANGO
from superdjango.views import AccessMixin, BreadcrumbsMixin, MessageMixin, TemplateView, UpdateView, ViewSet
from ..utils import get_profile_model
from .forms import ProfileForm
from .signals import user_profile_links

ProfileModel = get_profile_model()

# Exports

__all__ = (
    "ProfileDetail",
    "ProfileRequiredMixin",
    "ProfileUpdate",
    "ProfileViewSet",
)

# Mixins


[docs]class ProfileRequiredMixin(MessageMixin, AccessMixin): """Use this to require a profile before proceeding.""" auto_create = SUPERDJANGO.USER_AUTO_CREATE_PROFILE """Indicates whether a profile should be created for the user if one does not exist.""" login_required = True """A login is always required for profile access."""
[docs] def check_other(self, request, *args, **kwargs): """Check whether a profile exists. Sets ``self.object`` as well. The ``auto_create`` option is passed to the profile model's ``for_user()`` method, which means the profile may be created on the fly. A typical approach to this would be to define ``auto_create`` (or ``SUPERDJANGO_AUTO_CREATE_PROFILE``) as ``False`` for profile detail views and override to ``True`` for the profile update view. This allows profiles to be created as needed. """ if ProfileModel is None: raise ImproperlyConfigured("Profile view has been invoked without defining SUPERDJANGO_USER_PROFILE_MODEL.") # noinspection PyUnresolvedReferences profile = ProfileModel.for_user(self.request.user, create=self.auto_create) # noinspection PyAttributeOutsideInit self.object = profile return profile is not None
[docs] def dispatch_other(self, request, message=None, redirect_url=None): """Returns a 404 response when ``raise_access_exception`` is ``True``. Otherwise, this will send authenticated users to the update view (where a profile should be created by default) and unauthenticated users to the login page. """ if self.raise_access_exception: raise Http404(_("A user profile is required to view this page, but no profile was found.")) # Send authenticated users to profile update which (hopefully) allows them to create/update their profile. # Otherwise, redirect to login. This may result in an endless loop for the user if no auto create is enabled on # the profile update view. # noinspection PyUnresolvedReferences if self.request.user.is_authenticated: # noinspection PyUnresolvedReferences url = "%s?%s=%s" % (reverse("accounts_profile_update"), REDIRECT_FIELD_NAME, self.request.path) else: # noinspection PyUnresolvedReferences url = "%s?%s=%s" % (reverse("accounts_login"), REDIRECT_FIELD_NAME, self.request.path) return HttpResponseRedirect(url)
# Views
[docs]class ProfileDetail(ProfileRequiredMixin, BreadcrumbsMixin, TemplateView): """Display the user profile for the current user.""" active_page = "accounts" pattern_name = "accounts_profile" pattern_value = 'profile/' model = ProfileModel template_name = "accounts/profile_detail.html"
[docs] def get_breadcrumbs(self): """Get profile breadcrumbs.""" crumbs = super().get_breadcrumbs() crumbs.add(_("Profile"), "") return crumbs
[docs] def get_context_data(self, **kwargs): """Add ``profile`` to the context.""" context = super().get_context_data(**kwargs) context['profile'] = self.object groupings = list() links = list() results = user_profile_links.send(ProfileDetail, profile=self.object) for f, _links in results: for link in _links: if link.grouping is not None and link.grouping not in groupings: groupings.append(link.grouping) links += _links context['link_groupings'] = groupings context['links'] = links return context
[docs]class ProfileUpdate(ProfileRequiredMixin, BreadcrumbsMixin, UpdateView): """Facilitate self management of user profile data.""" active_page = "accounts" auto_create = True form_class = ProfileForm pattern_name = "accounts_profile_update" pattern_value = 'profile/update/' model = ProfileModel success_url = reverse_lazy("accounts_profile") template_name = "accounts/profile_update_form.html"
[docs] def form_valid(self, form): if "time_zone" in form.cleaned_data: self.request.session[SUPERDJANGO.I18N_TIMEZONE_KEY] = form.cleaned_data['time_zone'] self.request.session.modified = True return super().form_valid(form)
[docs] def get_breadcrumbs(self): """Overridden to so that ``UpdateView`` breadcrumbs are not used.""" crumbs = super().get_breadcrumbs() crumbs.add(_("Profile"), reverse("accounts_profile")) crumbs.add(self.get_subtitle(), "") return crumbs
[docs] def get_cancel_url(self): """Send the user back to the profile view.""" return reverse("accounts_profile")
[docs] def get_form(self, data=None, files=None, **kwargs): """Add the current user to form data.""" kwargs['user'] = self.request.user return super().get_form(data=data, files=files, **kwargs)
[docs] def get_form_class(self): """Get the form class from the model or using the default ``form_class`` attribute of the view.""" try: return self.object.get_form_class() except AttributeError: return self.form_class
[docs] def get_object(self): """Overridden to return the current profile without a lookup key. ``self.object`` is defined in the ``ProfileRequiredMixin``. """ return self.object
[docs] def get_subtitle(self): """Provide a default subtitle for the page.""" if self.subtitle is not None: return self.subtitle return _("Edit")
# BaseView Sets
[docs]class ProfileViewSet(ViewSet): views = [ ProfileDetail, ProfileUpdate, ]