Exemple #1
0
class UserForumOptionsForm(Form):
    newsletters = forms.BooleanField(label=_("Newsletters"),
                                     help_text=_("On occasion board administrator may want to send e-mail message to multiple members."),
                                     required=False)
    timezone = forms.ChoiceField(label=_("Your Current Timezone"),
                                 help_text=_("If dates and hours displayed by forums are inaccurate, you can fix it by adjusting timezone setting."),
                                 choices=tzlist())
    hide_activity = forms.TypedChoiceField(label=_("Your Visibility"),
                                           help_text=_("If you want to, you can limit other members ability to track your presence on forums."),
                                           choices=(
                                                    (0, _("Show my presence to everyone")),
                                                    (1, _("Show my presence to people I follow")),
                                                    (2, _("Show my presence to nobody")),
                                                    ), coerce=int)
    subscribe_start = forms.TypedChoiceField(label=_("Threads I start"),
                                             choices=(
                                                      (0, _("Don't watch")),
                                                      (1, _("Put on watched threads list")),
                                                      (2, _("Put on watched threads list and e-mail me when somebody replies")),
                                                      ), coerce=int)
    subscribe_reply = forms.TypedChoiceField(label=_("Threads I reply to"),
                                             choices=(
                                                      (0, _("Don't watch")),
                                                      (1, _("Put on watched threads list")),
                                                      (2, _("Put on watched threads list and e-mail me when somebody replies")),
                                                      ), coerce=int)
    allow_pds = forms.TypedChoiceField(label=_("Allow Private Threads Invitations"),
                                       help_text=_("If you wish, you can restrict who can invite you to private threads. Keep in mind some groups or members may be allowed to override this preference."),
                                       choices=(
                                                (0, _("From everyone")),
                                                (1, _("From everyone but not members I ignore")),
                                                (2, _("From members I follow")),
                                                (2, _("From nobody")),
                                                ), coerce=int)
Exemple #2
0
class WarnLevelForm(Form):
    name = forms.CharField(label=_("Warning Level Name"),
                           max_length=255, validators=[validate_sluggable(
                                                                          _("Warning level name must contain alphanumeric characters."),
                                                                          _("Warning level name is too long.")
                                                                          )])
    description = forms.CharField(label=_("Warning Level Description"),
                                  help_text=_("Optional message displayed to members with this warning level."),
                                  widget=forms.Textarea, required=False)
    expires_after_minutes = forms.IntegerField(label=_("Warning Level Expiration"),
                                               help_text=_("Enter number of minutes since this warning level was imposed on member until it's reduced and lower level is imposed, or 0 to make this warning level permanent."),
                                               initial=0, min_value=0)
    restrict_posting_replies = forms.TypedChoiceField(
        label=_("Restrict Replies Posting"),
        choices=(
           (WarnLevel.RESTRICT_NO, _("No restrictions")),
           (WarnLevel.RESTRICT_MODERATOR_REVIEW, _("Review by moderator")),
           (WarnLevel.RESTRICT_DISALLOW, _("Disallowed")),
        ),
        coerce=int, initial=0)
    restrict_posting_threads = forms.TypedChoiceField(
        label=_("Restrict Threads Posting"),
        choices=(
           (WarnLevel.RESTRICT_NO, _("No restrictions")),
           (WarnLevel.RESTRICT_MODERATOR_REVIEW, _("Review by moderator")),
           (WarnLevel.RESTRICT_DISALLOW, _("Disallowed")),
        ),
        coerce=int, initial=0)
Exemple #3
0
    def finalize_form(self):
        # Can we change threads states?
        if self.include_thread_weight and (self.request.acl.threads.can_pin_threads(self.forum) and
            (not self.thread or self.request.acl.threads.can_pin_threads(self.forum) >= self.thread.weight)):
            thread_weight = []
            if self.request.acl.threads.can_pin_threads(self.forum) == 2:
                thread_weight.append((2, _("Announcement")))
            thread_weight.append((1, _("Sticky")))
            thread_weight.append((0, _("Standard")))
            if thread_weight:
                try:
                    current_weight = self.thread.weight
                except AttributeError:
                    current_weight = 0
                self.add_field('thread_weight', forms.TypedChoiceField(widget=forms.RadioSelect,
                                                                       choices=thread_weight,
                                                                       required=False,
                                                                       coerce=int,
                                                                       initial=current_weight))

        # Can we lock threads?
        if self.include_close_thread and self.request.acl.threads.can_close(self.forum):
            self.add_field('close_thread', forms.BooleanField(required=False))

        if self.request.acl.threads.can_upload_attachments(self.forum):
            self.add_field('new_file', forms.FileField(required=False))

        # Give inheritor chance to set custom fields
        try:
            type_fields_call = self.type_fields
        except AttributeError:
            type_fields_call = None
        if type_fields_call:
            type_fields_call()
