Package omeroweb :: Package webclient :: Module custom_forms
[hide private]
[frames] | no frames]

Source Code for Module omeroweb.webclient.custom_forms

  1  #!/usr/bin/env python 
  2  # 
  3  # 
  4  # Copyright (C) 2011 University of Dundee & Open Microscopy Environment. 
  5  # All rights reserved. 
  6  # 
  7  # This program is free software: you can redistribute it and/or modify 
  8  # it under the terms of the GNU Affero General Public License as 
  9  # published by the Free Software Foundation, either version 3 of the 
 10  # License, or (at your option) any later version. 
 11  # 
 12  # This program is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15  # GNU Affero General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU Affero General Public License 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 19  # 
 20   
 21  import re 
 22  from itertools import chain 
 23   
 24  from django import forms 
 25  from django.forms.widgets import SelectMultiple, CheckboxInput, MultipleHiddenInput 
 26  from django.utils.encoding import force_unicode 
 27  from django.utils.html import escape, conditional_escape 
 28  from django.utils.safestring import mark_safe 
 29   
 30  from django.forms.fields import Field, EMPTY_VALUES 
 31  from django.forms.widgets import Select 
 32  from django.forms import ModelChoiceField, ValidationError 
 33  from django.utils.translation import ugettext_lazy as _ 
 34  from django.utils.encoding import smart_unicode 
 35   
 36  from omero_model_FileAnnotationI import FileAnnotationI 
 37  from omero_model_TagAnnotationI import TagAnnotationI 
 38  from omero_model_LongAnnotationI import LongAnnotationI 
 39   
 40  ################################################################## 
 41  # Fields 
 42   
