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):
63 fields = ['name', 'public']
65 class CreateBundleForm(forms.ModelForm):
66 def __init__(self, *args, **kwargs):
67 super(CreateBundleForm, self).__init__(*args, **kwargs)
74 name = self.cleaned_data['name']
75 count = Bundle.objects.filter(owner = self.instance.owner, \
78 raise forms.ValidationError('A bundle called %s already exists' \
82 class DeleteBundleForm(forms.Form):
83 name = 'deletebundleform'
84 form_name = forms.CharField(initial = name, widget = forms.HiddenInput)
85 bundle_id = forms.IntegerField(widget = forms.HiddenInput)
87 class DelegateField(forms.ModelChoiceField):
88 def __init__(self, project, *args, **kwargs):
89 queryset = User.objects.filter(userprofile__in = \
91 .filter(maintainer_projects = project) \
93 super(DelegateField, self).__init__(queryset, *args, **kwargs)
96 class PatchForm(forms.ModelForm):
97 def __init__(self, instance = None, project = None, *args, **kwargs):
98 if (not project) and instance:
99 project = instance.project
101 raise Exception("meep")
102 super(PatchForm, self).__init__(instance = instance, *args, **kwargs)
103 self.fields['delegate'] = DelegateField(project, required = False)
107 fields = ['state', 'archived', 'delegate']
109 class UserProfileForm(forms.ModelForm):
112 fields = ['primary_project', 'patches_per_page']
114 class OptionalDelegateField(DelegateField):
115 no_change_choice = ('*', 'no change')
118 def __init__(self, no_change_choice = None, *args, **kwargs):
120 if (no_change_choice):
121 self.no_change_choice = no_change_choice
122 super(OptionalDelegateField, self). \
123 __init__(initial = self.no_change_choice[0], *args, **kwargs)
125 def _get_choices(self):
127 super(OptionalDelegateField, self)._get_choices())
128 choices.append(self.no_change_choice)
131 choices = property(_get_choices, forms.ChoiceField._set_choices)
133 def is_no_change(self, value):
134 return value == self.no_change_choice[0]
136 def clean(self, value):
137 if value == self.no_change_choice[0]:
139 return super(OptionalDelegateField, self).clean(value)
141 class OptionalModelChoiceField(forms.ModelChoiceField):
142 no_change_choice = ('*', 'no change')
145 def __init__(self, no_change_choice = None, *args, **kwargs):
147 if (no_change_choice):
148 self.no_change_choice = no_change_choice
149 super(OptionalModelChoiceField, self). \
150 __init__(initial = self.no_change_choice[0], *args, **kwargs)
152 def _get_choices(self):
154 super(OptionalModelChoiceField, self)._get_choices())
155 choices.append(self.no_change_choice)
158 choices = property(_get_choices, forms.ChoiceField._set_choices)
160 def is_no_change(self, value):
161 return value == self.no_change_choice[0]
163 def clean(self, value):
164 if value == self.no_change_choice[0]:
166 return super(OptionalModelChoiceField, self).clean(value)
168 class MultipleBooleanField(forms.ChoiceField):
169 no_change_choice = ('*', 'no change')
170 def __init__(self, *args, **kwargs):
171 super(MultipleBooleanField, self).__init__(*args, **kwargs)
172 self.choices = [self.no_change_choice] + \
173 [(True, 'Archived'), (False, 'Unarchived')]
175 def is_no_change(self, value):
176 return value == self.no_change_choice[0]
178 # TODO: Check whether it'd be worth to use a TypedChoiceField here; I
179 # think that'd allow us to get rid of the custom valid_value() and
180 # to_python() methods.
181 def valid_value(self, value):
182 if value in [v1 for (v1, v2) in self.choices]:
186 def to_python(self, value):
187 if value is None or self.is_no_change(value):
188 return self.no_change_choice[0]
189 elif value == 'True':
191 elif value == 'False':
194 raise ValueError('Unknown value: %s' % value)
196 class MultiplePatchForm(forms.Form):
198 state = OptionalModelChoiceField(queryset = State.objects.all())
199 archived = MultipleBooleanField()
201 def __init__(self, project, *args, **kwargs):
202 super(MultiplePatchForm, self).__init__(*args, **kwargs)
203 self.fields['delegate'] = OptionalDelegateField(project = project,
206 def save(self, instance, commit = True):
207 opts = instance.__class__._meta
209 raise ValueError("The %s could not be changed because the data "
210 "didn't validate." % opts.object_name)
211 data = self.cleaned_data
212 # Update the instance
213 for f in opts.fields:
214 if not f.name in data:
217 field = self.fields.get(f.name, None)
221 if field.is_no_change(data[f.name]):
224 setattr(instance, f.name, data[f.name])
230 class EmailForm(forms.Form):
231 email = forms.EmailField(max_length = 200)
233 UserPersonLinkForm = EmailForm
234 OptinoutRequestForm = EmailForm