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

# Imports

from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from superdjango.conf import SUPERDJANGO
from superdjango.html.library import Fieldset
from superdjango.contrib.i18n.timezones import COMMON_TIMEZONE_CHOICES
from ..utils import get_profile_model, get_user_profile

ProfileModel = get_profile_model()
UserModel = get_user_model()

# Exports

__all__ = (
    "ProfileForm",
)

# Constants

DEFAULT_REDIRECT_TO_CHOICES = (
    ("/", _("Home")),
    ("/accounts/profile/", _("My Account")),
)

LOGIN_REDIRECT_URL = getattr(settings, "LOGIN_REDIRECT_URL", "/")

# Forms


[docs]class ProfileForm(forms.ModelForm): """A base form for user profiles based on the ``ProfileModel``.""" field_order = [ "prefix", "first_name", "last_name", "suffix", "address", "phone_number", "email", "username", "redirect_to", "time_zone", "gravatar_enabled", "photo", ] address = forms.CharField( label=_("Address"), help_text=_("Enter your mailing address."), widget=forms.Textarea, required=False ) email = forms.EmailField( label=_("Email Address"), help_text=_("Enter your email address."), required=False ) first_name = forms.CharField( label=_("First Name"), help_text=_("Your given name."), max_length=128, required=True ) gravatar_enabled = forms.BooleanField( help_text=_("Indicates whether to use gravatar.com for your profile photos."), label=_("Enable Gravatar") ) last_name = forms.CharField( label=_("Last Name"), help_text=_("Your family name."), max_length=128, required=True ) middle_name = forms.CharField( label=_("Middle Name"), help_text=_("Your middle name or initial."), max_length=128, required=False ) phone_number = forms.CharField( label=_("Phone Number"), help_text=_("Enter your phone number."), required=False ) photo = forms.FileField( label=_("Photo"), help_text=_("Upload a photo to use for your profile picture."), required=False ) prefix = forms.CharField( label=_("Prefix"), help_text=_("Enter a prefix to appear before your name or leave blank for nothing."), max_length=64, required=False ) # Default redirect choices will be overridden by account settings. redirect_to = forms.ChoiceField( choices=SUPERDJANGO.REDIRECT_TO_CHOICES or DEFAULT_REDIRECT_TO_CHOICES, initial=LOGIN_REDIRECT_URL, help_text=_("By default, go to this page after logging in."), label=_("Redirect To"), required=True ) suffix = forms.CharField( label=_("Suffix"), help_text=_("Enter a suffix to appear after your name or leave blank for nothing."), max_length=64, required=False ) # Default choices will be overridden by account settings. time_zone = forms.ChoiceField( choices=SUPERDJANGO.TIMEZONE_CHOICES or COMMON_TIMEZONE_CHOICES, label=_("Timezone"), help_text=_("Select the timezone in which you reside or work."), required=False ) username = forms.CharField( label=_("User Name"), max_length=150, required=True ) class Meta: model = ProfileModel fields = [ "address", "email", "first_name", "gravatar_enabled", "last_name", "middle_name", "phone_number", "photo", "prefix", "redirect_to", "suffix", "time_zone", "username", ]
[docs] def __init__(self, *args, **kwargs): """Initialize with a user keyword argument, add redirect and time zone choices, and set defaults.""" # Get the user or die trying. self.user = kwargs.pop("user", None) if self.user is None: raise ImproperlyConfigured("user is a required kwarg.") # This allows view logic to pass the redirect choices but still default to those supplied by the accounts app. redirect_to_choices = kwargs.pop( "redirect_to_choices", SUPERDJANGO.REDIRECT_TO_CHOICES or DEFAULT_REDIRECT_TO_CHOICES ) # This allows view logic to pass time zone choices but still default to configured or common choices. time_zone_choices = kwargs.pop( "time_zone_choices", SUPERDJANGO.TIMEZONE_CHOICES or COMMON_TIMEZONE_CHOICES ) # Initialize the form. super(ProfileForm, self).__init__(*args, **kwargs) # Set the value of fields that come from the user. self.fields['email'].initial = self.user.email self.fields['username'].initial = self.user.username # First and last name may have been entered if the user account was created manually or (for example) through a # registration process that did not create a profile record. These will be blank during the first load of a # profile form, but we can attempt to display them as initial values. Note that email and username above work # because the values are not bound to profile. However, # self.fields['first_name'].initial = profile.user.first_name will *not* work because those fields are bound # in the call to super() above. profile = kwargs['instance'] if not profile.first_name: self.initial['first_name'] = profile.user.first_name if not profile.last_name: self.initial['last_name'] = profile.user.last_name # Set choices. self.fields['redirect_to'].choices = redirect_to_choices self.fields['time_zone'].choices = time_zone_choices
[docs] def clean_email(self): """Email addresses must be unique. This checks to see if the current address is different than the submitted address and makes sure a new address is not already taken. """ current_profile = get_user_profile(self.user) if current_profile.user.email != self.cleaned_data['email']: if UserModel.objects.filter(email__iexact=self.cleaned_data['email']).exists(): raise forms.ValidationError(_("This email address is already in use.")) return self.cleaned_data['email']
[docs] def clean_username(self): """User names must be unique. This checks to see if the current name is different than the submitted name and makes sure a new name is not already taken. """ current_profile = get_user_profile(self.user) current_username = getattr(current_profile.user, UserModel.USERNAME_FIELD) if current_username != self.cleaned_data['username']: criteria = { UserModel.USERNAME_FIELD: self.cleaned_data['username'] } if UserModel.objects.filter(**criteria).exists(): raise forms.ValidationError(_("This user name is already in use.")) return self.cleaned_data['username']
@property def fieldsets(self): """Alias of ``get_fieldsets()``.""" return self.get_fieldsets()
[docs] def get_fieldsets(self): """Get the field sets to be included in the form. :rtype: list[superdjango.html.library.Fieldset] """ a = list() contact = Fieldset(_("Contact"), fields=[ self["prefix"], self["first_name"], self["middle_name"], self["last_name"], self["suffix"], self["address"], self["phone_number"], self["email"], ]) a.append(contact) user = Fieldset(_("User"), fields=[ self["username"], self["photo"], ]) a.append(user) prefs = Fieldset(_("Preferences"), fields=[ self["gravatar_enabled"], self["redirect_to"], self["time_zone"] ]) a.append(prefs) return a
@property def has_fieldsets(self): """Indicates the form has fieldsets. :rtype: bool """ return True
[docs] def save(self, commit=True): """Process user fields.""" # Email is saved to the user account. email = self.cleaned_data.pop('email') # User names are also saved to the user account. first_name = self.cleaned_data['first_name'] last_name = self.cleaned_data['last_name'] username = self.cleaned_data.pop('username') user = UserModel.objects.get(pk=self.instance.user_id) user.email = email user.first_name = first_name user.last_name = last_name setattr(user, UserModel.USERNAME_FIELD, username) user.save() return super(ProfileForm, self).save(commit=commit)