from django import forms from django.contrib.auth import authenticate, login from django.contrib.auth.models import User from django.contrib.sites.models import Site from django.utils.translation import ugettext_lazy as _ from . import models from . import profile as profile_utils from . import constants from . import utils REQUIRED = ( u"There was missing information on your order. Please correct " u"the errors below." ) class BasePersonForm(forms.Form): """ There's a common theme of form data for person information. """ first_name = forms.CharField( label=_(u"First name"), max_length=30, required=True, widget=forms.TextInput(attrs={"type": "text", "size": 25}), ) last_name = forms.CharField( label=_(u"Last name"), max_length=30, required=True, widget=forms.TextInput(attrs={"type": "text", "size": 25}), ) company = forms.CharField( label=_(u"Company"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) address1 = forms.CharField( label=_(u"Address 1"), max_length=30, required=True, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) address2 = forms.CharField( label=_(u"Address 2"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) city = forms.CharField( label=_(u"City"), max_length=30, required=True, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) region = forms.CharField( label=_(u"Region"), max_length=30, required=True, widget=forms.Select( choices=constants.STATE_CHOICES, attrs={"width": "100px", "onchange": "calculate_price();"}, ), ) country = forms.CharField( label=_(u"Country"), max_length=50, required=True, widget=forms.Select( choices=constants.COUNTRIES, attrs={"onchange": "check_state(); calculate_price();"}, ), ) country_other = forms.CharField( label=_(u"Other"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 25}), ) postal_code = forms.CharField( label=_(u"Postal Code"), max_length=15, required=True, widget=forms.TextInput( attrs={"type": "text", "size": 15, "onchange": "calculate_price();"} ), ) plus_four = forms.CharField( label=_(u"Plus Four"), max_length=15, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 15}), ) phone = forms.CharField( label=_(u"Phone"), max_length=30, required=True, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) class EmailRequiredPersonForm(BasePersonForm): """ In some cases, we need the email address to be required """ email = forms.EmailField( label=_(u"Email"), max_length=30, required=True, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) class EmailNotRequiredPersonForm(BasePersonForm): """ In some cases, we need the email address to not be required """ email = forms.EmailField( label=_(u"Email"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) class NonRequiredBasePersonForm(forms.Form): first_name = forms.CharField( label=_(u"First name"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 25}), ) last_name = forms.CharField( label=_(u"Last name"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 25}), ) company = forms.CharField( label=_(u"Company"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) address1 = forms.CharField( label=_(u"Address 1"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) address2 = forms.CharField( label=_(u"Address 2"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) city = forms.CharField( label=_(u"City"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) region = forms.ChoiceField( label=_(u"Region"), required=False, choices=constants.STATE_CHOICES, widget=forms.Select( choices=constants.STATE_CHOICES, attrs={"onchange": "calculate_price();"} ), ) country = forms.ChoiceField( label=_(u"Country"), required=False, choices=(("", "----------"),) + constants.COUNTRIES, widget=forms.Select( choices=constants.STATE_CHOICES, attrs={"onchange": "check_state(); calculate_price();"}, ), ) country_other = forms.CharField( label=_(u"Other"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 25}), ) postal_code = forms.CharField( label=_(u"Postal Code"), max_length=15, required=False, widget=forms.TextInput( attrs={"type": "text", "size": 15, "onchange": "calculate_price();"} ), ) plus_four = forms.CharField( label=_(u"Plus Four"), max_length=4, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 15}), ) phone = forms.CharField( label=_(u"Phone"), max_length=30, required=False, widget=forms.TextInput(attrs={"type": "text", "size": 50}), ) class ProfileCreateForm(EmailRequiredPersonForm): """ Form used for creating a new user """ password1 = forms.CharField( label=_("Password"), widget=forms.PasswordInput, required=True ) password2 = forms.CharField( label=_("Password confirmation"), widget=forms.PasswordInput, required=True ) def save(self, request=None): """ Creates a new user and account. Returns the newly created user. """ password = self.cleaned_data["password1"] username, email, password = ( self.cleaned_data["email"], self.cleaned_data["email"], password, ) user = User.objects.create_user(username, email, password) user.first_name = self.cleaned_data["first_name"] user.last_name = self.cleaned_data["last_name"] user.save() profile = profile_utils.get_profile(user) profile.company = self.cleaned_data["company"] profile.address1 = self.cleaned_data["address1"] profile.address2 = self.cleaned_data["address2"] profile.city = self.cleaned_data["city"] profile.region = self.cleaned_data["region"] profile.phone = self.cleaned_data["phone"] profile.country = self.cleaned_data["country"] profile.postal_code = self.cleaned_data["postal_code"] profile.plus_four = self.cleaned_data["plus_four"] profile.save() user = authenticate(username=username, password=password) if request: login(request, user) site = Site.objects.get_current() utils.send_new_account_email(email, password, user, profile, site) return user def clean(self): # We want a single error message. We don't display the validation # errors for each part of the form for field in self.fields: if self.fields[field].required and not self.cleaned_data.get(field, None): raise forms.ValidationError(_(REQUIRED)) self.clean_email() return self.cleaned_data def clean_email(self): """ Validate that the e-mail address is unique. """ if User.objects.filter( email__iexact=self.cleaned_data["email"] ) or User.objects.filter(username__iexact=self.cleaned_data["email"]): raise forms.ValidationError( _("This email is already in use. " "Please supply a different email.") ) return self.cleaned_data["email"] def clean_password2(self): password1 = self.cleaned_data.get("password1", "") password2 = self.cleaned_data["password2"] if password1 != password2: raise forms.ValidationError( "Your passwords did not match. Please re-enter your passwords." ) return password2 class ProfileUpdateForm(EmailRequiredPersonForm): """ A form to demonstrate how to add extra fields to the signup form, in this case adding the first and last name. """ def __init__(self, user, *args, **kwargs): self.user = user super(ProfileUpdateForm, self).__init__(*args, **kwargs) def clean_email(self): """ Validate that the email is not already registered with another user """ if User.objects.filter(email__iexact=self.cleaned_data["email"]).exclude( email__iexact=self.user.email ): raise forms.ValidationError( _(u"This email is already in use. Please supply a different " u"email.") ) return self.cleaned_data["email"] def save(self, request=None): """ Override the save method to save the first and last name to the user field. """ user = self.user user.first_name = self.cleaned_data["first_name"] user.last_name = self.cleaned_data["last_name"] user.email = self.cleaned_data["email"] user.save() profile = profile_utils.get_profile(user) profile.company = self.cleaned_data["company"] profile.address1 = self.cleaned_data["address1"] profile.address2 = self.cleaned_data["address2"] profile.city = self.cleaned_data["city"] profile.region = self.cleaned_data["region"] profile.phone = self.cleaned_data["phone"] profile.country = self.cleaned_data["country"] profile.country_other = self.cleaned_data["country_other"] profile.postal_code = self.cleaned_data["postal_code"] profile.plus_four = self.cleaned_data["plus_four"] profile.save() # Userena expects to get the new user from this form, so return the new # user. return user class ProfileSecondaryAddressForm(NonRequiredBasePersonForm): address_from = forms.DateField(required=False) address_to = forms.DateField(required=False) class Meta: model = models.SecondaryProfileAddress exclude = "profile" def __init__(self, *args, **kw): super(ProfileSecondaryAddressForm, self).__init__(*args, **kw) def save(self, *args, **kwargs): user = kwargs.pop("user", None) profile_address = profile_utils.get_profile_secondary_address(user) profile_address.profile = profile_utils.get_profile(user) for k, v in self.cleaned_data.iteritems(): setattr(profile_address, k, v) profile_address.save() return profile_address