Exemple #4
0
class CloseMeetingForm(forms.ModelForm):

    send_to_options = list(SendToOption.choices[2:])

    # On QA servers, allow users to prevent sending of protocols
    if settings.QA_SERVER:
        send_to_options.insert(0, SendToOption.choices[0])

    send_to = forms.TypedChoiceField(label=_("Send to"),
                                     coerce=int,
                                     choices=send_to_options,
                                     widget=forms.RadioSelect)
    issues = forms.MultipleChoiceField(
        label=_("The selected issues will be archived"),
        choices=[],
        widget=forms.CheckboxSelectMultiple,
        required=False)

    class Meta:
        model = Meeting

        fields = ('held_at', )

        widgets = {
            'held_at': OCSplitDateTime,
        }

    def _get_issue_alert(self, issue):
        if not issue.changed_in_current():
            return _('Issue was not modified in this meeting')
        elif issue.open_proposals():
            return u'{0} {1}'.format(issue.open_proposals().count(),
                                     _('Undecided proposals'))
        else:
            return None

    def __init__(self, *args, **kwargs):
        #         self.helper = FormHelper()
        #
        #         self.helper.add_input(Submit('submit', _('Close Meeting')))
        issues = kwargs.pop('issues')
        super(CloseMeetingForm, self).__init__(*args, **kwargs)
        issues_op = []
        init_vals = []  # issues which 'archive' checkbox should be checked
        for issue in issues:
            choice_txt = issue.title
            alert_txt = self._get_issue_alert(issue)
            if alert_txt:
                choice_txt += u'<span class="help-text">{0}</span>'.format(
                    alert_txt)
            else:
                # mark as ready for archive only when no alerts exist
                init_vals.append(issue.id)
            issues_op.append((
                issue.id,
                mark_safe(choice_txt),
            ))
        self.fields['issues'].choices = issues_op
        self.fields['issues'].initial = init_vals
