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