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