def _formfield(self, initial): return TypedChoiceField( choices=self._args['choices'], coerce=int, initial=initial, empty_value=None, )
def _formfield(self, initial): return TypedChoiceField( choices=self._CHOICES.items(), coerce=int, widget=RadioSelect, initial=initial, empty_value=None, )
def __init__(self, section=None, *args, **kwargs): super().__init__(*args, **kwargs) self.section = section # Lines which are in the section where we create our line. self.section_lines = section_lines = [] # The lines after the one we create (but not in the same section): # their order have to be incremented self.next_lines = next_lines = [] # Order of the last line before our section (used if our section is empty). self.empty_section_order = 1 nodes = [*SectionTree(self.pform)] section_id = section.id if section else None # Filling of 'section_lines' & 'next_lines' node_it = reversed(nodes) try: while True: node = next(node_it) if not node.is_section: if node.section_id == section_id: section_lines.append(node) else: next_lines.append(node) elif node.id == section_id: previous_line = find_first( node_it, (lambda node: not node.is_section), None) if previous_line: self.empty_section_order = previous_line.order + 1 break except StopIteration: pass if section_lines: section_lines.reverse() # TODO: cached_gettext ?? msg_fmt = gettext('Before: «{question}» (#{number})').format choices = [ (0, gettext('Start of section')), *((i, msg_fmt(question=node.question, number=node.number)) for i, node in enumerate(section_lines[1:], start=1)), (len(section_lines), gettext('End of section')), ] self.fields['index'] = TypedChoiceField( label=gettext('Order'), coerce=int, choices=choices, initial=len(choices) - 1, )
def __init__(self, *args, model_instance=None, **kwargs): result = super().__init__(*args, **kwargs) self.fields['status'] = TypedChoiceField( choices=Task.STATUS_CHOICES, initial=model_instance and model_instance.status or None, label='', widget=StatusChoice( instance_pk=model_instance and model_instance.pk or None)) return result
class PollFormLineConditionsForm(CremeForm): use_or = TypedChoiceField( label=_('Use OR or AND between conditions'), choices=[(0, _('AND')), (1, _('OR'))], coerce=(lambda x: bool(int(x))), widget=CremeRadioSelect, ) conditions = PollFormLineConditionsField(label=_('Conditions'), required=False) def __init__(self, entity, line, *args, **kwargs): super().__init__(*args, **kwargs) self.line = line self.old_conditions = conditions = line.get_conditions() fields = self.fields # TODO: remove 'bool' if no more nullable fields['use_or'].initial = int(bool(line.conds_use_or)) conditions_f = fields['conditions'] conditions_f.sources = entity.lines.filter(order__lt=line.order) conditions_f.initial = conditions def save(self, *args, **kwargs): line = self.line cdata = self.cleaned_data update_model_instance(line, conds_use_or=cdata['use_or']) conds2del = [] # TODO: select for update ?? for old_condition, condition in zip_longest(self.old_conditions, cdata['conditions']): if not condition: # Less new conditions that old conditions => delete conditions in excess conds2del.append(old_condition.id) elif not old_condition: condition.line = line condition.save() elif old_condition.update(condition): old_condition.save() if conds2del: PollFormLineCondition.objects.filter(pk__in=conds2del).delete()
class PollFormLineCreateForm(_PollFormLineForm): type = TypedChoiceField( label=_('Type'), choices=PollLineType.choices(), coerce=int, initial=PollLineType.STRING, ) lower_bound = IntegerField( label=_('Lower bound'), required=False, help_text=_('For integer type only.'), ) upper_bound = IntegerField( label=_('Upper bound'), required=False, help_text=_('For integer type only.'), ) choices = CharField( widget=Textarea(), label=_('Available choices'), required=False, help_text=_('Give the possible choices (one per line) ' 'if you choose the type "Choice list".'), ) def __init__(self, section=None, *args, **kwargs): super().__init__(*args, **kwargs) self.section = section self.section_lines = section_lines = [ ] # Lines which are in the section where we create our line self.next_lines = next_lines = [ ] # The lines after the one we create (but not in the same section): # their order have to be incremented self.empty_section_order = 1 # Order of the last line before our section (used if our section is empty) nodes = [*SectionTree(self.pform)] section_id = section.id if section else None # Filling of 'section_lines' & 'next_lines' node_it = reversed(nodes) try: while True: node = next(node_it) if not node.is_section: if node.section_id == section_id: section_lines.append(node) else: next_lines.append(node) elif node.id == section_id: previous_line = find_first( node_it, (lambda node: not node.is_section), None) if previous_line: self.empty_section_order = previous_line.order + 1 break except StopIteration: pass if section_lines: section_lines.reverse() msg_fmt = gettext('Before: «{question}» (#{number})' ).format # TODO: cached_gettext ?? choices = [ (0, gettext('Start of section')), *((i, msg_fmt(question=node.question, number=node.number)) for i, node in enumerate(section_lines[1:], start=1)), (len(section_lines), gettext('End of section')) ] self.fields['index'] = TypedChoiceField( label=gettext('Order'), coerce=int, choices=choices, initial=len(choices) - 1, ) def clean(self): cleaned_data = super().clean() if not self._errors: get_data = cleaned_data.get self.type_args = PollLineType.build_serialized_args( ptype=cleaned_data['type'], lower_bound=get_data('lower_bound'), upper_bound=get_data('upper_bound'), choices=[ *enumerate( filter(None, (choice.strip() for choice in get_data( 'choices', '').split('\n'))), start=1, ) ], ) # Can raise Validation errors return cleaned_data def save(self, *args, **kwargs): cdata = self.cleaned_data section_lines = self.section_lines if not section_lines: index = 0 order = self.empty_section_order else: index = cdata['index'] if index < len(section_lines): order = section_lines[index].order else: order = section_lines[-1].order + 1 instance = self.instance instance.pform = self.pform instance.section = self.section instance.order = order instance.type = cdata['type'] instance.type_args = self.type_args for line in chain(section_lines[index:], self.next_lines): line.order += 1 line.save() return super().save(*args, **kwargs)
class EventModelForm(ModelForm): update_date = DateTimeField( input_formats=(DATE_FORMAT, ), widget=widgets.DateTimeInput(format=DATE_FORMAT)) foia = TypedChoiceField(empty_value=None, initial=None, coerce=lambda pk: Foia.objects.get(pk=pk)) email = ModelChoiceField(queryset=InboundEmail.objects.all(), required=False, widget=widgets.HiddenInput) def __init__(self, *args, **kwargs): super(EventModelForm, self).__init__(*args, **kwargs) if 'initial' in kwargs and 'email' in kwargs['initial']: email = InboundEmail.objects.filter( pk=kwargs['initial']['email']).select_related( 'sender').first() sender_projects = Project.objects.filter( collaborators=email.sender).values_list('pk', flat=True) prefix_re = re.compile('(re|fwd):', flags=re.IGNORECASE) generic_language_re = re.compile( r'((?:tpia|record(?:s)*|foia|public\s+information)\s+request)(?!\s+log(?:s)*)', flags=re.IGNORECASE | re.VERBOSE) def strip_subject(subject): prefix_removed = prefix_re.sub('', subject) generics_removed = generic_language_re.sub('', prefix_removed) return ''.join(_ for _ in generics_removed if _.isalpha() or _ == ' ') cleaned_email_subject = strip_subject(email.subject) def match_email_to_foia(foia): score = fuzz.ratio( strip_subject(foia['request_subject']), cleaned_email_subject, ) # Boost the score if the sender is the same and for requests # that are in one of the sender's projects if foia['email__sender__pk'] == email.sender.pk: score += 25 elif foia['project__pk'] is not None and \ foia['project__pk'] in sender_projects: score += 20 days_apart = (email.sent.date() - foia['sent']).days # Penalize requests that are older than 30 days, but max out # the penalty at the 180-day mark min_days = 30 max_days = 180 normalized_days_apart = min(max(min_days, days_apart), max_days) - min_days score *= (1 - float(normalized_days_apart) / float(max_days)) return score all_foias = Foia.objects.all().select_related( 'email', 'email__sender').values( 'pk', 'sent', 'request_subject', 'email__sender__pk', 'email__sender__last_name', 'project__pk', ) for foia in all_foias: foia['label'] = '%s: %s' % ( foia['email__sender__last_name'], foia['request_subject'], ) ranked_foias = sorted(all_foias, key=match_email_to_foia, reverse=True) self.fields['foia'].choices = [( f['pk'], f['label'], ) for f in ranked_foias] else: self.fields['foia'].choices = Foia.objects.all().select_related( 'email__sender').values_list('pk', 'request_subject') class Meta: model = Event fields = ( 'foia', 'status', 'update_date', 'amount_asked', 'amount_paid', 'notes', 'email', ) widgets = {'status': RadioSelect(choices=Event.STATUS_CHOICES)}
class CartAddProductForm(forms.Form): quantity = TypedChoiceField(choices=PRODUCT_QUANTITY_CHOICES, coerce=int) override = forms.BooleanField(required=False, initial=False, widget=forms.HiddenInput)
class UserSettingsConfigForm(CremeForm): url = URLField(label=_(u'Server URL'), required=False) url_examples = ChoiceField( label=_(u'Server URL examples'), required=False, help_text=_(u'Some common configurations'), choices=chain((("", ""), ), COMMONS_SERVER_URL_CFG), widget=Select( attrs={'onchange': 'this.form.url.value=$(this).val();'}), ) domain = CharField(label=_(u'Domain'), required=False) ssl = ChoiceField( label=_(u'Is secure'), required=False, choices=(('', _('Default')), (1, _('Yes')), (0, _('No'))), ) login = CharField(label=_(u'Login'), required=False) password = CharField(label=_(u'Password'), required=False, widget=PasswordInput) sync_calendars = TypedChoiceField( label=_(u'Synchronize activities (calendars)'), help_text=_(u'Choose if either you want to synchronize ' u'your activities in both way or not.'), choices=_BOOL_CHOICES, coerce=_choice_2_bool, ) sync_contacts = TypedChoiceField( label=_(u'Synchronize contacts'), help_text=_(u'Choose if either you want to synchronize ' u'your contacts in both way or not.'), choices=_BOOL_CHOICES, coerce=_choice_2_bool, ) blocks = FieldBlockManager( ('mobile_sync', _(u'Mobile synchronization configuration'), '*'), ('what_sync', _(u'What to sync'), ('sync_calendars', 'sync_contacts')), ) def __init__(self, *args, **kwargs): super(UserSettingsConfigForm, self).__init__(*args, **kwargs) # user = self.user # self._svalues_cache = svalues_cache = {} # sv_get = SettingValue.objects.get # def get_svalue(key_id): # sv = svalues_cache[key_id] = sv_get(key_id=key_id, user=user) # return sv fields = self.fields user_settings = self.user.settings # sv_doesnotexist = SettingValue.DoesNotExist def_svalues = get_default_server_setting_values() let_empty_msg = ugettext( u"Let empty to get the default configuration (currently '%s').") url_field = fields['url'] # url_field.help_text = let_empty_msg % sv_get(key_id=MAPI_SERVER_URL).value url_field.help_text = let_empty_msg % (def_svalues['url'].value or '') # try: # url_field.initial = get_svalue(USER_MOBILE_SYNC_SERVER_URL).value # except sv_doesnotexist: # pass url_field.initial = self._old_url = user_settings.get( user_msync_server_url_key, '') domain_field = fields['domain'] # domain_field.help_text = let_empty_msg % sv_get(key_id=MAPI_DOMAIN).value domain_field.help_text = let_empty_msg % (def_svalues['domain'].value or '') # try: # domain_field.initial = get_svalue(USER_MOBILE_SYNC_SERVER_DOMAIN).value # except sv_doesnotexist: # pass domain_field.initial = user_settings.get(user_msync_server_domain_key, '') ssl_field = fields['ssl'] ssl_field.help_text = ugettext( u"Let 'Default' to get the default configuration (currently '%s')." ) % ( # ugettext('Yes') if sv_get(key_id=MAPI_SERVER_SSL).value else ugettext('No') ugettext('Yes') if def_svalues['ssl'].value else ugettext('No')) # try: # ssl_field.initial = int(get_svalue(USER_MOBILE_SYNC_SERVER_SSL).value) # except sv_doesnotexist: # pass ssl_field.initial = int( user_settings.get(user_msync_server_ssl_key, False)) # ---------------------------------- # try: # fields['login'].initial = get_svalue(USER_MOBILE_SYNC_SERVER_LOGIN).value # except sv_doesnotexist: # pass fields['login'].initial = self._old_login = user_settings.get( user_msync_server_login_key, '') pwd_field = fields['password'] # try: # pwd_field.initial = Cipher.decrypt_from_db(get_svalue(USER_MOBILE_SYNC_SERVER_PWD).value) # pwd_field.widget.render_value = True # except sv_doesnotexist: # pass try: pwd_field.initial = Cipher.decrypt_from_db( user_settings[user_msync_server_pwd_key]) except KeyError: pass else: pwd_field.widget.render_value = True # try: # fields['sync_calendars'].initial = int(get_svalue(USER_MOBILE_SYNC_ACTIVITIES).value) # except sv_doesnotexist: # pass fields['sync_calendars'].initial = int( user_settings.get(user_msync_activities_key, False)) # try: # fields['sync_contacts'].initial = int(get_svalue(USER_MOBILE_SYNC_CONTACTS).value) # except sv_doesnotexist: # pass fields['sync_contacts'].initial = int( user_settings.get(user_msync_contacts_key, False)) def clean_ssl(self): try: return _choice_2_bool(self.cleaned_data['ssl']) except ValueError: pass def save(self): user = self.user clean_get = self.cleaned_data.get # url_is_created = False # login_is_created = False # def upgrade_svalue(key_id, value): # svalue = self._svalues_cache.get(key_id) # created = False # # if svalue is None: # svalue = self._svalues_cache[key_id] \ # = SettingValue.objects.create(key_id=key_id, user=user, value=value) # created = True # elif svalue.value != value: # svalue.value = value # svalue.save() # # return created # # def delete_svalue(key_id): # svalue = self._svalues_cache.pop(key_id, None) # # if svalue is not None: # svalue.delete() url = clean_get('url') # if url: # url_is_created = upgrade_svalue(USER_MOBILE_SYNC_SERVER_URL, url) # else: # delete_svalue(USER_MOBILE_SYNC_SERVER_URL) domain = clean_get('domain') # if domain: # upgrade_svalue(USER_MOBILE_SYNC_SERVER_DOMAIN, domain) # else: # delete_svalue(USER_MOBILE_SYNC_SERVER_DOMAIN) ssl = clean_get('ssl') # if ssl is not None: # upgrade_svalue(USER_MOBILE_SYNC_SERVER_SSL, ssl) # else: # delete_svalue(USER_MOBILE_SYNC_SERVER_SSL) login = clean_get('login') # if login: # login_is_created = upgrade_svalue(USER_MOBILE_SYNC_SERVER_LOGIN, login) # else: # delete_svalue(USER_MOBILE_SYNC_SERVER_LOGIN) # upgrade_svalue(USER_MOBILE_SYNC_ACTIVITIES, clean_get('sync_calendars')) # upgrade_svalue(USER_MOBILE_SYNC_CONTACTS, clean_get('sync_contacts')) password = clean_get('password') # if password: # upgrade_svalue(USER_MOBILE_SYNC_SERVER_PWD, Cipher.encrypt_for_db(password)) # else: # delete_svalue(USER_MOBILE_SYNC_SERVER_PWD) with self.user.settings as user_settings: # TODO: factorise if url: user_settings[user_msync_server_url_key] = url else: user_settings.pop(user_msync_server_url_key, None) if domain: user_settings[user_msync_server_domain_key] = domain else: user_settings.pop(user_msync_server_domain_key, None) if ssl is not None: user_settings[user_msync_server_ssl_key] = ssl else: user_settings.pop(user_msync_server_ssl_key, None) if login: user_settings[user_msync_server_login_key] = login else: user_settings.pop(user_msync_server_login_key, None) user_settings[user_msync_activities_key] = clean_get( 'sync_calendars') user_settings[user_msync_contacts_key] = clean_get('sync_contacts') if password: user_settings[ user_msync_server_pwd_key] = Cipher.encrypt_for_db( password) else: user_settings.pop(user_msync_server_pwd_key, None) # TODO: test # TODO: add a true button to purge (ex: we could want to purge if the url is changed, or not) # if url_is_created or login_is_created: if self._old_url != url or self._old_login != login: try: as_client = CremeClient.objects.get(user=user) except CremeClient.DoesNotExist: pass else: as_client.purge( ) # NB: If server_url or login have changed, we reset all mapping & clientdef