diff options
Diffstat (limited to 'patchwork/forms.py')
-rw-r--r-- | patchwork/forms.py | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/patchwork/forms.py b/patchwork/forms.py new file mode 100644 index 0000000..0327958 --- /dev/null +++ b/patchwork/forms.py @@ -0,0 +1,237 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +from django.contrib.auth.models import User +from django import forms + +from patchwork.models import Patch, State, Bundle, UserProfile + +class RegistrationForm(forms.Form): + first_name = forms.CharField(max_length = 30, required = False) + last_name = forms.CharField(max_length = 30, required = False) + username = forms.RegexField(regex = r'^\w+$', max_length=30, + label=u'Username') + email = forms.EmailField(max_length=100, label=u'Email address') + password = forms.CharField(widget=forms.PasswordInput(), + label='Password') + + def clean_username(self): + value = self.cleaned_data['username'] + try: + user = User.objects.get(username__iexact = value) + except User.DoesNotExist: + return self.cleaned_data['username'] + raise forms.ValidationError('This username is already taken. ' + \ + 'Please choose another.') + + def clean_email(self): + value = self.cleaned_data['email'] + try: + user = User.objects.get(email__iexact = value) + except User.DoesNotExist: + return self.cleaned_data['email'] + raise forms.ValidationError('This email address is already in use ' + \ + 'for the account "%s".\n' % user.username) + + def clean(self): + return self.cleaned_data + +class LoginForm(forms.Form): + username = forms.CharField(max_length = 30) + password = forms.CharField(widget = forms.PasswordInput) + +class BundleForm(forms.ModelForm): + name = forms.RegexField(regex = r'^[^/]+$', max_length=50, label=u'Name', + error_messages = {'invalid': 'Bundle names can\'t contain slashes'}) + + class Meta: + model = Bundle + fields = ['name', 'public'] + +class CreateBundleForm(BundleForm): + def __init__(self, *args, **kwargs): + super(CreateBundleForm, self).__init__(*args, **kwargs) + + class Meta: + model = Bundle + fields = ['name'] + + def clean_name(self): + name = self.cleaned_data['name'] + count = Bundle.objects.filter(owner = self.instance.owner, \ + name = name).count() + if count > 0: + raise forms.ValidationError('A bundle called %s already exists' \ + % name) + return name + +class DeleteBundleForm(forms.Form): + name = 'deletebundleform' + form_name = forms.CharField(initial = name, widget = forms.HiddenInput) + bundle_id = forms.IntegerField(widget = forms.HiddenInput) + +class DelegateField(forms.ModelChoiceField): + def __init__(self, project, *args, **kwargs): + queryset = User.objects.filter(profile__in = \ + UserProfile.objects \ + .filter(maintainer_projects = project) \ + .values('pk').query) + super(DelegateField, self).__init__(queryset, *args, **kwargs) + + +class PatchForm(forms.ModelForm): + def __init__(self, instance = None, project = None, *args, **kwargs): + if (not project) and instance: + project = instance.project + if not project: + raise Exception("meep") + super(PatchForm, self).__init__(instance = instance, *args, **kwargs) + self.fields['delegate'] = DelegateField(project, required = False) + + class Meta: + model = Patch + fields = ['state', 'archived', 'delegate'] + +class UserProfileForm(forms.ModelForm): + class Meta: + model = UserProfile + fields = ['primary_project', 'patches_per_page'] + +class OptionalDelegateField(DelegateField): + no_change_choice = ('*', 'no change') + to_field_name = None + + def __init__(self, no_change_choice = None, *args, **kwargs): + self.filter = None + if (no_change_choice): + self.no_change_choice = no_change_choice + super(OptionalDelegateField, self). \ + __init__(initial = self.no_change_choice[0], *args, **kwargs) + + def _get_choices(self): + choices = list( + super(OptionalDelegateField, self)._get_choices()) + choices.append(self.no_change_choice) + return choices + + choices = property(_get_choices, forms.ChoiceField._set_choices) + + def is_no_change(self, value): + return value == self.no_change_choice[0] + + def clean(self, value): + if value == self.no_change_choice[0]: + return value + return super(OptionalDelegateField, self).clean(value) + +class OptionalModelChoiceField(forms.ModelChoiceField): + no_change_choice = ('*', 'no change') + to_field_name = None + + def __init__(self, no_change_choice = None, *args, **kwargs): + self.filter = None + if (no_change_choice): + self.no_change_choice = no_change_choice + super(OptionalModelChoiceField, self). \ + __init__(initial = self.no_change_choice[0], *args, **kwargs) + + def _get_choices(self): + choices = list( + super(OptionalModelChoiceField, self)._get_choices()) + choices.append(self.no_change_choice) + return choices + + choices = property(_get_choices, forms.ChoiceField._set_choices) + + def is_no_change(self, value): + return value == self.no_change_choice[0] + + def clean(self, value): + if value == self.no_change_choice[0]: + return value + return super(OptionalModelChoiceField, self).clean(value) + +class MultipleBooleanField(forms.ChoiceField): + no_change_choice = ('*', 'no change') + def __init__(self, *args, **kwargs): + super(MultipleBooleanField, self).__init__(*args, **kwargs) + self.choices = [self.no_change_choice] + \ + [(True, 'Archived'), (False, 'Unarchived')] + + def is_no_change(self, value): + return value == self.no_change_choice[0] + + # TODO: Check whether it'd be worth to use a TypedChoiceField here; I + # think that'd allow us to get rid of the custom valid_value() and + # to_python() methods. + def valid_value(self, value): + if value in [v1 for (v1, v2) in self.choices]: + return True + return False + + def to_python(self, value): + if value is None or self.is_no_change(value): + return self.no_change_choice[0] + elif value == 'True': + return True + elif value == 'False': + return False + else: + raise ValueError('Unknown value: %s' % value) + +class MultiplePatchForm(forms.Form): + action = 'update' + state = OptionalModelChoiceField(queryset = State.objects.all()) + archived = MultipleBooleanField() + + def __init__(self, project, *args, **kwargs): + super(MultiplePatchForm, self).__init__(*args, **kwargs) + self.fields['delegate'] = OptionalDelegateField(project = project, + required = False) + + def save(self, instance, commit = True): + opts = instance.__class__._meta + if self.errors: + raise ValueError("The %s could not be changed because the data " + "didn't validate." % opts.object_name) + data = self.cleaned_data + # Update the instance + for f in opts.fields: + if not f.name in data: + continue + + field = self.fields.get(f.name, None) + if not field: + continue + + if field.is_no_change(data[f.name]): + continue + + setattr(instance, f.name, data[f.name]) + + if commit: + instance.save() + return instance + +class EmailForm(forms.Form): + email = forms.EmailField(max_length = 200) + +UserPersonLinkForm = EmailForm +OptinoutRequestForm = EmailForm |