1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org>
4 # This file is part of the Patchwork package.
6 # Patchwork is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # Patchwork is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Patchwork; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 from django.contrib.auth.models import User
22 from django import forms
24 from patchwork.models import Patch, State, Bundle, UserProfile
26 class RegistrationForm(forms.Form):
27 first_name = forms.CharField(max_length = 30, required = False)
28 last_name = forms.CharField(max_length = 30, required = False)
29 username = forms.RegexField(regex = r'^\w+$', max_length=30,
31 email = forms.EmailField(max_length=100, label=u'Email address')
32 password = forms.CharField(widget=forms.PasswordInput(),
35 def clean_username(self):
36 value = self.cleaned_data['username']
38 user = User.objects.get(username__iexact = value)
39 except User.DoesNotExist:
40 return self.cleaned_data['username']
41 raise forms.ValidationError('This username is already taken. ' + \
42 'Please choose another.')
44 def clean_email(self):
45 value = self.cleaned_data['email']
47 user = User.objects.get(email__iexact = value)
48 except User.DoesNotExist:
49 return self.cleaned_data['email']
50 raise forms.ValidationError('This email address is already in use ' + \
51 'for the account "%s".\n' % user.username)
54 return self.cleaned_data
56 class LoginForm(forms.Form):
57 username = forms.CharField(max_length = 30)
58 password = forms.CharField(widget = forms.PasswordInput)
60 class BundleForm(forms.ModelForm):
61 name = forms.RegexField(regex = r'^[^/]+$', max_length=50, label=u'Name',
62 error_messages = {'invalid': 'Bundle names can\'t contain slashes'})
66 fields = ['name', 'public']
68 class CreateBundleForm(BundleForm):
69 def __init__(self, *args, **kwargs):
70 super(CreateBundleForm, self).__init__(*args, **kwargs)
77 name = self.cleaned_data['name']
78 count = Bundle.objects.filter(owner = self.instance.owner, \
81 raise forms.ValidationError('A bundle called %s already exists' \
85 class DeleteBundleForm(forms.Form):
86 name = 'deletebundleform'
87 form_name = forms.CharField(initial = name, widget = forms.HiddenInput)
88 bundle_id = forms.IntegerField(widget = forms.HiddenInput)
90 class DelegateField(forms.ModelChoiceField):
91 def __init__(self, project, *args, **kwargs):
92 queryset = User.objects.filter(userprofile__in = \
94 .filter(maintainer_projects = project) \
96 super(DelegateField, self).__init__(queryset, *args, **kwargs)
99 class PatchForm(forms.ModelForm):
100 def __init__(self, instance = None, project = None, *args, **kwargs):
101 if (not project) and instance:
102 project = instance.project
104 raise Exception("meep")
105 super(PatchForm, self).__init__(instance = instance, *args, **kwargs)
106 self.fields['delegate'] = DelegateField(project, required = False)
110 fields = ['state', 'archived', 'delegate']
112 class UserProfileForm(forms.ModelForm):
115 fields = ['primary_project', 'patches_per_page']
117 class OptionalDelegateField(DelegateField):
118 no_change_choice = ('*', 'no change')
121 def __init__(self, no_change_choice = None, *args, **kwargs):
123 if (no_change_choice):
124 self.no_change_choice = no_change_choice
125 super(OptionalDelegateField, self). \
126 __init__(initial = self.no_change_choice[0], *args, **kwargs)
128 def _get_choices(self):
130 super(OptionalDelegateField, self)._get_choices())
131 choices.append(self.no_change_choice)
134 choices = property(_get_choices, forms.ChoiceField._set_choices)
136 def is_no_change(self, value):
137 return value == self.no_change_choice[0]
139 def clean(self, value):
140 if value == self.no_change_choice[0]:
142 return super(OptionalDelegateField, self).clean(value)
144 class OptionalModelChoiceField(forms.ModelChoiceField):
145 no_change_choice = ('*', 'no change')
148 def __init__(self, no_change_choice = None, *args, **kwargs):
150 if (no_change_choice):
151 self.no_change_choice = no_change_choice
152 super(OptionalModelChoiceField, self). \
153 __init__(initial = self.no_change_choice[0], *args, **kwargs)
155 def _get_choices(self):
157 super(OptionalModelChoiceField, self)._get_choices())
158 choices.append(self.no_change_choice)
161 choices = property(_get_choices, forms.ChoiceField._set_choices)
163 def is_no_change(self, value):
164 return value == self.no_change_choice[0]
166 def clean(self, value):
167 if value == self.no_change_choice[0]:
169 return super(OptionalModelChoiceField, self).clean(value)
171 class MultipleBooleanField(forms.ChoiceField):
172 no_change_choice = ('*', 'no change')
173 def __init__(self, *args, **kwargs):
174 super(MultipleBooleanField, self).__init__(*args, **kwargs)
175 self.choices = [self.no_change_choice] + \
176 [(True, 'Archived'), (False, 'Unarchived')]
178 def is_no_change(self, value):
179 return value == self.no_change_choice[0]
181 # TODO: Check whether it'd be worth to use a TypedChoiceField here; I
182 # think that'd allow us to get rid of the custom valid_value() and
183 # to_python() methods.
184 def valid_value(self, value):
185 if value in [v1 for (v1, v2) in self.choices]:
189 def to_python(self, value):
190 if value is None or self.is_no_change(value):
191 return self.no_change_choice[0]
192 elif value == 'True':
194 elif value == 'False':
197 raise ValueError('Unknown value: %s' % value)
199 class MultiplePatchForm(forms.Form):
201 state = OptionalModelChoiceField(queryset = State.objects.all())
202 archived = MultipleBooleanField()
204 def __init__(self, project, *args, **kwargs):
205 super(MultiplePatchForm, self).__init__(*args, **kwargs)
206 self.fields['delegate'] = OptionalDelegateField(project = project,
209 def save(self, instance, commit = True):
210 opts = instance.__class__._meta
212 raise ValueError("The %s could not be changed because the data "
213 "didn't validate." % opts.object_name)
214 data = self.cleaned_data
215 # Update the instance
216 for f in opts.fields:
217 if not f.name in data:
220 field = self.fields.get(f.name, None)
224 if field.is_no_change(data[f.name]):
227 setattr(instance, f.name, data[f.name])
233 class EmailForm(forms.Form):
234 email = forms.EmailField(max_length = 200)
236 UserPersonLinkForm = EmailForm
237 OptinoutRequestForm = EmailForm