43 -class MultiEmailField(forms.Field):
44 - def clean(self, value):
45 if not value: 46 raise forms.ValidationError('No email.') 47 if value.count(' ') > 0: 48 raise forms.ValidationError('Use only separator ";". Remove every spaces.') 49 emails = value.split(';') 50 for email in emails: 51 if not self.is_valid_email(email): 52 raise forms.ValidationError('%s is not a valid e-mail address. Use separator ";"' % email) 53 return emails
54
55 - def is_valid_email(self, email):
56 email_pat = re.compile(r"(?:^|\s)[-a-z0-9_.]+@(?:[-a-z0-9]+\.)+[a-z]{2,6}(?:\s|$)",re.IGNORECASE) 57 return email_pat.match(email) is not None
58
59 -class UrlField(forms.Field):
60 - def clean(self, value):
61 if not value: 62 raise forms.ValidationError('No url.') 63 if not self.is_valid_url(value): 64 raise forms.ValidationError('%s is not a valid url' % value) 65 return value
66
67 - def is_valid_url(self, url):
68 url_pat = re_http = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',re.IGNORECASE) 69 return url_pat.match(url) is not None
70 71 ################################################################## 72 # Metadata queryset iterator for group form 73
74 -class MetadataQuerySetIterator(object):
75 - def __init__(self, queryset, empty_label, cache_choices):
76 self.queryset = queryset 77 self.empty_label = empty_label 78 self.cache_choices = cache_choices
79
80 - def __iter__(self):
81 if self.empty_label is not None: 82 yield (u"", self.empty_label) 83 for obj in self.queryset: 84 yield (obj.value, smart_unicode(obj.value))
85 # Clear the QuerySet cache if required. 86 #if not self.cache_choices: 87 #self.queryset._result_cache = None 88
89 -class MetadataModelChoiceField(ModelChoiceField):
90
91 - def _get_choices(self):
92 # If self._choices is set, then somebody must have manually set 93 # the property self.choices. In this case, just return self._choices. 94 if hasattr(self, '_choices'): 95 return self._choices 96 # Otherwise, execute the QuerySet in self.queryset to determine the 97 # choices dynamically. Return a fresh QuerySetIterator that has not 98 # been consumed. Note that we're instantiating a new QuerySetIterator 99 # *each* time _get_choices() is called (and, thus, each time 100 # self.choices is accessed) so that we can ensure the QuerySet has not 101 # been consumed. 102 return MetadataQuerySetIterator(self.queryset, self.empty_label, 103 self.cache_choices)
104
105 - def _set_choices(self, value):
106 # This method is copied from ChoiceField._set_choices(). It's necessary 107 # because property() doesn't allow a subclass to overwrite only 108 # _get_choices without implementing _set_choices. 109 self._choices = self.widget.choices = list(value)
110 111 choices = property(_get_choices, _set_choices) 112
113 - def clean(self, value):
114 Field.clean(self, value) 115 if value in EMPTY_VALUES: 116 return None 117 res = False 118 for q in self.queryset: 119 if long(value) == q.id: 120 res = True 121 if not res: 122 raise ValidationError(self.error_messages['invalid_choice']) 123 return value
124
125 -class AnnotationQuerySetIterator(object):
126
127 - def __init__(self, queryset, empty_label, cache_choices):
128 self.queryset = queryset 129 self.empty_label = empty_label 130 self.cache_choices = cache_choices
131
132 - def __iter__(self):
133 if self.empty_label is not None: 134 yield (u"", self.empty_label) 135 for obj in self.queryset: 136 textValue = None 137 if isinstance(obj._obj, FileAnnotationI): 138 textValue = (len(obj.getFileName()) < 45) and (obj.getFileName()) or (obj.getFileName()[:42]+"...") 139 elif isinstance(obj._obj, TagAnnotationI): 140 if obj.textValue is not None: 141 if obj.ns is not None and obj.ns!="": 142 textValue = (len(obj.textValue) < 45) and ("%s (tagset)" % obj.textValue) or ("%s (tagset)" % obj.textValue[:42]+"...") 143 else: 144 textValue = (len(obj.textValue) < 45) and (obj.textValue) or (obj.textValue[:42]+"...") 145 elif isinstance(obj._obj, LongAnnotationI): 146 textValue = obj.longValue 147 else: 148 textValue = obj.textValue 149 150 if isinstance(textValue, str): 151 l = len(textValue) 152 if l > 55: 153 textValue = "%s..." % textValue[:55] 154 oid = obj.id 155 yield (oid, smart_unicode(textValue))
156 # Clear the QuerySet cache if required. 157 #if not self.cache_choices: 158 #self.queryset._result_cache = None 159
160 -class AnnotationModelChoiceField(ModelChoiceField):
161
162 - def _get_choices(self):
163 # If self._choices is set, then somebody must have manually set 164 # the property self.choices. In this case, just return self._choices. 165 if hasattr(self, '_choices'): 166 return self._choices 167 # Otherwise, execute the QuerySet in self.queryset to determine the 168 # choices dynamically. Return a fresh QuerySetIterator that has not 169 # been consumed. Note that we're instantiating a new QuerySetIterator 170 # *each* time _get_choices() is called (and, thus, each time 171 # self.choices is accessed) so that we can ensure the QuerySet has not 172 # been consumed. 173 return AnnotationQuerySetIterator(self.queryset, self.empty_label, 174 self.cache_choices)
175
176 - def _set_choices(self, value):
177 # This method is copied from ChoiceField._set_choices(). It's necessary 178 # because property() doesn't allow a subclass to overwrite only 179 # _get_choices without implementing _set_choices. 180 self._choices = self.widget.choices = list(value)
181 182 choices = property(_get_choices, _set_choices) 183
184 - def clean(self, value):
185 Field.clean(self, value) 186 if value in EMPTY_VALUES: 187 return None 188 res = False 189 for q in self.queryset: 190 if long(value) == q.id: 191 res = True 192 if not res: 193 raise ValidationError(self.error_messages['invalid_choice']) 194 return value
195
196 -class AnnotationModelMultipleChoiceField(AnnotationModelChoiceField):
197 """A MultipleChoiceField whose choices are a model QuerySet.""" 198 hidden_widget = MultipleHiddenInput 199 default_error_messages = { 200 'list': _(u'Enter a list of values.'), 201 'invalid_choice': _(u'Select a valid choice. That choice is not one of the' 202 u' available choices.'), 203 }
204 - def __init__(self, queryset, cache_choices=False, required=True, 205 widget=SelectMultiple, label=None, initial=None, 206 help_text=None, *args, **kwargs):
207 super(AnnotationModelMultipleChoiceField, self).__init__(queryset, None, 208 cache_choices, required, widget, label, initial, help_text, 209 *args, **kwargs)
210
211 - def clean(self, value):
212 if self.required and not value: 213 raise ValidationError(self.error_messages['required']) 214 elif not self.required and not value: 215 return [] 216 if not isinstance(value, (list, tuple)): 217 raise ValidationError(self.error_messages['list']) 218 final_values = [] 219 for val in value: 220 try: 221 long(val) 222 except: 223 raise ValidationError(self.error_messages['invalid_choice']) 224 else: 225 res = False 226 for q in self.queryset: 227 if long(val) == q.id: 228 res = True 229 if not res: 230 raise ValidationError(self.error_messages['invalid_choice']) 231 else: 232 final_values.append(val) 233 return final_values
234 235 # Object queryset iterator for group form
236 -class ObjectQuerySetIterator(object):
237 - def __init__(self, queryset, empty_label, cache_choices):
238 self.queryset = queryset 239 self.empty_label = empty_label 240 self.cache_choices = cache_choices
241
242 - def __iter__(self):
243 if self.empty_label is not None: 244 yield (u"", self.empty_label) 245 for obj in self.queryset: 246 if hasattr(obj.id, 'val'): 247 yield (obj.id.val, smart_unicode(obj.id.val)) 248 else: 249 yield (obj.id, smart_unicode(obj.id))
250 # Clear the QuerySet cache if required. 251 #if not self.cache_choices: 252 #self.queryset._result_cache = None 253
254 -class ObjectModelChoiceField(ModelChoiceField):
255
256 - def _get_choices(self):
257 # If self._choices is set, then somebody must have manually set 258 # the property self.choices. In this case, just return self._choices. 259 if hasattr(self, '_choices'): 260 return self._choices 261 # Otherwise, execute the QuerySet in self.queryset to determine the 262 # choices dynamically. Return a fresh QuerySetIterator that has not 263 # been consumed. Note that we're instantiating a new QuerySetIterator 264 # *each* time _get_choices() is called (and, thus, each time 265 # self.choices is accessed) so that we can ensure the QuerySet has not 266 # been consumed. 267 return ObjectQuerySetIterator(self.queryset, self.empty_label, 268 self.cache_choices)
269
270 - def _set_choices(self, value):
271 # This method is copied from ChoiceField._set_choices(). It's necessary 272 # because property() doesn't allow a subclass to overwrite only 273 # _get_choices without implementing _set_choices. 274 self._choices = self.widget.choices = list(value)
275 276 choices = property(_get_choices, _set_choices) 277
278 - def clean(self, value):
279 Field.clean(self, value) 280 if value in EMPTY_VALUES: 281 return None 282 res = False 283 for q in self.queryset: 284 if hasattr(q.id, 'val'): 285 if long(value) == q.id.val: 286 res = True 287 else: 288 if long(value) == q.id: 289 res = True 290 if not res: 291 raise ValidationError(self.error_messages['invalid_choice']) 292 return value
293
294 -class ObjectModelMultipleChoiceField(ObjectModelChoiceField):
295 """A MultipleChoiceField whose choices are a model QuerySet.""" 296 hidden_widget = MultipleHiddenInput 297 default_error_messages = { 298 'list': _(u'Enter a list of values.'), 299 'invalid_choice': _(u'Select a valid choice. That choice is not one of the' 300 u' available choices.'), 301 } 302
303 - def __init__(self, queryset, cache_choices=False, required=True, 304 widget=SelectMultiple, label=None, initial=None, 305 help_text=None, *args, **kwargs):
306 super(ObjectModelMultipleChoiceField, self).__init__(queryset, None, 307 cache_choices, required, widget, label, initial, help_text, 308 *args, **kwargs)
309
310 - def clean(self, value):
311 if self.required and not value: 312 raise ValidationError(self.error_messages['required']) 313 elif not self.required and not value: 314 return [] 315 if not isinstance(value, (list, tuple)): 316 raise ValidationError(self.error_messages['list']) 317 final_values = [] 318 for val in value: 319 try: 320 long(val) 321 except: 322 raise ValidationError(self.error_messages['invalid_choice']) 323 else: 324 res = False 325 for q in self.queryset: 326 if hasattr(q.id, 'val'): 327 if long(val) == q.id.val: 328 res = True 329 else: 330 if long(val) == q.id: 331 res = True 332 if not res: 333 raise ValidationError(self.error_messages['invalid_choice']) 334 else: 335 final_values.append(val) 336 return final_values
337