Exemple #5
0
def make_form(request, role, form):
    if role.special != 'guest':
        form.base_fields['can_report_content'] = forms.BooleanField(
            label=_("Can report content"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_handle_reports'] = forms.BooleanField(
            label=_("Can handle reports"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_upload_report_attachments'] = forms.BooleanField(
            label=_("Can upload attachments in reports discussions"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields[
            'can_download_report_attachments'] = forms.BooleanField(
                label=_("Can download attachments in reports discussions"),
                widget=YesNoSwitch,
                initial=False,
                required=False)
        form.base_fields['report_attachment_size'] = forms.IntegerField(
            label=_(
                "Max size of single attachment in reports discussions (in Kb)"
            ),
            help_text=_("Enter zero for no limit."),
            min_value=0,
            initial=100)
        form.base_fields['report_attachment_limit'] = forms.IntegerField(
            label=_(
                "Max number of attachments per post in reports discussions"),
            help_text=_("Enter zero for no limit."),
            min_value=0,
            initial=3)
        form.base_fields['can_mod_reports_discussions'] = forms.BooleanField(
            label=_("Can moderate reports discussions"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_delete_reports'] = forms.TypedChoiceField(
            label=_("Can delete reports"),
            choices=(
                (0, _("No")),
                (1, _("Yes, soft-delete")),
                (2, _("Yes, hard-delete")),
            ),
            coerce=int)

        form.fieldsets.append(
            (_("Reporting Content"),
             ('can_report_content', 'can_handle_reports',
              'can_upload_report_attachments',
              'can_download_report_attachments', 'report_attachment_size',
              'report_attachment_limit', 'can_mod_reports_discussions',
              'can_delete_reports')))
Exemple #6
0
class SendMessageForm(forms.Form):
    to = forms.TypedChoiceField(
        label=_("To"),
        choices=[],
        coerce=int,
        required=True,
        widget=forms.RadioSelect(attrs={"class": "form-control"}))
    subject = forms.CharField(
        label=_("Subject"),
        max_length=230,
        widget=forms.TextInput(attrs={"class": "form-control"}))
    message = forms.CharField(
        widget=forms.Textarea(attrs={"class": "form-control"}),
        label=_("Your message"))

    def __init__(self, foirequest, *args, **kwargs):
        super(SendMessageForm, self).__init__(*args, **kwargs)
        self.foirequest = foirequest

        choices = [(0, _("Default address of %(publicbody)s") % {
            "publicbody": foirequest.public_body.name
        })]
        choices.extend([
            (m.id, m.reply_address_entry)
            for k, m in foirequest.possible_reply_addresses().items()
        ])
        self.fields['to'].choices = choices

        if foirequest.law and foirequest.law.email_only:
            self.fields['send_address'] = forms.BooleanField(
                label=_("Send physical address"),
                help_text=(_(
                    'If the public body is asking for your post '
                    'address, check this and we will append it to your message.'
                )),
                required=False)

    def save(self, user):
        if self.cleaned_data["to"] == 0:
            recipient_name = self.foirequest.public_body.name
            recipient_email = self.foirequest.public_body.email
            recipient_pb = self.foirequest.public_body
        else:
            message = list(
                filter(lambda x: x.id == self.cleaned_data["to"],
                       list(self.foirequest.messages)))[0]
            recipient_name = message.sender_name
            recipient_email = message.sender_email
            recipient_pb = message.sender_public_body
        return self.foirequest.add_message(user,
                                           recipient_name,
                                           recipient_email,
                                           self.cleaned_data["subject"],
                                           self.cleaned_data['message'],
                                           recipient_pb=recipient_pb,
                                           send_address=self.cleaned_data.get(
                                               'send_address', True))
class DonateForm(forms.Form):
    """Form for accepting a donation."""

    name = pyoforms.StripCharField(max_length=200)
    email = forms.EmailField(max_length=255)
    phone = pyoforms.StripCharField(max_length=20)
    country_code = forms.TypedChoiceField(
        choices=model.Profile._meta.get_field('country_code').choices,
        widget=forms.RadioSelect(),
        )
    school = pyoforms.ModelChoiceField(
        queryset=model.School.objects.filter(auto=False).order_by('name'),
        empty_label=u"I'm not affiliated with a school or program",
        required=False,
        widget=SchoolRadioSelect,
        initial=u'',
        )
    addschool = forms.BooleanField(
        initial=False, required=False, widget=forms.HiddenInput)

    amount = pyoforms.StripCharField(max_length=20)


    def __init__(self, *args, **kwargs):
        """Also instantiate a nested SchoolForm."""
        super(DonateForm, self).__init__(*args, **kwargs)
        self.addschool_form = SchoolForm(self.data or None, prefix='addschool')


    def clean(self):
        """
        Verify password fields match and school is provided.

        If addschool is True, build a new School based on data in nested
        SchoolForm.

        If not, and no school was selected, auto-construct one.

        """
        data = self.cleaned_data
        if data.get('addschool'):
            if self.addschool_form.is_valid():
                data['school'] = self.addschool_form.save(commit=False)
            else:
                raise forms.ValidationError(
                    "Could not add a school.")
        else:
            # reinstantiate unbound addschool_form to avoid spurious errors
            self.addschool_form = SchoolForm(prefix='addschool')
            if data.get('email') and not data.get('school'):
                data['school'] = model.School(
                    name=(u"%f-%s" % (time.time(), data['email']))[:200],
                    postcode="",
                    auto=True,
                    )
        return data
Exemple #8
0
class PublishUpcomingMeetingForm(forms.ModelForm):

    send_to = forms.TypedChoiceField(label=_("Send to"), coerce=int,
                                choices=SendToOption.choices,
                                widget=forms.RadioSelect)

    class Meta:
        model = Community

        fields = ()
Exemple #9
0
 def __init__(self, foirequest, *args, **kwargs):
     super(ConcreteLawForm, self).__init__(*args, **kwargs)
     self.foirequest = foirequest
     self.possible_laws = foirequest.law.combined.all()
     self.fields['law'] = forms.TypedChoiceField(
         label=_("Information Law"),
         choices=([('', '-------')] +
                  list(map(lambda x: (x.pk, x.name), self.possible_laws))),
         coerce=int,
         empty_value='')
Exemple #10
0
class AllFieldsForm(forms.Form):
    boolean = forms.BooleanField()
    char = forms.CharField(max_length=50)
    choices = forms.ChoiceField(choices=ALPHA_CHOICES)
    date = forms.DateField()
    datetime = forms.DateTimeField()
    decimal = forms.DecimalField(decimal_places=2, max_digits=4)
    email = forms.EmailField()
    file_field = forms.FileField()
    file_path = forms.FilePathField(path='uploads/')
    float_field = forms.FloatField()
    generic_ip_address = forms.GenericIPAddressField()
    image = forms.ImageField()
    integer = forms.IntegerField()
    ip_address = forms.IPAddressField()
    multiple_choices = forms.MultipleChoiceField(choices=ALPHA_CHOICES)
    null_boolean = forms.NullBooleanField()
    regex_field = forms.RegexField(regex='^\w+$', js_regex='^[a-zA-Z]+$')
    slug = forms.SlugField()
    split_datetime = forms.SplitDateTimeField()
    time = forms.TimeField()
    typed_choices = forms.TypedChoiceField(choices=NUMERIC_CHOICES, coerce=int)
    typed_multiple_choices = forms.TypedMultipleChoiceField(
        choices=NUMERIC_CHOICES, coerce=int)
    url = forms.URLField()

    # GIS fields.
    if gis_forms:
        osm_point = gis.PointField(
            widget=mixin(gis.PointWidget, gis.BaseOsmWidget))
        osm_multipoint = gis.MultiPointField(
            widget=mixin(gis.MultiPointWidget, gis.BaseOsmWidget))
        osm_linestring = gis.LineStringField(
            widget=mixin(gis.LineStringWidget, gis.BaseOsmWidget))
        osm_multilinestring = gis.MultiLineStringField(
            widget=mixin(gis.MultiLineStringWidget, gis.BaseOsmWidget))
        osm_polygon = gis.PolygonField(
            widget=mixin(gis.PolygonWidget, gis.BaseOsmWidget))
        osm_multipolygon = gis.MultiPolygonField(
            widget=mixin(gis.MultiPolygonWidget, gis.BaseOsmWidget))

        gmap_point = gis.PointField(
            widget=mixin(gis.PointWidget, BaseGMapWidget))
        gmap_multipoint = gis.MultiPointField(
            widget=mixin(gis.MultiPointWidget, BaseGMapWidget))
        gmap_linestring = gis.LineStringField(
            widget=mixin(gis.LineStringWidget, BaseGMapWidget))
        gmap_multilinestring = gis.MultiLineStringField(
            widget=mixin(gis.MultiLineStringWidget, BaseGMapWidget))
        gmap_polygon = gis.PolygonField(
            widget=mixin(gis.PolygonWidget, BaseGMapWidget))
        gmap_multipolygon = gis.MultiPolygonField(
            widget=mixin(gis.MultiPolygonWidget, BaseGMapWidget))
Exemple #11
0
 def create_prefix_form(self):
     self.prefixes = ThreadPrefix.objects.forum_prefixes(self.forum)
     if self.prefixes:
         self.add_field(
             'thread_prefix',
             forms.TypedChoiceField(
                 label=_("Thread Prefix"),
                 choices=[(0, _("No prefix"))] +
                 [(p.pk, _(p.name)) for p in self.prefixes.values()],
                 coerce=int,
                 required=False,
                 empty_value=0,
                 initial=self.thread.prefix_id if self.thread else None))
Exemple #12
0
def make_form(request, role, form):
    if role.special != 'guest':
        form.base_fields['can_warn_members'] = forms.BooleanField(
            label=_("Can warn other members"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_see_other_members_warns'] = forms.BooleanField(
            label=_("Can see other members warnings"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_cancel_warnings'] = forms.TypedChoiceField(
            label=_("Can cancel warnings"),
            widget=forms.Select,
            initial=0,
            coerce=int,
            choices=(
                (0, _("No")),
                (1, _("If is warning giver")),
                (2, _("Yes, all warnings")),
            ))
        form.base_fields['can_cancel_warnings_newer_than'] = forms.IntegerField(
            label=_(
                "Maximum age of warning that can be canceled (in minutes)"),
            help_text=_("Enter zero to disable this limitation."),
            min_value=0,
            initial=15)
        form.base_fields['can_delete_warnings'] = forms.BooleanField(
            label=_("Can delete warnings"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_be_warned'] = forms.BooleanField(
            label=_("Can be warned"),
            widget=YesNoSwitch,
            initial=False,
            required=False)

        form.fieldsets.append((_("Warning Members"), (
            'can_warn_members',
            'can_see_other_members_warns',
            'can_cancel_warnings',
            'can_cancel_warnings_newer_than',
            'can_delete_warnings',
            'can_be_warned',
        )))
Exemple #13
0
 def finalize_form(self):
     choices = []
     for choice in self.poll.choices_cache:
         choices.append((choice['pk'], choice['name']))
     if self.poll.max_choices > 1:
         self.add_field(
             'options',
             forms.TypedMultipleChoiceField(
                 choices=choices,
                 coerce=int,
                 required=False,
                 widget=forms.CheckboxSelectMultiple))
     else:
         self.add_field(
             'options',
             forms.TypedChoiceField(choices=choices,
                                    coerce=int,
                                    required=False,
                                    widget=forms.RadioSelect))
Exemple #14
0
    def finalize_form(self):
        choices = [(0, _("Don't use any polls"))]
        for thread in self.threads:
            if thread.has_poll:
                choices.append((thread.pk, thread.name))

        if len(choices) > 2:
            self.add_field(
                'final_poll',
                forms.TypedChoiceField(
                    label=_("Final Poll"),
                    help_text=
                    _("More than one of threads that you are going to merge has poll. Select poll that will be used in merged thread or delete all polls."
                      ),
                    choices=choices,
                    coerce=int,
                    initial=choices[1][0]))

        self.add_field(
            'new_forum',
            ForumChoiceField(
                label=_("Thread Forum"),
                help_text=_("Select forum you want to put new thread in."),
                queryset=Forum.objects.get(
                    special='root').get_descendants().filter(
                        pk__in=self.request.acl.forums.acl['can_browse']),
                initial=self.threads[0].forum))
        self.add_field(
            'thread_name',
            forms.CharField(
                label=_("Thread Name"),
                help_text=
                _("Name of new thread that will be created as result of merge."
                  ),
                max_length=settings.thread_name_max,
                initial=self.threads[-1].name,
                validators=[
                    validate_sluggable(
                        _("Thread name must contain at least one alpha-numeric character."
                          ), _("Thread name is too long. Try shorter name."))
                ]))
Exemple #15
0
class ImportDatasetForm(django_forms.Form):
    parser = forms.TypedChoiceField(
        label=_('Data to import from network'),
        widget=forms.RadioSelect,
        required=True,
    )

    def __init__(self, choices=None, *args, **kwargs):
        super(ImportDatasetForm, self).__init__(*args, **kwargs)

        self.fields['parser'].choices = choices

        self.helper = FormHelper()
        self.helper.layout = Layout(
            Div(
                Div('parser', ),
                FormActions(
                    Submit('import-web', _("Import"),
                           css_class='button white')),
                css_class='file-attachment-form',
            ))
Exemple #16
0
    def __init__(self, foirequest, *args, **kwargs):
        super(SendMessageForm, self).__init__(*args, **kwargs)
        self.foirequest = foirequest
        choices = [(m.id, m.reply_address_entry)
                   for k, m in foirequest.possible_reply_addresses().items()]
        choices.append((0, _("Default address of %(publicbody)s") % {
            "publicbody": foirequest.public_body.name
        }))
        self.fields.insert(
            0, 'to',
            forms.TypedChoiceField(label=_("To"),
                                   choices=choices,
                                   coerce=int,
                                   required=True))

        if foirequest.law and foirequest.law.email_only:
            self.fields['send_address'] = forms.BooleanField(
                label=_("Send physical address"),
                help_text=(_(
                    'If the public body is asking for your post '
                    'address, check this and we will append it to your message.'
                )),
                required=False)
Exemple #17
0
def make_form(request, role, form):
    if role.special != 'guest':
        form.base_fields['can_use_private_threads'] = forms.BooleanField(
            label=_("Can participate in private threads"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_start_private_threads'] = forms.BooleanField(
            label=_("Can start private threads"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields[
            'can_upload_attachments_in_private_threads'] = forms.BooleanField(
                label=_("Can upload attachments"),
                widget=YesNoSwitch,
                initial=False,
                required=False)
        form.base_fields[
            'can_download_attachments_in_private_threads'] = forms.BooleanField(
                label=_("Can download attachments"),
                widget=YesNoSwitch,
                initial=False,
                required=False)
        form.base_fields[
            'private_thread_attachment_size'] = forms.IntegerField(
                label=_("Max. size of single attachment (in KB)"),
                min_value=0,
                initial=100,
                required=False)
        form.base_fields[
            'private_thread_attachments_limit'] = forms.IntegerField(
                label=_("Max. number of attachments per post"),
                min_value=0,
                initial=3,
                required=False)
        form.base_fields['can_invite_ignoring'] = forms.BooleanField(
            label=_("Can invite users that ignore him"),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['private_threads_mod'] = forms.BooleanField(
            label=_("Can moderate threads"),
            help_text=
            _("Makes user with this role Private Threads moderator capable of closing, deleting and editing all private threads he participates in at will."
              ),
            widget=YesNoSwitch,
            initial=False,
            required=False)
        form.base_fields['can_delete_checkpoints'] = forms.TypedChoiceField(
            label=_("Can delete checkpoints"),
            choices=(
                (0, _("No")),
                (1, _("Yes, soft-delete")),
                (2, _("Yes, hard-delete")),
            ),
            coerce=int)

        form.fieldsets.append(
            (_("Private Threads"),
             ('can_use_private_threads', 'can_start_private_threads',
              'can_upload_attachments_in_private_threads',
              'can_download_attachments_in_private_threads',
              'private_thread_attachment_size',
              'private_thread_attachments_limit', 'can_invite_ignoring',
              'private_threads_mod', 'can_delete_checkpoints')))
Exemple #18
0
 class TypedForm(forms.Form):
     typed = forms.TypedChoiceField(coerce=my_coerce,
                                    choices=TYPE_CHOICES)
class RegistrationForm(forms.Form):
    """
    Form for registering a new user account.

    Validates that the email address is not already in use, and requires the
    password to be entered twice to catch typos. Also allows user to either
    pick from an existing list of schools or enter a new one.

    """
    name = pyoforms.StripCharField(max_length=200)
    role = pyoforms.StripCharField(max_length=200)
    password = forms.CharField(widget=forms.PasswordInput(render_value=False))
    password_confirm = forms.CharField(
        label="confirm password",
        widget=forms.PasswordInput(render_value=False))
    email = forms.EmailField(max_length=255)
    phone = pyoforms.StripCharField(max_length=20)
    country_code = forms.TypedChoiceField(
        choices=model.Profile._meta.get_field('country_code').choices,
        widget=forms.RadioSelect(),
        )
    school = pyoforms.ModelChoiceField(
        queryset=model.School.objects.filter(auto=False).order_by('name'),
        empty_label=u"I'm not affiliated with a school or program",
        required=False,
        widget=SchoolRadioSelect,
        initial=u'',
        )
    addschool = forms.BooleanField(
        initial=False, required=False, widget=forms.HiddenInput)
    terms_confirm = forms.BooleanField(required=True)


    def __init__(self, *args, **kwargs):
        """Also instantiate a nested SchoolForm."""
        super(RegistrationForm, self).__init__(*args, **kwargs)
        self.addschool_form = SchoolForm(self.data or None, prefix='addschool')


    def clean(self):
        """
        Verify password fields match and school is provided.

        If addschool is True, build a new School based on data in nested
        SchoolForm.

        If not, and no school was selected, auto-construct one.

        """
        data = self.cleaned_data
        password = data.get('password')
        confirm = data.get('password_confirm')
        if password != confirm:
            raise forms.ValidationError("The passwords didn't match.")
        if data.get('addschool'):
            if self.addschool_form.is_valid():
                data['school'] = self.addschool_form.save(commit=False)
            else:
                raise forms.ValidationError(
                    "Could not add a school.")
        else:
            # reinstantiate unbound addschool_form to avoid spurious errors
            self.addschool_form = SchoolForm(prefix='addschool')
            if data.get('email') and not data.get('school'):
                data['school'] = model.School(
                    name=(u"%f-%s" % (time.time(), data['email']))[:200],
                    postcode="",
                    auto=True,
                    )
        return data


    def clean_email(self):
        """Validate that the supplied email address is unique."""
        if model.User.objects.filter(
                email__iexact=self.cleaned_data['email']):
            raise forms.ValidationError(
                "This email address is already in use. "
                "Please supply a different email address."
                )
        return self.cleaned_data['email']


    def save(self):
        """Save and return new user profile."""
        school = self.cleaned_data['school']
        if school.id is None:
            # this could just set country_code and then school.save(), but that
            # creates a race condition for two users creating same school at
            # same time, resulting in IntegrityError
            school, created = model.School.objects.get_or_create(
                name=school.name,
                postcode=school.postcode,
                defaults={
                    'country_code': self.cleaned_data['country_code'],
                    'auto': school.auto,
                    },
                )

        profile = model.Profile.create_with_user(
            name=self.cleaned_data['name'],
            email=self.cleaned_data['email'],
            password=self.cleaned_data['password'],
            role=self.cleaned_data['role'],
            country_code=self.cleaned_data['country_code'],
            school=school,
            school_staff=True,
            email_confirmed=False,
            is_active=True,
            email_notifications=True,
            )

        return profile