def add_fields(self, form, index): """A hook for adding extra fields on to each form instance.""" initial_form_count = self.initial_form_count() if self.can_order: # Only pre-fill the ordering field for initial forms. if index is not None and index < initial_form_count: form.fields[ORDERING_FIELD_NAME] = IntegerField( label=_('Order'), initial=index + 1, required=False, widget=self.get_ordering_widget(), ) else: form.fields[ORDERING_FIELD_NAME] = IntegerField( label=_('Order'), required=False, widget=self.get_ordering_widget(), ) if self.can_delete and (self.can_delete_extra or index < initial_form_count): form.fields[DELETION_FIELD_NAME] = BooleanField(label=_('Delete'), required=False)
class MobileContactCreateForm(ContactQuickForm): is_favorite = BooleanField(label=pgettext_lazy('mobile-contact', 'Is favorite'), required=False) class Meta(ContactQuickForm.Meta): fields = ('last_name', 'first_name', 'phone', 'mobile', 'email') widgets = { 'phone': PhoneInput, 'mobile': PhoneInput, } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.instance.user = self.user # del self.fields['user'] errors = self.errors for fname, field in self.fields.items(): if fname != 'is_favorite': attrs = field.widget.attrs attrs['class'] = 'form-input' if fname not in errors else \ 'form-input form-input-invalid' if field.required: attrs['required'] = '' def clean(self): self.cleaned_data['user'] = self.user # NB: used in super().clean() return super().clean() def save(self, *args, **kwargs): contact = super().save(*args, **kwargs) if self.cleaned_data['is_favorite']: MobileFavorite.objects.create(entity=contact, user=self.user) return contact
class MessageCreateForm(ModelForm): close_it = BooleanField(required=False) class Meta: model = Message fields = ['text', 'close_it'] def __init__(self, request, ticket, *args, **kwargs): super(MessageCreateForm, self).__init__(*args, **kwargs) self.request = request self.ticket = ticket self.fields['close_it'].initial = False def save(self, commit=True): obj = super(MessageCreateForm, self).save(commit=False) obj.owner = self.request.user obj.ticket = self.ticket obj.save() if self.request.user.is_staff and self.cleaned_data['close_it']: obj.ticket.close(self.request.user) else: obj.ticket.touch(self.request.user) return obj
class SnapshotApplicationForm(forms.Form): publish = BooleanField(label=ugettext_noop("Publish?"), required=False) name = CharField(label=ugettext_noop("Name"), required=True) description = CharField(label=ugettext_noop("Description"), required=False, widget=forms.Textarea, help_text=ugettext_noop("A detailed technical description of the application")) deployment_date = CharField(label=ugettext_noop("Deployment date"), required=False) phone_model = CharField(label=ugettext_noop("Phone model"), required=False) user_type = CharField(label=ugettext_noop("User type"), required=False, help_text=ugettext_noop("e.g. CHW, ASHA, RA, etc")) attribution_notes = CharField(label=ugettext_noop("Attribution notes"), required=False, help_text=ugettext_noop("Enter any special instructions to users here. This will be shown just before users copy your project."), widget=forms.Textarea) def __init__(self, *args, **kwargs): super(SnapshotApplicationForm, self).__init__(*args, **kwargs) self.fields.keyOrder = [ 'publish', 'name', 'description', 'deployment_date', 'phone_model', 'user_type', 'attribution_notes' ]
class WorkoutFormCreate(ModelForm): duration = DecimalField( min_value=0, max_value=40, max_digits=5, label="Duration (15 min blocks)", help_text="e.g., for a 30 minute workout, enter '2'.") with_other_class = BooleanField( label="With different class?", help_text="BONUS POINTS! Select this if you worked out with" + "a teammates from a different graduating class, like a" + "Sophomore with a Junior.") workout_date = DateField(initial=datetime.today, widget=SelectDateWidget(years=(2015, 2016)), label="Workout Date", help_text="When did you do the workout?") activity = ModelChoiceField( queryset=Activity.objects.order_by('description')) class Meta: model = Workout fields = [ # Appears in the form in this order: 'workout_date', 'activity', 'with_other_class', 'duration', ] exclude = [ 'user', ] def __init__(self, user=None, *args, **kwargs): super(WorkoutFormCreate, self).__init__(*args, **kwargs) self._user = user
def import_common_template(request): if not request.is_trust: return JsonResponse({ 'result': False, 'message': 'you have no permission to call this api.' }) try: req_data = json.loads(request.body) except Exception: return JsonResponse({ 'result': False, 'message': 'invalid json format' }) template_data = req_data.get('template_data', None) if not template_data: return JsonResponse({ 'result': False, 'message': 'template data can not be none' }) r = read_encoded_template_data(template_data) if not r['result']: return JsonResponse(r) override = BooleanField().to_python(req_data.get('override', False)) try: import_result = CommonTemplate.objects.import_templates(r['data']['template_data'], override) except Exception as e: logger.exception(e) return JsonResponse({ 'result': False, 'message': 'invalid flow data or error occur, please contact administrator' }) return JsonResponse(import_result)
class FormularioLogin(forms.Form): """! Clase que permite crear el formulario de ingreso a la aplicación @author Ing. Leonel P. Hernandez M. (leonelphm at gmail.com) @copyright <a href='https://www.gnu.org/licenses/gpl-3.0.en.html'>GNU Public License versión 3 (GPLv3)</a> @date 09-01-2017 @version 1.0.0 """ contrasena = CharField() usuario = CharField() remember_me = BooleanField() captcha = CaptchaField() class Meta: fields = ('usuario', 'contrasena', 'remember_me' 'captcha') def __init__(self, *args, **kwargs): super(FormularioLogin, self).__init__(*args, **kwargs) self.fields['contrasena'].widget = PasswordInput() self.fields['contrasena'].widget.attrs.update({ 'class': 'form-control', 'placeholder': 'Contraseña' }) self.fields['usuario'].widget.attrs.update({ 'class': 'form-control', 'placeholder': 'Nombre de Usuario' }) self.fields['remember_me'].label = "Recordar" self.fields['remember_me'].widget = CheckboxInput() self.fields['remember_me'].required = False self.fields['captcha'].required = True
class SecurityForm(BaseModelForm): new_password = CharField(widget=PasswordInput, required=False) repeat_new_password = CharField(widget=PasswordInput, required=False) change_password = BooleanField(required=False) current_password = CharField(widget=PasswordInput, required=True) def clean_current_password(self): current_password = self.cleaned_data.get('current_password', '') if not self.request.user.check_password(current_password): raise ValidationError(_('The current password is incorrect.')) return current_password def clean_new_password(self): new_password = self.cleaned_data.get('new_password') if self.cleaned_data['change_password'] and not new_password: raise ValidationError(_('The password can not be empty.')) return new_password def clean_repeat_new_password(self): new_password = self.cleaned_data.get('new_password', '') repeat_new_password = self.cleaned_data.get('repeat_new_password', '') if self.cleaned_data[ 'change_password'] and new_password != repeat_new_password: raise ValidationError(_('Password do not match.')) return repeat_new_password def save(self, commit=True): if self.cleaned_data.get('change_password'): new_password = self.cleaned_data['new_password'] self.instance.set_password(new_password) super(SecurityForm, self).save() class Meta: fields = ('email', 'change_password', 'new_password', 'repeat_new_password') model = get_user_model()
class MarkerForm(ModelForm): title = CharField( label=_("Marker Title"), widget=widgets.TextInput(attrs={'size': 60}), help_text=_( "Please choose a title, then go to the map to set a marker pin")) use_icon = BooleanField( label=_("Use customized marker icon"), initial=False, required=False, ) marker_image = ModelChoiceField( queryset=Image.objects.all(), label=_("Marker Image"), required=False, ) marker_width = GlossaryFormField( widget=CascadingSizeWidget(allowed_units=['px'], required=False), label=_("Marker Width"), required=False, help_text=_("Width of the marker icon in pixels."), ) marker_anchor = GlossaryFormField( widget=MultipleCascadingSizeWidget(['left', 'top'], allowed_units=['px', '%'], required=False), required=False, label=_("Marker Anchor"), help_text= _("The coordinates of the icon's anchor (relative to its top left corner)." ), ) popup_text = HTMLFormField( required=False, help_text=_("Optional rich text to display in popup."), ) position = Field(widget=widgets.HiddenInput) glossary_field_order = [ 'title', 'marker_width', 'marker_anchor', 'popup_text' ] class Meta: exclude = ['glossary'] def __init__(self, *args, **kwargs): try: initial = dict(kwargs['instance'].glossary) has_original = True except (KeyError, AttributeError): initial = {} has_original = False initial.update(kwargs.pop('initial', {})) self.base_fields['position'].initial = json.dumps( initial.pop('position', {})) for key in self.glossary_field_order: self.base_fields[key].initial = initial.get(key) try: self.base_fields['marker_image'].initial = initial['image']['pk'] except KeyError: self.base_fields['marker_image'].initial = None self.base_fields['use_icon'].initial = False else: self.base_fields['use_icon'].initial = True self.base_fields['marker_image'].widget = AdminFileWidget( ManyToOneRel(FilerImageField, Image, 'file_ptr'), site) super(MarkerForm, self).__init__(*args, **kwargs) if has_original: self.fields['title'].help_text = None def clean(self): try: position = self.cleaned_data['position'] if isinstance(position, six.string_types): position = json.loads(position) elif not isinstance(position, dict): raise ValueError except (ValueError, KeyError): raise ValidationError( "Invalid internal position data. Check your Javascript imports." ) else: if 'lat' not in position or 'lng' not in position: # place the marker in the center of the current map position = { k: v for k, v in self.instance.cascade_element. glossary['map_position'].items() if k in ['lat', 'lng'] } self.instance.glossary.update(position=position) marker_image = self.cleaned_data.pop('marker_image', None) if marker_image: image_data = {'pk': marker_image.pk, 'model': 'filer.Image'} self.instance.glossary.update(image=image_data) else: self.instance.glossary.pop('image', None) popup_text = self.cleaned_data.pop('popup_text', None) if strip_tags(popup_text): popup_text = strip_spaces_between_tags(popup_text) self.cleaned_data.update(popup_text=popup_text) for key in self.glossary_field_order: self.instance.glossary.update({key: self.cleaned_data.get(key)})
class SnapshotSettingsForm(SnapshotSettingsMixin): title = CharField(label=ugettext_noop("Title"), required=True, max_length=100) project_type = CharField(label=ugettext_noop("Project Category"), required=True, help_text=ugettext_noop("e.g. MCH, HIV, etc.")) license = ChoiceField(label=ugettext_noop("License"), required=True, choices=LICENSES.items(), widget=Select(attrs={'class': 'input-xxlarge'})) description = CharField( label=ugettext_noop("Long Description"), required=False, widget=forms.Textarea, help_text=ugettext_noop( "A high-level overview of your project as a whole")) short_description = CharField( label=ugettext_noop("Short Description"), required=False, widget=forms.Textarea(attrs={'maxlength': 200}), help_text=ugettext_noop( "A brief description of your project (max. 200 characters)")) share_multimedia = BooleanField( label=ugettext_noop("Share all multimedia?"), required=False, help_text=ugettext_noop( "This will allow any user to see and use all multimedia in this project" )) share_reminders = BooleanField( label=ugettext_noop("Share Reminders?"), required=False, help_text=ugettext_noop( "This will publish reminders along with this project")) image = forms.ImageField( label=ugettext_noop("Exchange image"), required=False, help_text=ugettext_noop( "An optional image to show other users your logo or what your app looks like" )) video = CharField( label=ugettext_noop("Youtube Video"), required=False, help_text=ugettext_noop( "An optional youtube clip to tell users about your app. Please copy and paste a URL to a youtube video" )) cda_confirmed = BooleanField( required=False, label=ugettext_noop("Content Distribution Agreement")) def __init__(self, *args, **kw): super(SnapshotSettingsForm, self).__init__(*args, **kw) self.fields.keyOrder = [ 'title', 'short_description', 'description', 'project_type', 'image', 'video', 'share_multimedia', 'share_reminders', 'license', 'cda_confirmed', ] self.fields['license'].help_text = \ render_to_string('domain/partials/license_explanations.html', { 'extra': _("All un-licensed multimedia files in " "your project will be given this license") }) self.fields['cda_confirmed'].help_text = \ render_to_string('domain/partials/cda_modal.html') def clean_cda_confirmed(self): data_cda = self.cleaned_data['cda_confirmed'] data_publish = self.data.get('publish_on_submit', "no") == "yes" if data_publish and data_cda is False: raise forms.ValidationError( 'You must agree to our Content Distribution Agreement to publish your project.' ) return data_cda def clean_video(self): video = self.cleaned_data['video'] if not video: return video def video_id(value): # http://stackoverflow.com/questions/4356538/how-can-i-extract-video-id-from-youtubes-link-in-python#answer-7936523 """ Examples: - http://youtu.be/SA2iWivDJiE - http://www.youtube.com/watch?v=_oPAwA_Udwc&feature=feedu - http://www.youtube.com/embed/SA2iWivDJiE - http://www.youtube.com/v/SA2iWivDJiE?version=3&hl=en_US """ query = urlparse(value) if query.hostname == 'youtu.be': return query.path[1:] if query.hostname in ('www.youtube.com', 'youtube.com'): if query.path == '/watch': p = parse_qs(query.query) return p['v'][0] if query.path[:7] == '/embed/': return query.path.split('/')[2] if query.path[:3] == '/v/': return query.path.split('/')[2] # fail? return None v_id = video_id(video) if not v_id: raise forms.ValidationError( 'This is not a correctly formatted youtube URL. Please use a different URL.' ) return v_id def clean(self): cleaned_data = self.cleaned_data sm = cleaned_data["share_multimedia"] license = cleaned_data["license"] app_ids = self._get_apps_to_publish() if sm and license not in self.dom.most_restrictive_licenses( apps_to_check=app_ids): license_choices = [ LICENSES[l] for l in self.dom.most_restrictive_licenses( apps_to_check=app_ids) ] msg = render_to_string('domain/partials/restrictive_license.html', {'licenses': license_choices}) self._errors["license"] = self.error_class([msg]) del cleaned_data["license"] sr = cleaned_data["share_reminders"] if sr: # check that the forms referenced by the events in each reminders exist in the project referenced_forms = CaseReminderHandler.get_referenced_forms( domain=self.dom.name) if referenced_forms: apps = [Application.get(app_id) for app_id in app_ids] app_forms = [ f.unique_id for forms in [app.get_forms() for app in apps] for f in forms ] nonexistent_forms = filter(lambda f: f not in app_forms, referenced_forms) nonexistent_forms = [ FormBase.get_form(f) for f in nonexistent_forms ] if nonexistent_forms: msg = """ Your reminders reference forms that are not being published. Make sure the following forms are being published: %s """ % str([f.default_name() for f in nonexistent_forms]).strip('[]') self._errors["share_reminders"] = self.error_class([msg]) return cleaned_data def _get_apps_to_publish(self): app_ids = [] for d, val in self.data.iteritems(): d = d.split('-') if len(d) < 2: continue if d[1] == 'publish' and val == 'on': app_ids.append(d[0]) return app_ids
class DomainMetadataForm(DomainGlobalSettingsForm, SnapshotSettingsMixin): customer_type = ChoiceField(label=_("Customer Type"), choices=(('basic', _('Basic')), ('plus', _('Plus')), ('full', _('Full')))) is_test = ChoiceField(label=_("Test Project"), choices=(('true', _('Test')), ('false', _('Real')), ('none', _('Not Sure')))) commconnect_enabled = BooleanField( label=_("CommConnect Enabled"), required=False, help_text=_("CommConnect is a CommCareHQ module for SMS messages, " "reminders and data collection.")) survey_management_enabled = BooleanField( label=_("Survey Management Enabled"), required=False, help_text=_("Survey Management is a CommCareHQ module for SMS and " "Call Center based surveys for large samples. It is " "under active development. Do not enable for your domain " "unless you're piloting it.")) sms_case_registration_enabled = BooleanField( label=_("Enable Case Registration Via SMS"), required=False) sms_case_registration_type = CharField( label=_("SMS Case Registration Type"), required=False) sms_case_registration_owner_id = ChoiceField( label=_("SMS Case Registration Owner"), required=False, choices=[]) sms_case_registration_user_id = ChoiceField( label=_("SMS Case Registration Submitting User"), required=False, choices=[]) default_sms_backend_id = CharField( label=_("Default SMS Backend"), required=False, help_text=_("This SMS backend will be used if a contact has no " "backend specified.")) call_center_enabled = BooleanField( label=_("Call Center Application"), required=False, help_text=_("Call Center mode is a CommCareHQ module for managing " "call center workflows. It is still under " "active development. Do not enable for your domain unless " "you're actively piloting it.")) call_center_case_owner = ChoiceField( label=_("Call Center Case Owner"), initial=None, required=False, help_text=_("Select the person who will be listed as the owner " "of all cases created for call center users.")) call_center_case_type = CharField( label=_("Call Center Case Type"), required=False, help_text=_( "Enter the case type to be used for FLWs in call center apps")) restrict_superusers = BooleanField( label=_("Restrict Superuser Access"), required=False, help_text=_("If access to a domain is restricted only users added " + "to the domain and staff members will have access.")) ota_restore_caching = BooleanField( label=_("Enable Restore Caching (beta)"), required=False, help_text=_( "Speed up phone restores. Useful if you have users with " "large case lists and are getting timeouts during restore. " "This feature is still in testing. Don't enable unless " "you are an advanced user.")) secure_submissions = BooleanField( label=_("Only accept secure submissions"), required=False, help_text=_( "Turn this on to prevent others from impersonating your " "mobile workers. To use, all of your deployed applications " "must be using secure submissions."), ) cloudcare_releases = ChoiceField( label=_("CloudCare should use"), initial=None, required=False, choices=( ('stars', _('Latest starred version')), ('nostars', _('Every version (not recommended)')), ), help_text=_("Choose whether CloudCare should use the latest " "starred build or every build in your application.")) def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) domain = kwargs.pop('domain', None) super(DomainMetadataForm, self).__init__(*args, **kwargs) if not (user and user.is_previewer): self.fields['call_center_enabled'].widget = forms.HiddenInput() self.fields['call_center_case_owner'].widget = forms.HiddenInput() self.fields['call_center_case_type'].widget = forms.HiddenInput() if not (user and user.is_staff): self.fields['restrict_superusers'].widget = forms.HiddenInput() project = Domain.get_by_name(domain) if project.cloudcare_releases == 'default' or not domain_has_privilege( domain, privileges.CLOUDCARE): # if the cloudcare_releases flag was just defaulted, don't bother showing # this setting at all self.fields['cloudcare_releases'].widget = forms.HiddenInput() if domain is not None: groups = Group.get_case_sharing_groups(domain) users = CommCareUser.by_domain(domain) domain_group_choices = [(group._id, group.name) for group in groups] domain_user_choices = [(user._id, user.raw_username) for user in users] domain_owner_choices = domain_group_choices + domain_user_choices self.fields[ "sms_case_registration_owner_id"].choices = domain_owner_choices self.fields[ "sms_case_registration_user_id"].choices = domain_user_choices call_center_user_choices = [ (user._id, user.raw_username + ' [user]') for user in users ] call_center_group_choices = [(group._id, group.name + ' [group]') for group in groups] self.fields["call_center_case_owner"].choices = \ [('', '')] + \ call_center_user_choices + \ call_center_group_choices def _validate_sms_registration_field(self, field_name, error_msg): value = self.cleaned_data.get(field_name) if value is not None: value = value.strip() if self.cleaned_data.get("sms_case_registration_enabled", False): if value is None or value == "": raise forms.ValidationError(error_msg) return value def clean_sms_case_registration_type(self): return self._validate_sms_registration_field( "sms_case_registration_type", _("Please enter a default case type for cases that register themselves via sms." )) def clean_sms_case_registration_owner_id(self): return self._validate_sms_registration_field( "sms_case_registration_owner_id", _("Please enter a default owner for cases that register themselves via sms." )) def clean_sms_case_registration_user_id(self): return self._validate_sms_registration_field( "sms_case_registration_user_id", _("Please enter a default submitting user for cases that register themselves via sms." )) def save(self, request, domain): res = DomainGlobalSettingsForm.save(self, request, domain) if not res: return False try: domain.project_type = self.cleaned_data['project_type'] domain.customer_type = self.cleaned_data['customer_type'] domain.is_test = self.cleaned_data['is_test'] domain.commconnect_enabled = self.cleaned_data.get( 'commconnect_enabled', False) domain.survey_management_enabled = self.cleaned_data.get( 'survey_management_enabled', False) domain.sms_case_registration_enabled = self.cleaned_data.get( 'sms_case_registration_enabled', False) domain.sms_case_registration_type = self.cleaned_data.get( 'sms_case_registration_type') domain.sms_case_registration_owner_id = self.cleaned_data.get( 'sms_case_registration_owner_id') domain.sms_case_registration_user_id = self.cleaned_data.get( 'sms_case_registration_user_id') domain.default_sms_backend_id = self.cleaned_data.get( 'default_sms_backend_id') domain.call_center_config.enabled = self.cleaned_data.get( 'call_center_enabled', False) if domain.call_center_config.enabled: domain.internal.using_call_center = True domain.call_center_config.case_owner_id = self.cleaned_data.get( 'call_center_case_owner', None) domain.call_center_config.case_type = self.cleaned_data.get( 'call_center_case_type', None) domain.restrict_superusers = self.cleaned_data.get( 'restrict_superusers', False) domain.ota_restore_caching = self.cleaned_data.get( 'ota_restore_caching', False) cloudcare_releases = self.cleaned_data.get('cloudcare_releases') if cloudcare_releases and domain.cloudcare_releases != 'default': # you're never allowed to change from default domain.cloudcare_releases = cloudcare_releases secure_submissions = self.cleaned_data.get('secure_submissions', False) apps_to_save = [] if secure_submissions != domain.secure_submissions: for app in ApplicationBase.by_domain(domain.name): if app.secure_submissions != secure_submissions: app.secure_submissions = secure_submissions apps_to_save.append(app) domain.secure_submissions = secure_submissions domain.save() if apps_to_save: ApplicationBase.bulk_save(apps_to_save) return True except Exception, e: logging.exception("couldn't save project settings - error is %s" % e) return False
class MarkerForm(EntangledModelForm): title = CharField( label=_("Marker Title"), widget=widgets.TextInput(attrs={'size': 60}), help_text=_( "Please choose a title, then go to the map to set a marker pin")) use_icon = BooleanField( label=_("Use customized marker icon"), initial=False, required=False, ) marker_image = AdminImageFormField( ManyToOneRel(FilerImageField, Image, 'file_ptr'), Image.objects.all(), label=_("Marker Image"), required=False, to_field_name='image_file', ) marker_width = SizeField( label=_("Marker Width"), allowed_units=['px'], required=False, help_text=_("Width of the marker icon in pixels."), ) marker_anchor = MultiSizeField( ['left', 'top'], label=_("Marker Anchor"), allowed_units=['px', '%'], required=False, help_text= _("The coordinates of the icon's anchor (relative to its top left corner)." ), ) popup_text = HTMLFormField( required=False, help_text=_("Optional rich text to display in popup."), ) position = HiddenDictField() class Meta: entangled_fields = { 'glossary': [ 'title', 'use_icon', 'marker_image', 'marker_width', 'marker_anchor', 'popup_text', 'position' ] } def clean(self): cleaned_data = super().clean() try: position = cleaned_data['position'] if isinstance(position, str): position = json.loads(position) elif not isinstance(position, dict): raise ValueError except (ValueError, KeyError): raise ValidationError( "Invalid internal position data. Check your Javascript imports." ) else: if 'lat' not in position or 'lng' not in position: # place the marker in the center of the current map position = { k: v for k, v in self.instance.cascade_element. glossary['map_position'].items() if k in ['lat', 'lng'] } cleaned_data['position'] = position popup_text = cleaned_data.pop('popup_text', '') if strip_tags(popup_text): cleaned_data['popup_text'] = strip_spaces_between_tags(popup_text) return cleaned_data
class PLMObjectCreationForm(forms.ModelForm): auto = BooleanField( required=False, initial=True, help_text= _("Checking this box, you allow OpenPLM to set the reference of the object." )) clean_reference = _clean_reference clean_revision = _clean_revision def __init__(self, user, start, inbulk_cache, *args, **kwargs): data = kwargs.get("data") if data is None: initial = get_initial_creation_data(user, self.Meta.model, start, inbulk_cache) initial.update(kwargs.pop("initial", {})) kwargs["initial"] = initial self.start = start self.inbulk_cache = inbulk_cache self.user = user super(PLMObjectCreationForm, self).__init__(*args, **kwargs) # lifecycles and groups are cached if inbulk_cache is a dictionary # this is an optimization if several creation forms are displayed # in one request # for example, the decomposition of a STEP file can display # a lot of creation forms # display only valid groups field = self.fields["group"] field.cache_choices = inbulk_cache is not None if inbulk_cache is None or "group" not in inbulk_cache: groups = user.groups.all().values_list("id", flat=True) field.queryset = m.GroupInfo.objects.filter( id__in=groups).order_by("name") if inbulk_cache is not None: # a bit ugly but ModelChoiceField reevalute the # queryset if cache_choices is False and choice_cache # is not populated inbulk_cache["group"] = field.queryset list(field.choices) # populates choice_cache inbulk_cache["gr_cache"] = field.choice_cache else: field.queryset = inbulk_cache["group"] field.choice_cache = inbulk_cache["gr_cache"] field.error_messages["invalid_choice"] = INVALID_GROUP if data is None and "group" not in initial: # set initial value of group to the last selected group try: field.initial = inbulk_cache["gr_initial"] except (KeyError, TypeError): try: last_created_object = m.PLMObject.objects.filter( creator=user).order_by("-ctime")[0] last_group = last_created_object.group except IndexError: last_group = field.queryset[0] if field.queryset else None if last_group in field.queryset: field.initial = last_group if inbulk_cache: inbulk_cache["gr_initial"] = field.initial # do not accept the cancelled lifecycle field = self.fields["lifecycle"] field.cache_choices = inbulk_cache is not None if inbulk_cache is None or "lifecycles" not in inbulk_cache: lifecycles = m.Lifecycle.objects.filter(type=m.Lifecycle.STANDARD).\ exclude(pk=m.get_cancelled_lifecycle().pk).order_by("name") self.fields["lifecycle"].queryset = lifecycles if inbulk_cache is not None: inbulk_cache["lifecycles"] = lifecycles list(field.choices) inbulk_cache["lc_cache"] = field.choice_cache else: lifecycles = inbulk_cache["lifecycles"] self.fields["lifecycle"].queryset = lifecycles field.choice_cache = inbulk_cache["lc_cache"] def clean(self): cleaned_data = self.cleaned_data ref = cleaned_data.get("reference", "") rev = cleaned_data.get("revision", "") auto = cleaned_data.get("auto", False) inbulk = getattr(self, "inbulk_cache") cls = self.Meta.model user = self.user if auto and not ref: cleaned_data["reference"] = ref = get_new_reference( user, cls, self.start, inbulk) if not auto and not ref: self.errors['reference'] = [ _("You did not check the Auto box: the reference is required.") ] if cls.objects.filter(type=cls.__name__, revision=rev, reference=ref).exists(): if not auto: raise ValidationError( _("An object with the same type, reference and revision already exists" )) else: cleaned_data["reference"] = get_new_reference( user, cls, self.start, inbulk) elif cls.objects.filter(type=cls.__name__, reference=ref).exists(): raise ValidationError( _("An object with the same type and reference exists, you may consider to revise it." )) return cleaned_data
class HttpBackendForm(BackendForm): url = TrimmedCharField( label=ugettext_noop("URL"), ) message_param = TrimmedCharField( label=ugettext_noop("Message Parameter"), ) number_param = TrimmedCharField( label=ugettext_noop("Phone Number Parameter"), ) include_plus = BooleanField( required=False, label=ugettext_noop("Include '+' in Phone Number"), ) method = ChoiceField( label=ugettext_noop("HTTP Request Method"), choices=( ("GET", "GET"), ("POST", "POST") ), ) additional_params = RecordListField( input_name="additional_params", label=ugettext_noop("Additional Parameters"), ) def __init__(self, *args, **kwargs): if "initial" in kwargs and "additional_params" in kwargs["initial"]: additional_params_dict = kwargs["initial"]["additional_params"] kwargs["initial"]["additional_params"] = [ {"name": key, "value": value} for key, value in additional_params_dict.items() ] super(HttpBackendForm, self).__init__(*args, **kwargs) def clean_url(self): value = self.cleaned_data.get("url") if is_url_or_host_banned(value): raise ValidationError(_("Invalid URL")) return value def clean_additional_params(self): value = self.cleaned_data.get("additional_params") result = {} for pair in value: name = pair["name"].strip() value = pair["value"].strip() if name == "" or value == "": raise ValidationError("Please enter both name and value.") if name in result: raise ValidationError("Parameter name entered twice: %s" % name) result[name] = value return result @property def gateway_specific_fields(self): return crispy.Fieldset( _("HTTP Settings"), 'url', 'method', 'message_param', 'number_param', 'include_plus', 'additional_params', )
class DomainMetadataForm(DomainGlobalSettingsForm, SnapshotSettingsMixin): customer_type = ChoiceField(label='Customer Type', choices=(('basic', 'Basic'), ('plus', 'Plus'), ('full', 'Full'))) is_test = ChoiceField(label='Test Project', choices=tf_choices('Test', 'Real')) survey_management_enabled = BooleanField(label='Survey Management Enabled', required=False) sms_case_registration_enabled = BooleanField( label='Enable Case Registration Via SMS', required=False) sms_case_registration_type = CharField(label='SMS Case Registration Type', required=False) sms_case_registration_owner_id = ChoiceField( label='SMS Case Registration Owner', required=False, choices=[]) sms_case_registration_user_id = ChoiceField( label='SMS Case Registration Submitting User', required=False, choices=[]) default_sms_backend_id = CharField( label="Default SMS Backend", required=False, help_text= "This SMS backend will be used if a contact has no backend specified.") commtrack_enabled = BooleanField( label='CommTrack Enabled', required=False, help_text= 'CommTrack is a CommCareHQ module for logistics, inventory tracking, and supply chain management. It is still under active development. Do not enable for your domain unless you\'re actively piloting it.' ) def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) domain = kwargs.pop('domain', None) super(DomainMetadataForm, self).__init__(*args, **kwargs) if not (user and user.is_previewer): # commtrack is pre-release self.fields['commtrack_enabled'].widget = forms.HiddenInput() if domain is not None: groups = Group.get_case_sharing_groups(domain) users = CommCareUser.by_domain(domain) domain_owner_choices = [(group._id, group.name) for group in groups] domain_user_choices = [(user._id, user.raw_username) for user in users] domain_owner_choices += domain_user_choices self.fields[ "sms_case_registration_owner_id"].choices = domain_owner_choices self.fields[ "sms_case_registration_user_id"].choices = domain_user_choices def _validate_sms_registration_field(self, field_name, error_msg): value = self.cleaned_data.get(field_name) if value is not None: value = value.strip() if self.cleaned_data.get("sms_case_registration_enabled", False): if value is None or value == "": raise forms.ValidationError(error_msg) return value def clean_sms_case_registration_type(self): return self._validate_sms_registration_field( "sms_case_registration_type", _("Please enter a default case type for cases that register themselves via sms." )) def clean_sms_case_registration_owner_id(self): return self._validate_sms_registration_field( "sms_case_registration_owner_id", _("Please enter a default owner for cases that register themselves via sms." )) def clean_sms_case_registration_user_id(self): return self._validate_sms_registration_field( "sms_case_registration_user_id", _("Please enter a default submitting user for cases that register themselves via sms." )) def save(self, request, domain): res = DomainGlobalSettingsForm.save(self, request, domain) if not res: return False try: domain.project_type = self.cleaned_data['project_type'] domain.customer_type = self.cleaned_data['customer_type'] domain.is_test = self.cleaned_data['is_test'] == 'true' domain.survey_management_enabled = self.cleaned_data.get( 'survey_management_enabled', False) domain.sms_case_registration_enabled = self.cleaned_data.get( 'sms_case_registration_enabled', False) domain.sms_case_registration_type = self.cleaned_data.get( 'sms_case_registration_type') domain.sms_case_registration_owner_id = self.cleaned_data.get( 'sms_case_registration_owner_id') domain.sms_case_registration_user_id = self.cleaned_data.get( 'sms_case_registration_user_id') domain.default_sms_backend_id = self.cleaned_data.get( 'default_sms_backend_id') domain.commtrack_enabled = self.cleaned_data.get( 'commtrack_enabled', False) commtrack_util.bootstrap_default(domain) domain.save() return True except Exception: return False
class ConfirmTOSForm(Form): confirm = BooleanField(required=True)
def add_delete_field_to_form(): DeadlineForm.base_fields["DELETE"] = BooleanField(required=False) yield del DeadlineForm.base_fields["DELETE"]
class KeywordForm(Form): domain = None keyword_id = None keyword = CharField(label=gettext_noop("Keyword")) description = TrimmedCharField(label=gettext_noop("Description")) override_open_sessions = BooleanField( required=False, initial=False, label=gettext_noop("Override open SMS Surveys"), ) allow_keyword_use_by = ChoiceField( required=False, label=gettext_noop("Allow Keyword Use By"), initial='any', choices=( ('any', gettext_noop("Both Mobile Workers and Cases")), ('users', gettext_noop("Mobile Workers Only")), ('cases', gettext_noop("Cases Only")), )) sender_content_type = ChoiceField(label=gettext_noop("Send to Sender"), ) sender_message = TrimmedCharField( required=False, label=gettext_noop("Message"), ) sender_app_and_form_unique_id = ChoiceField( required=False, label=gettext_noop("Survey"), ) other_recipient_content_type = ChoiceField( required=False, label=gettext_noop("Notify Another Person"), initial=NO_RESPONSE, ) other_recipient_type = ChoiceField( required=False, initial=False, label=gettext_noop("Recipient"), choices=KEYWORD_RECIPIENT_CHOICES, ) other_recipient_id = ChoiceField( required=False, label=gettext_noop("Group Name"), ) other_recipient_message = TrimmedCharField( required=False, label=gettext_noop("Message"), ) other_recipient_app_and_form_unique_id = ChoiceField( required=False, label=gettext_noop("Survey"), ) process_structured_sms = BooleanField( required=False, label=gettext_noop( "Process incoming keywords as a Structured Message"), ) structured_sms_app_and_form_unique_id = ChoiceField( required=False, label=gettext_noop("Survey"), ) use_custom_delimiter = BooleanField( required=False, label=gettext_noop("Use Custom Delimiter"), ) delimiter = TrimmedCharField( required=False, label=gettext_noop("Please Specify Delimiter"), ) use_named_args_separator = BooleanField( required=False, label=gettext_noop("Use Joining Character"), ) use_named_args = BooleanField( required=False, label=gettext_noop("Use Named Answers"), ) named_args_separator = TrimmedCharField( required=False, label=gettext_noop("Please Specify Joining Characcter"), ) named_args = RecordListField( input_name="named_args", initial=[], ) def __init__(self, *args, **kwargs): if 'domain' in kwargs: self.domain = kwargs.pop('domain') if 'keyword_id' in kwargs: self.keyword_id = kwargs.pop('keyword_id') self.process_structured_sms = False if 'process_structured' in kwargs: self.process_structured_sms = kwargs.pop('process_structured') super(KeywordForm, self).__init__(*args, **kwargs) self.fields['sender_content_type'].choices = self.content_type_choices self.fields[ 'other_recipient_content_type'].choices = self.content_type_choices self.fields['other_recipient_id'].choices = self.group_choices self.fields[ 'sender_app_and_form_unique_id'].choices = self.form_choices self.fields[ 'other_recipient_app_and_form_unique_id'].choices = self.form_choices self.fields[ 'structured_sms_app_and_form_unique_id'].choices = self.form_choices from corehq.apps.reminders.views import KeywordsListView self.helper = FormHelper() self.helper.form_class = "form form-horizontal" self.helper.label_class = 'col-sm-3 col-md-2' self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' layout_fields = [ crispy.Fieldset( _('Basic Information'), crispy.Field( 'keyword', data_bind="value: keyword, " "valueUpdate: 'afterkeydown', " "event: {keyup: updateExampleStructuredSMS}", ), crispy.Field( 'description', data_bind="text: description", ), ), ] if self.process_structured_sms: layout_fields.append( crispy.Fieldset( _("Structured Message Options"), crispy.Field( 'structured_sms_app_and_form_unique_id', data_bind="value: structuredSmsAppAndFormUniqueId", css_class="hqwebapp-select2", ), hqcrispy.B3MultiField( _("Delimiters"), crispy.Div( crispy.Div(InlineField( twbscrispy.PrependedText( 'use_custom_delimiter', '', data_bind="checked: useCustomDelimiter, " "click: updateExampleStructuredSMS"), block_css_class="span2", ), css_class='col-md-4 col-lg-4'), crispy.Div(InlineField( 'delimiter', data_bind="value: delimiter, " "valueUpdate: 'afterkeydown', " "event: {keyup: updateExampleStructuredSMS}," "visible: useCustomDelimiter", block_css_class="span4", ), css_class='col-md-4 col-lg-4')), ), hqcrispy.B3MultiField( _("Named Answers"), crispy.Div(InlineField( twbscrispy.PrependedText( 'use_named_args', '', data_bind="checked: useNamedArgs, " "click: updateExampleStructuredSMS"), ), css_class='col-md-4 col-lg-4'), hqcrispy.ErrorsOnlyField('named_args'), crispy.Div(data_bind="template: {" " name: 'ko-template-named-args', " " data: $data" "}, " "visible: useNamedArgs", ), ), hqcrispy.B3MultiField( _("Joining Characters"), crispy.Div( crispy.Div(InlineField( twbscrispy.PrependedText( 'use_named_args_separator', '', data_bind="checked: useNamedArgsSeparator, " "click: updateExampleStructuredSMS"), ), css_class='col-md-4 col-lg-4'), crispy.Div(InlineField( 'named_args_separator', data_bind="value: namedArgsSeparator, " "valueUpdate: 'afterkeydown', " "event: {keyup: updateExampleStructuredSMS}," "visible: useJoiningCharacter", ), css_class='col-md-6 col-lg-4')), data_bind="visible: useNamedArgs", ), hqcrispy.B3MultiField( _("Example Structured Message"), crispy.HTML('<pre style="background: white;" ' 'data-bind="text: exampleStructuredSms">' '</pre>'), ), ), ) layout_fields.extend([ crispy.Fieldset( _("Response"), crispy.Field( 'sender_content_type', data_bind="value: senderContentType", ), crispy.Div( crispy.Field( 'sender_message', data_bind="text: senderMessage", ), data_bind="visible: isMessageSMS", ), crispy.Div( crispy.Field( 'sender_app_and_form_unique_id', data_bind="value: senderAppAndFormUniqueId", css_class="hqwebapp-select2", ), data_bind="visible: isMessageSurvey", ), crispy.Field( 'other_recipient_content_type', data_bind="value: otherRecipientContentType", ), hqcrispy.B3MultiField( "", crispy.Div( crispy.HTML( '<h4 style="margin-bottom: 20px;">%s</h4>' % _("Recipient Information"), ), crispy.Field( 'other_recipient_type', data_bind="value: otherRecipientType", ), crispy.Div( crispy.Field( 'other_recipient_id', data_bind="value: otherRecipientId", ), data_bind="visible: showRecipientGroup", ), crispy.Div( crispy.Field( 'other_recipient_message', data_bind="value: otherRecipientMessage", ), data_bind= "visible: otherRecipientContentType() == 'sms'", ), crispy.Div( crispy.Field( 'other_recipient_app_and_form_unique_id', data_bind= "value: otherRecipientAppAndFormUniqueId", css_class="hqwebapp-select2", ), data_bind= "visible: otherRecipientContentType() == 'survey'", ), css_class="well", data_bind="visible: notifyOthers", ), ), ), crispy.Fieldset( _("Advanced Options"), twbscrispy.PrependedText( 'override_open_sessions', '', data_bind="checked: overrideOpenSessions", ), 'allow_keyword_use_by', ), hqcrispy.FormActions( twbscrispy.StrictButton( _("Save"), css_class='btn-primary', type='submit', ), crispy.HTML( '<a href="%s" class="btn btn-default">Cancel</a>' % reverse(KeywordsListView.urlname, args=[self.domain]))), ]) self.helper.layout = crispy.Layout(*layout_fields) @property def content_type_choices(self): return KEYWORD_CONTENT_CHOICES @property @memoized def group_choices(self): group_ids = Group.ids_by_domain(self.domain) groups = [] for group_doc in iter_docs(Group.get_db(), group_ids): groups.append((group_doc['_id'], group_doc['name'])) return groups @property @memoized def form_choices(self): available_forms = get_form_list(self.domain) return [('', '')] + [(form['code'], form['name']) for form in available_forms] @property def current_values(self): values = {} for field_name in self.fields.keys(): values[field_name] = self[field_name].value() return values def clean_keyword(self): value = self.cleaned_data.get("keyword") if value is not None: value = value.strip().upper() if value is None or value == "": raise ValidationError(_("This field is required.")) if len(value.split()) > 1: raise ValidationError(_("Keyword should be one word.")) duplicate = Keyword.get_keyword(self.domain, value) if duplicate and duplicate.couch_id != self.keyword_id: raise ValidationError(_("Keyword already exists.")) return value def clean_sender_message(self): value = self.cleaned_data.get("sender_message") if self.cleaned_data.get("sender_content_type") == METHOD_SMS: if value is None or value == "": raise ValidationError(_("This field is required.")) return value else: return None def clean_sender_app_and_form_unique_id(self): value = self.cleaned_data.get("sender_app_and_form_unique_id") if self.cleaned_data.get("sender_content_type") == METHOD_SMS_SURVEY: if value is None: raise ValidationError( _("Please create a form first, and then add a keyword " "for it.")) validate_app_and_form_unique_id(value, self.domain) return value else: return None def clean_other_recipient_message(self): value = self.cleaned_data.get("other_recipient_message") if self.cleaned_data.get("other_recipient_content_type") == METHOD_SMS: if value is None or value == "": raise ValidationError(_("This field is required.")) return value else: return None def clean_other_recipient_app_and_form_unique_id(self): value = self.cleaned_data.get("other_recipient_app_and_form_unique_id") if self.cleaned_data.get( "other_recipient_content_type") == METHOD_SMS_SURVEY: if value is None: raise ValidationError( _("Please create a form first, and then " "add a keyword for it.")) validate_app_and_form_unique_id(value, self.domain) return value else: return None def clean_structured_sms_app_and_form_unique_id(self): value = self.cleaned_data.get("structured_sms_app_and_form_unique_id") if self.process_structured_sms: if value is None: raise ValidationError( _("Please create a form first, and then add a " "keyword for it.")) validate_app_and_form_unique_id(value, self.domain) return value else: return None def clean_delimiter(self): value = self.cleaned_data.get("delimiter", None) if self.process_structured_sms and self.cleaned_data[ "use_custom_delimiter"]: if value is None or value == "": raise ValidationError(_("This field is required.")) return value else: return None def clean_named_args(self): if self.process_structured_sms and self.cleaned_data["use_named_args"]: use_named_args_separator = self.cleaned_data[ "use_named_args_separator"] value = self.cleaned_data.get("named_args") data_dict = {} for d in value: name = d["name"].strip().upper() xpath = d["xpath"].strip() if name == "" or xpath == "": raise ValidationError( _("Name and xpath are both required fields.")) for k, v in data_dict.items(): if (not use_named_args_separator and (k.startswith(name) or name.startswith(k))): raise ValidationError( _("Cannot have two names overlap: ") + "(%s, %s)" % (k, name)) if use_named_args_separator and k == name: raise ValidationError( _("Cannot use the same name twice: ") + name) if v == xpath: raise ValidationError( _("Cannot reference the same xpath twice: ") + xpath) data_dict[name] = xpath return data_dict else: return {} def clean_named_args_separator(self): value = self.cleaned_data["named_args_separator"] if (self.process_structured_sms and self.cleaned_data["use_named_args"] and self.cleaned_data["use_named_args_separator"]): if value is None or value == "": raise ValidationError(_("This field is required.")) if value == self.cleaned_data["delimiter"]: raise ValidationError( _("Delimiter and joining character cannot be the same.")) return value else: return None def clean_other_recipient_type(self): if self.cleaned_data['other_recipient_content_type'] == NO_RESPONSE: return None value = self.cleaned_data["other_recipient_type"] if value == RECIPIENT_OWNER: if self.cleaned_data['allow_keyword_use_by'] != 'cases': raise ValidationError( _("In order to send to the case's owner you must restrict " "keyword initiation only to cases.")) return value def clean_other_recipient_id(self): if self.cleaned_data['other_recipient_content_type'] == NO_RESPONSE: return None value = self.cleaned_data["other_recipient_id"] recipient_type = self.cleaned_data.get("other_recipient_type", None) if recipient_type == RECIPIENT_USER_GROUP: try: g = Group.get(value) assert g.doc_type == "Group" assert g.domain == self.domain except Exception: raise ValidationError("Invalid Group.") return value else: return None
class BackendForm(Form): domain = None backend_id = None name = CharField(label=ugettext_noop("Name")) display_name = CharField( label=ugettext_noop("Display Name"), required=False, ) description = CharField( label=ugettext_noop("Description"), widget=forms.Textarea, required=False, ) give_other_domains_access = BooleanField( required=False, label=ugettext_noop("Give other domains access.")) authorized_domains = CharField( required=False, label=ugettext_noop("List of authorized domains"), help_text=ugettext_lazy("A comma-separated list of domain names")) reply_to_phone_number = CharField( required=False, label=ugettext_noop("Reply-To Phone Number"), ) inbound_api_key = CharField( required=False, label=ugettext_lazy("Inbound API Key"), disabled=True, ) opt_out_keywords = CharField( required=False, label=ugettext_noop("List of opt out keywords"), help_text=ugettext_lazy("A comma-separated list of keywords")) opt_in_keywords = CharField( required=False, label=ugettext_noop("List of opt in keywords"), help_text=ugettext_lazy("A comma-separated list of keywords")) @property def is_global_backend(self): return self.domain is None @property def general_fields(self): fields = [ crispy.Field('name', css_class='input-xxlarge'), crispy.Field('display_name', css_class='input-xxlarge'), crispy.Field('description', css_class='input-xxlarge', rows="3"), crispy.Field('reply_to_phone_number', css_class='input-xxlarge'), crispy.Field('opt_out_keywords'), crispy.Field('opt_in_keywords') ] if not self.is_global_backend: fields.extend([ crispy.Field( twbscrispy.PrependedText( 'give_other_domains_access', '', data_bind="checked: share_backend")), crispy.Div( 'authorized_domains', data_bind="visible: showAuthorizedDomains", ), ]) if self.backend_id: backend = SQLMobileBackend.load(self.backend_id) if backend.show_inbound_api_key_during_edit: self.fields[ 'inbound_api_key'].initial = backend.inbound_api_key fields.append(crispy.Field('inbound_api_key')) return fields def __init__(self, *args, **kwargs): button_text = kwargs.pop('button_text', _("Create SMS Gateway")) self.domain = kwargs.pop('domain') self.backend_id = kwargs.pop('backend_id') super(BackendForm, self).__init__(*args, **kwargs) self.helper = HQFormHelper() self.helper.form_method = 'POST' self.helper.layout = crispy.Layout( crispy.Fieldset(_('General Settings'), *self.general_fields), self.gateway_specific_fields, crispy.Fieldset( _("Phone Numbers"), crispy.Div(data_bind="template: {" " name: 'ko-load-balancing-template', " " data: $data" "}", ), data_bind="visible: use_load_balancing", ), hqcrispy.FormActions( StrictButton(button_text, type="submit", css_class='btn-primary'), ), ) if self.backend_id: # When editing, don't allow changing the name because name might be # referenced as a contact-level backend preference. # By setting disabled to True, Django makes sure the value won't change # even if something else gets posted. self.fields['name'].disabled = True @property def gateway_specific_fields(self): return crispy.Div() def clean_name(self): value = self.cleaned_data.get("name") if value is not None: value = value.strip().upper() if value is None or value == "": raise ValidationError(_("This field is required.")) if re.compile(r"\s").search(value) is not None: raise ValidationError(_("Name may not contain any spaces.")) if self.is_global_backend: # We're using the form to create a global backend, so # ensure name is not duplicated among other global backends is_unique = SQLMobileBackend.name_is_unique( value, backend_id=self.backend_id) else: # We're using the form to create a domain-level backend, so # ensure name is not duplicated among other backends owned by this domain is_unique = SQLMobileBackend.name_is_unique( value, domain=self.domain, backend_id=self.backend_id) if not is_unique: raise ValidationError(_("Name is already in use.")) return value def clean_authorized_domains(self): if not self.cleaned_data.get("give_other_domains_access"): return [] else: value = self.cleaned_data.get("authorized_domains") if value is None or value.strip() == "": return [] else: return [domain.strip() for domain in value.split(",")] def clean_opt_out_keywords(self): keywords = self.cleaned_data.get('opt_out_keywords') if not keywords: return [] else: return [kw.strip().upper() for kw in keywords.split(',')] def clean_opt_in_keywords(self): keywords = self.cleaned_data.get('opt_in_keywords') if not keywords: return [] else: return [kw.strip().upper() for kw in keywords.split(',')] def clean_reply_to_phone_number(self): value = self.cleaned_data.get("reply_to_phone_number") if value is None: return None else: value = value.strip() if value == "": return None else: return value
def __init__(self, action, *args, **kwargs): # build the forms from the action attributes try: self.action_item = Action.objects.get(name=action) except ObjectDoesNotExist: self.action_item = Action(name=action, ) attributes = self.action_item.attributes.all() from django.forms.models import fields_for_model model_fields = fields_for_model(Translation) model_fields = {} #for field in model_fields_list: # print(field) # model_fields[ field ] = model_fields_list[field] #for attr in attributes: # if attr.datatype in model_fields: # self.Meta.fields.append(attr.datatype) #if self.action_item.target_type: # if not 'target' in self.Meta.fields: # self.Meta.fields.append('target') super(BaseActionForm, self).__init__(*args, **kwargs) # build fields from attributes attributes = self.action_item.attributes.all() for attr in attributes: if attr.datatype == 'target': qs = Item.objects.filter(id__in=list( get_targets(self.instance, self.action_item.target_type))) att_field = TargetModelChoiceField(queryset=qs, ) elif attr.datatype == 'query': qs = Item.objects.filter(id__in=list( get_targets(self.instance, self.action_item.target_type))) att_field = TargetQueryField(queryset=qs, initial=None) elif attr.datatype == 'string': att_field = CharField(max_length=1024) elif attr.datatype == 'markdown': att_field = CharField(max_length=25600, widget=Textarea) elif attr.datatype == 'description': att_field = CharField(max_length=25600000, widget=Textarea) elif attr.datatype == 'boolean': att_field = BooleanField() elif attr.datatype == 'integer': att_field = IntegerField() elif attr.datatype == 'number': att_field = FloatField() elif attr.datatype == 'email': att_field = EmailField() elif attr.datatype == 'slug': att_field = SlugField() elif attr.datatype == 'url': att_field = URLField() #elif attr.datatype in model_fields: # att_field = model_fields[ attr.datatype ] elif attr.datatype == 'image': att_field = MediaUploadField() else: #continue att_field = CharField(max_length=1024) att_field.initial = attr.default att_field.required = attr.required att_field.label = attr.label att_field.help_text = attr.help self.fields[attr.name] = att_field if attr.hidden: self.fields[attr.name].widget = forms.HiddenInput() if attr.regexp: validator = RegexValidator(attr.regexp, message=attr.regexp_error) if not att_field.validators: att_field.validators = [] att_field.validators.append(validator) self.set_form_control_class()
class CSVPRocessorForm(Form): header = BooleanField(label='Header', initial=False, required=False) validate = BooleanField(label='Form validation', initial=False, required=False) preview_all = BooleanField(label='Preview all records', initial=False, required=False) create_missing = BooleanField(label='Create missing rows', initial=False, required=False) def _head(self, rows=10): with open_csv(self._filename) as csv: output = [] for i in range(rows): output.append(csv.next()) return output def clean(self): found = False # todo: we should try to create a dummy model to force some validation ?? for i, f in enumerate(self._fields): fld = 'fld_%s' % i col = 'col_%s' % i lkf = 'lkf_%s' % i column = self.cleaned_data[col] field_name = self.cleaned_data[fld] lookup_name = self.cleaned_data[lkf] if column >= 0 or field_name: found = True if not (column >= 0 and field_name): self._errors[fld] = self.error_class( [_("Please set both 'column' and 'field'")]) raise ValidationError("Please fix errors below") Field, _u, _u, _u = self._model._meta.get_field_by_name( field_name) if isinstance(Field, ForeignKey): if not lookup_name: self._errors[fld] = self.error_class([ _('Please set lookup field name for "%s"') % field_name ]) else: try: Field.rel.to._meta.get_field_by_name(lookup_name) except Exception as e: self._errors[fld] = self.error_class([e]) if not found: raise ValidationError("Please set columns mapping") return self.cleaned_data def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row): top_errors = self.non_field_errors( ) # Errors that should be displayed above all fields. output, hidden_fields = [], [] for name in ('header', 'preview_all', 'validate', 'create_missing'): field = self.fields[name] bf = BoundField(self, field, name) bf_errors = self.error_class([ conditional_escape(error) for error in bf.errors ]) # Escape and cache in local variable. if bf_errors: top_errors.extend([ u'(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors ]) output.append( '<tr><td class="label" colspan="4">%s</td><td>%s</td></tr>' % (bf.label, unicode(bf))) output.append( u'<tr><th>%s</th><th>%s</th><th class="rex">%s</th><th class="lkf">%s</th><th class="key">%s</th></tr>' % (_('Column'), _('Field'), _('Regex'), _('Lookup Field'), _('pk'))) for i, f in enumerate(self._fields): line = [] error_line = [] rowid = self.fields['col_%s' % i].label for n in ('col_%s', 'fld_%s', 'rex_%s', 'lkf_%s', 'key_%s'): name = n % i field = self.fields[name] bf = BoundField(self, field, name) bf_errors = self.error_class([ conditional_escape(error) for error in bf.errors ]) # Escape and cache in local variable. error_line.append(force_unicode(bf_errors), ) line.append('<td class=%(class)s>%(field)s</td>' % { 'field': unicode(bf), 'class': n[:3] }) output.append('<tr><td colspan="5">%s</td></tr>' % ''.join(error_line)) output.append('<tr>%(line)s</tr>' % { 'line': ''.join(line), 'rowid': rowid }) if top_errors: output.insert(0, error_row % force_unicode(top_errors)) return mark_safe(u'\n'.join(output)) def as_hidden(self): output, hidden_fields = [], [] for name, field in self.fields.items(): field.widget = HiddenInput({'readonly': 'readonly'}) bf = BoundField(self, field, name) output.append(unicode(bf)) return mark_safe(u'\n'.join(output)) def as_table(self): "Returns this form rendered as HTML <tr>s -- excluding the <table></table>." return self._html_output( normal_row= u'<tr%(html_class_attr)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', error_row=u'<tr><td colspan="4">%s</td></tr>', row_ender=u'</td></tr>', help_text_html=u'<br /><span class="helptext">%s</span>', errors_on_separate_row=False)
class InvoiceMassImportForm(ImportForm4CremeEntity): source = EntityExtractorField( models_info=[(Organisation, 'name')], choices=choices, label=pgettext_lazy('billing', 'Source organisation'), ) target = EntityExtractorField( models_info=[(Organisation, 'name'), (Contact, 'last_name')], choices=choices, label=pgettext_lazy('billing', 'Target'), ) override_billing_addr = BooleanField( label=_('Update the billing address'), required=False, help_text=_( 'In update mode, update the billing address from the target.')) override_shipping_addr = BooleanField( label=_('Update the shipping address'), required=False, help_text=_( 'In update mode, update the shipping address from the target.') ) def _post_instance_creation(self, instance, line, updated): super()._post_instance_creation(instance, line, updated) cdata = self.cleaned_data user = self.user append_error = self.append_error source, err_msg = cdata['source'].extract_value(line, user) append_error(err_msg) target, err_msg = cdata['target'].extract_value(line, user) append_error(err_msg) create_rel = partial( Relation.objects.safe_create, subject_entity=instance, user=instance.user, ) # TODO: move this intelligence in models.Base.save() (see regular Forms) if not updated: create_rel(type_id=REL_SUB_BILL_ISSUED, object_entity=source) create_rel(type_id=REL_SUB_BILL_RECEIVED, object_entity=target) instance.billing_address = copy_or_create_address( target.billing_address, instance, _('Billing address')) instance.shipping_address = copy_or_create_address( target.shipping_address, instance, _('Shipping address')) instance.save() else: # Update mode relations = Relation.objects.filter( subject_entity=instance.pk, type__in=(REL_SUB_BILL_ISSUED, REL_SUB_BILL_RECEIVED)) issued_relation = find_first( relations, (lambda r: r.type_id == REL_SUB_BILL_ISSUED), None) received_relation = find_first( relations, (lambda r: r.type_id == REL_SUB_BILL_RECEIVED), None) assert issued_relation is not None assert received_relation is not None if issued_relation.object_entity_id != source: issued_relation.delete() create_rel(type_id=REL_SUB_BILL_ISSUED, object_entity=source) if received_relation.object_entity_id != target: received_relation.delete() create_rel(type_id=REL_SUB_BILL_RECEIVED, object_entity=target) b_change = s_change = False if cdata['override_billing_addr']: b_change = _copy_or_update_address( target, instance, 'billing_address', _('Billing address'), ) if cdata['override_shipping_addr']: s_change = _copy_or_update_address( target, instance, 'shipping_address', _('Shipping address'), ) if b_change or s_change: instance.save()
class EntityEmailForm(base_forms.CremeModelForm): """Mails are related to the selected contacts/organisations & the 'current' entity. Mails are send to selected contacts/organisations. """ sender = EmailField(label=_('Sender')) c_recipients = MultiCreatorEntityField(label=_('Contacts'), required=False, model=Contact, q_filter={'email__gt': ''}) o_recipients = MultiCreatorEntityField(label=_('Organisations'), required=False, model=Organisation, q_filter={'email__gt': ''}) send_me = BooleanField(label=_('Send me a copy of this mail'), required=False) error_messages = { 'no_person': _('Select at least a Contact or an Organisation'), } blocks = base_forms.FieldBlockManager( ('recipients', _('Who'), ['user', 'sender', 'send_me', 'c_recipients', 'o_recipients']), ('content', _('What'), ['subject', 'body', 'body_html']), ('extra', _('With'), ['signature', 'attachments']), ) class Meta: model = EntityEmail fields = ('user', 'sender', 'subject', 'body', 'body_html', 'signature', 'attachments') def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.entity = entity if isinstance(entity, (Contact, Organisation)): fn, msg = ('c_recipients', _('Beware: the contact «{}» has no email address!')) \ if isinstance(entity, Contact) else \ ('o_recipients', _('Beware: the organisation «{}» has no email address!')) field = self.fields[fn] if entity.email: field.initial = [entity.pk] else: field.help_text = msg.format(entity) self.user_contact = contact = self.user.linked_contact if contact.email: self.fields['sender'].initial = contact.email def finalize_recipient_field(name, model): if FieldsConfig.get_4_model(model).is_fieldname_hidden('email'): self.fields[name] = CharField( label=self.fields[name].label, required=False, widget=Label, initial=gettext( 'Beware: the field «Email address» is hidden ;' ' please contact your administrator.'), ) finalize_recipient_field('c_recipients', Contact) finalize_recipient_field('o_recipients', Organisation) def _clean_recipients(self, field_name): if isinstance(self.fields[field_name].widget, Label): return [] recipients = self.cleaned_data.get(field_name) or [] bad_entities = [] for entity in recipients: try: validate_email(entity.email) except ValidationError: bad_entities.append(entity) if bad_entities: msg_format = gettext('The email address for {} is invalid') user = self.user for entity in bad_entities: self.add_error(field_name, msg_format.format(entity.allowed_str(user))) return recipients def clean_c_recipients(self): return self._clean_recipients('c_recipients') def clean_o_recipients(self): return self._clean_recipients('o_recipients') def clean(self): cdata = super().clean() if not self._errors and not cdata['c_recipients'] and not cdata[ 'o_recipients']: raise ValidationError(self.error_messages['no_person'], code='no_person') return cdata def save(self): cdata = self.cleaned_data get_data = cdata.get sender = get_data('sender') subject = get_data('subject') body = get_data('body') body_html = get_data('body_html') signature = get_data('signature') attachments = get_data('attachments') user = get_data('user') sending_error = False def create_n_send_mail(recipient_address): nonlocal sending_error email = EntityEmail.create_n_send_mail( sender=sender, recipient=recipient_address, subject=subject, user=user, body=body, body_html=body_html, signature=signature, attachments=attachments, ) if email.status == MAIL_STATUS_SENDINGERROR: sending_error = True return email with atomic(): if get_data('send_me'): create_n_send_mail(sender) user_contact = self.user_contact create_relation = partial(Relation.objects.create, user=user) for recipient in chain(cdata['c_recipients'], cdata['o_recipients']): email = create_n_send_mail(recipient.email) create_relation(subject_entity=email, type_id=REL_SUB_MAIL_SENDED, object_entity=user_contact) create_relation(subject_entity=email, type_id=REL_SUB_MAIL_RECEIVED, object_entity=recipient) if sending_error: entity_emails_send_type.refresh_job()
class ReminderForm(Form): frequency_period = ChoiceField( choices=(('week', _('Week')), ('month', _('Month'))), widget=forms.Select, required=False, ) deadline_month = ChoiceField( choices=(tuple([(n, convert_to_ordinal(n)) for n in range(1, 31)] + [(31, ugettext_lazy('Last Day'))])), widget=forms.Select, required=False) deadline_week = ChoiceField( choices=(get_translated_weekdays()), widget=forms.Select(attrs={'data-bind': 'random'}), required=False) deadline_type_week = ChoiceField( choices=(('Same', _('Same week')), ('Following', _('Following week'))), widget=forms.Select(attrs={'class': 'deadline_type'}), required=False) deadline_type_month = ChoiceField( choices=(('Same', _('Same month')), ('Following', _('Following month'))), widget=forms.Select(attrs={'class': 'deadline_type'}), required=False) deadline_type = ChoiceField(choices=(('Same', _('Same')), ('Following', _('Following'))), widget=forms.Select, required=False) should_send_reminders_before_deadline = BooleanField(required=False, initial=False) number_of_days_before_deadline = DecimalField( label=ugettext_lazy("days before deadline"), required=False) reminder_text_before_deadline = CharField(widget=forms.Textarea, required=False, label=ugettext_lazy("SMS Text")) should_send_reminders_on_deadline = BooleanField( label=ugettext_lazy("The day of the deadline"), required=False, initial=False) reminder_text_on_deadline = CharField(widget=forms.Textarea, required=False, label=ugettext_lazy("SMS Text")) should_send_reminders_after_deadline = BooleanField( label=ugettext_lazy("days after the deadline"), required=False, initial=False) number_of_days_after_deadline = DecimalField( required=False, label=ugettext_lazy("number of days after deadline")) reminder_text_after_deadline = CharField(widget=forms.Textarea, required=False, label=ugettext_lazy("SMS Text")) whom_to_send_message = BooleanField(label=ugettext_lazy( "Only send reminders to senders who have not already submitted data for the current deadline." ), required=False, initial=True) def __init__(self, *args, **kwargs): super(ReminderForm, self).__init__(*args, **kwargs) deadline_month = ChoiceField( choices=(tuple([(n, convert_to_ordinal(n)) for n in range(1, 31)] + [(31, ugettext_lazy('Last Day'))])), widget=forms.Select, required=False) self.fields["deadline_month"] = deadline_month def clean(self): msg = _("This field is required") if self.cleaned_data.get('should_send_reminders_before_deadline'): if self.cleaned_data.get('number_of_days_before_deadline') is None: self._errors[ 'number_of_days_before_deadline'] = self.error_class([msg]) if self.cleaned_data.get('reminder_text_before_deadline') == '': self.errors[ 'reminder_text_before_deadline'] = self.error_class([msg]) if self.cleaned_data.get( 'should_send_reminders_on_deadline') and self.cleaned_data.get( 'reminder_text_on_deadline') == '': self.errors['reminder_text_on_deadline'] = self.error_class([msg]) if self.cleaned_data.get('should_send_reminders_after_deadline'): if self.cleaned_data.get('number_of_days_after_deadline') is None: self.errors[ 'number_of_days_after_deadline'] = self.error_class([msg]) if self.cleaned_data.get('reminder_text_after_deadline') == '': self.errors['reminder_text_after_deadline'] = self.error_class( [msg]) return self.cleaned_data
def empty_form(self): f = self.form(prefix=self.make_prefix("TEMPLATE")) f.fields["_exists"] = BooleanField(initial=True, widget=HiddenInput) f.fields["_deleted"] = BooleanField(initial=True, required=False, widget=SubmitButton) return f
class MessageForm(Form): schedule_name = CharField( required=True, label=_('Schedule Name'), max_length=1000, ) send_frequency = ChoiceField(required=True, label=_('Send'), choices=(('immediately', _('Immediately')), )) recipients = MessageRecipientField( label=_("Recipient(s)"), help_text=_("Type a username, group name or location"), ) content = ChoiceField( required=True, label=_("Content"), # seems like a weird label? choices= (('sms', _('SMS')), # ('email', _('Email')), # ('sms_survey', _('SMS Survey')), # ('ivr_survey', _('IVR Survey')), )) translate = BooleanField(label=_("Translate this message"), required=False) def __init__(self, *args, **kwargs): self.domain = kwargs.pop('domain') initial = kwargs.get('initial') readonly = False if initial: readonly = (initial.get('send_frequency') == 'immediately') message = initial.get('message', {}) kwargs['initial']['translate'] = '*' not in message kwargs['initial']['non_translated_message'] = message.get('*', '') for lang in self.project_languages: kwargs['initial']['message_%s' % lang] = message.get(lang, '') super(MessageForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_class = 'form form-horizontal' self.helper.label_class = 'col-sm-2 col-md-2 col-lg-2' self.helper.field_class = 'col-sm-10 col-md-3 col-lg-3' self.add_content_fields() if readonly: for field_name, field in self.fields.items(): field.disabled = True layout_fields = [ crispy.Field('schedule_name'), crispy.Field('send_frequency'), crispy.Field( 'recipients', # type='hidden', data_bind='value: message_recipients.value', placeholder=_("Select some recipients")), crispy.Field('content'), crispy.Field('translate', data_bind='checked: translate'), # todo this doesn't hide the label crispy.Field('non_translated_message', data_bind='visible: !translate()'), ] + [ crispy.Field('message_%s' % lang, data_bind='visible: translate') for lang in self.project_languages ] if not readonly: layout_fields += [ hqcrispy.FormActions( twbscrispy.StrictButton( _("Save"), css_class='btn-primary', type='submit', ), ), ] self.helper.layout = crispy.Layout(*layout_fields) @cached_property def project_languages(self): doc = StandaloneTranslationDoc.get_obj(self.domain, 'sms') return getattr(doc, 'langs', ['en']) def add_content_fields(self): self.fields['non_translated_message'] = CharField(label=_("Message"), required=False) for lang in self.project_languages: # TODO support RTL languages self.fields['message_%s' % lang] = CharField( label="{} ({})".format(_("Message"), lang), required=False) @property def current_values(self): values = {} for field_name in self.fields.keys(): values[field_name] = self[field_name].value() return values def clean_recipients(self): data = self.cleaned_data['recipients'] # TODO Will need to add more than user ids # TODO batch id verification for user_id in data: user = CommCareUser.get_db().get(user_id) assert user[ 'domain'] == self.domain, "User must be in the same domain" return data
class InvoiceMassImportForm(ImportForm4CremeEntity): source = EntityExtractorField( models_info=[(Organisation, 'name')], choices=choices, label=pgettext_lazy('billing', 'Source organisation'), ) target = EntityExtractorField( models_info=[ (Organisation, 'name'), (Contact, 'last_name'), ], choices=choices, label=pgettext_lazy('billing', 'Target'), ) override_billing_addr = BooleanField( label=_('Update the billing address'), required=False, help_text=_('In update mode, update the billing address from the target.'), ) override_shipping_addr = BooleanField( label=_('Update the shipping address'), required=False, help_text=_('In update mode, update the shipping address from the target.'), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) model = self._meta.model if model.generate_number_in_create: self.fields['number'].help_text = _( 'If you chose an organisation managed by Creme as source organisation, ' 'a number will be automatically generated for created «{}».' ).format(model._meta.verbose_name_plural) def _pre_instance_save(self, instance, line): cdata = self.cleaned_data append_error = self.append_error user = self.user for prop_name in ('source', 'target'): entity, err_msg = cdata[prop_name].extract_value(line, user) setattr(instance, prop_name, entity) # Error is really appended if 'err_msg' is not empty append_error(err_msg) def _post_instance_creation(self, instance, line, updated): super()._post_instance_creation(instance, line, updated) if updated: cdata = self.cleaned_data target = instance.target b_change = s_change = False if cdata['override_billing_addr']: b_change = _copy_or_update_address( target, instance, 'billing_address', _('Billing address'), ) if cdata['override_shipping_addr']: s_change = _copy_or_update_address( target, instance, 'shipping_address', _('Shipping address'), ) if b_change or s_change: instance.save()
def properties(self): return { "subprocess_has_update": BooleanField(), "has_subprocess": BooleanField() }
def properties(self): return { 'subprocess_has_update': BooleanField(), 'has_subprocess': BooleanField() }
class LoginForm(forms.Form): """! Clase del formulario de logeo @date 01-03-2017 @version 1.0.0 """ ## Campo de la constraseña contrasena = CharField() ## Nombre del usuario usuario = CharField() ## Formulario de recordarme remember_me = BooleanField() ## Campo del captcha #captcha = CaptchaField() def __init__(self, *args, **kwargs): """! Metodo que sobreescribe cuando se inicializa el formulario @date 01-03-2017 @param self <b>{object}</b> Objeto que instancia la clase @param args <b>{list}</b> Lista de los argumentos @param kwargs <b>{dict}</b> Diccionario con argumentos @return Retorna el formulario validado """ super(LoginForm, self).__init__(*args, **kwargs) self.fields['contrasena'].widget = PasswordInput() self.fields['contrasena'].widget.attrs.update({ 'class': 'validate', 'placeholder': 'Contraseña' }) self.fields['usuario'].widget.attrs.update({ 'class': 'validate', 'placeholder': 'Nombre de Usuario' }) self.fields['remember_me'].label = "Recordar" self.fields['remember_me'].widget = CheckboxInput() self.fields['remember_me'].required = False #self.fields['captcha'].label = "Captcha" #self.fields['captcha'].widget.attrs.update({'class': 'validate'}) def clean(self): """! Método que valida si el usuario a autenticar es valido @date 21-04-2017 @param self <b>{object}</b> Objeto que instancia la clase @return Retorna el campo con los errores """ usuario = self.cleaned_data['usuario'] contrasena = self.cleaned_data['contrasena'] usuario = authenticate(username=usuario, password=contrasena) if (not usuario): msg = "Verifique su usuario o contraseña" self.add_error('usuario', msg) class Meta: fields = ('usuario', 'contrasena', 'remember_me')