def __init__(self, *args, **kargs): base_area = vouchers.models.BudgetArea.get_by_path(['Accounts', 'Expenses']) self.strip_levels = base_area.depth areas = base_area.get_descendants() ModelChoiceField.__init__(self, queryset=areas, help_text='In general, this should be a fully indented budget area, not one with children', *args, **kargs)
def test_choices_not_fetched_when_not_rendering(self): """ Generating choices for ModelChoiceField should require 1 query (#12510). """ self.groups = [Group.objects.create(name=name) for name in 'abc'] # only one query is required to pull the model from DB with self.assertNumQueries(1): field = ModelChoiceField(Group.objects.order_by('-name')) self.assertEqual('a', field.clean(self.groups[0].pk).name)
def __init__(self, *args, **kargs): base_area = BudgetArea.get_by_path(settings.BASE_COMMITTEE_PATH) self.strip_levels = base_area.depth areas = (base_area.get_descendants() .filter(depth__lte=base_area.depth+settings.COMMITTEE_HIERARCHY_LEVELS) .exclude(name='Holding') ) ModelChoiceField.__init__(self, queryset=areas, help_text='Select the appropriate committe or other budget area', *args, **kargs)
class G3WUserForm(G3WRequestFormMixin, G3WFormMixin, FileFormMixin, UserCreationForm): department = ModelChoiceField(queryset=Department.objects.all(), required=False) backend = ChoiceField(choices=USER_BACKEND_TYPES) avatar = UploadedFileField(required=False) groups = ModelMultipleChoiceField( queryset=AuthGroup.objects.filter( name__in=[G3W_EDITOR1, G3W_EDITOR2, G3W_VIEWER1]), required=True, help_text=_('Select roles for this user'), label=_('Main roles')) user_groups_editor = ModelMultipleChoiceField( queryset=AuthGroup.objects.filter( ~Q(name__in=[G3W_EDITOR1, G3W_EDITOR2, G3W_VIEWER1, G3W_VIEWER2]), grouprole__role='editor'), required=False, help_text= _('Select <b>EDITOR groups</b> for this user, only Editor Level 2 can be added' ), label=_('User editor groups')) user_groups_viewer = ModelMultipleChoiceField( queryset=AuthGroup.objects.filter( ~Q(name__in=[G3W_EDITOR1, G3W_EDITOR2, G3W_VIEWER1, G3W_VIEWER2]), grouprole__role='viewer'), required=False, help_text= _('Select <b>VIEWER groups</b> for this user, only Viewer Level 1 can be added' ), label=_('User viewer groups')) def _set_editor1_queryset(self): """ Set correct guardian queryset for editor level 1 """ self.fields['user_groups_editor'].queryset = get_objects_for_user( self.request.user, 'auth.change_group', AuthGroup).order_by('name').filter(grouprole__role='editor') self.fields['user_groups_viewer'].queryset = get_objects_for_user( self.request.user, 'auth.change_group', AuthGroup).order_by('name').filter(grouprole__role='viewer') def __init__(self, *args, **kwargs): super(G3WUserForm, self).__init__(*args, **kwargs) #filter fileds by role: self.filterFieldsByRoles(**kwargs) #check for groups in intials data if 'groups' in self.initial and len(self.initial['groups']) > 0: self.initial['groups'] = self.initial['groups'] if 'user_groups' in self.initial and len( self.initial['user_groups']) > 0: self.initial['user_groups'] = self.initial['user_groups'] # change queryset for editor1 if G3W_EDITOR1 in getUserGroups(self.request.user): self._set_editor1_queryset() self.helper = FormHelper(self) self.helper.form_tag = False args = [ Div(Div(Div(Div(HTML( "<h3 class='box-title'><i class='fa fa-file'></i> {}</h3>". format(_('Anagraphic'))), css_class='box-header with-border'), Div( 'first_name', 'last_name', 'email', css_class='box-body', ), css_class='box box-success'), css_class='col-md-6'), Div(Div(Div(HTML( "<h3 class='box-title'><i class='fa fa-users'></i> {}</h3>" .format(_('ACL/Roles'))), css_class='box-header with-border'), Div(*self.__authrole_fields(), css_class='box-body'), css_class='box box-solid bg-teal-gradient'), css_class='col-md-6 {}'.format( self.checkFieldsVisible('is_superuser', 'is_staff', 'groups'))), css_class='row'), Div(Div(Div(Div(HTML( "<h3 class='box-title'><i class='fa fa-lock'></i> {}</h3>". format(_('Login data'))), css_class='box-header with-border'), Div( PrependedText('username', '<i class="fa fa-user"></i>'), PrependedText('password1', '<i class="fa fa-lock"></i>'), PrependedText('password2', '<i class="fa fa-lock"></i>'), css_class='box-body', ), css_class='box box-danger'), css_class='col-md-6'), Div(Div( Div( HTML( "<h3 class='box-title'><i class='fa fa-gear'></i> {}</h3>" .format(_('User data'))), css_class='box-header with-border'), Div( 'department', 'avatar', HTML( """{% if form.avatar.value %}<img class="img-responsive img-thumbnail" src="{{ MEDIA_URL }}{{ form.avatar.value }}">{% endif %}""", ), 'form_id', 'upload_url', 'delete_url', css_class='box-body', ), css_class='box box-default'), css_class='col-md-6'), css_class='row') ] # add backed if user id admin01 if self.request.user.is_superuser and self.request.user.is_staff: args.append( Div(Div(Div(Div(HTML( "<h3 class='box-title'><i class='fa fa-gear'></i> {}</h3>". format(_('User backend'))), css_class='box-header with-border'), Div( 'backend', css_class='box-body', ), css_class='box box-default'), css_class='col-md-6'), css_class='row')) self.helper.layout = Layout(*args) def __authrole_fields(self): """ Get fields for ACL box if they are into self.fields """ fields = [] if 'is_superuser' in self.fields: fields.append('is_superuser') if 'is_staff' in self.fields: fields.append('is_staff') if 'groups' in self.fields: fields.append( Field( 'groups', **{ 'css_class': 'select2 col-md-12', 'multiple': 'multiple', 'style': 'width:100%;' })) if 'user_groups_editor' in self.fields: fields.append( Field( 'user_groups_editor', **{ 'css_class': 'select2 col-md-12', 'multiple': 'multiple', 'style': 'width:100%;' })) if 'user_groups_viewer' in self.fields: fields.append( Field( 'user_groups_viewer', **{ 'css_class': 'select2 col-md-12', 'multiple': 'multiple', 'style': 'width:100%;' })) return fields def filterFieldsByRoles(self, **kwargs): if self.request.user.is_superuser: if not self.request.user.is_staff: self.fields.pop('is_staff') self.fields.pop('backend') elif G3W_EDITOR1 in getUserGroups(self.request.user): # other but only Editor level 1 can add user # if user is not himself if 'instance' in kwargs and kwargs['instance'] == self.request.user: self.fields.pop('groups') else: self.fields['groups'].queryset = AuthGroup.objects.filter( name__in=[G3W_EDITOR2, G3W_VIEWER1]) self.fields['groups'].required = True self.fields.pop('is_superuser') self.fields.pop('is_staff') self.fields.pop('backend') else: self.fields.pop('is_superuser') self.fields.pop('is_staff') self.fields.pop('groups') self.fields.pop('department') self.fields.pop('backend') # remove groups required is is_superuser or is_staff is set # 'on' 'off' come from icheck if 'data' in kwargs and ('is_superuser' in kwargs['data'] or 'is_staff' in kwargs['data']): if ('is_superuser' in kwargs['data'] and (kwargs['data']['is_superuser'] == 'on' or kwargs['data']['is_superuser'] is True)) or \ ('is_staff' in kwargs['data'] and (kwargs['data']['is_staff'] == 'on' or kwargs['data']['is_superuser'] is True)): self.fields['groups'].required = False def save(self, commit=True): user = super(UserCreationForm, self).save(commit=False) # if editor maps groups user add viewer maps groups group to the user saved if commit: if self.cleaned_data['password1']: user.set_password(self.cleaned_data['password1']) user.save() # for save groups if 'groups' not in self.cleaned_data: self.cleaned_data['groups'] = self.request.user.groups.all() else: if self.cleaned_data['groups']: self.cleaned_data['groups'] = self.cleaned_data['groups'] else: self.cleaned_data['groups'] = [] if 'user_groups_editor' in self.cleaned_data and self.cleaned_data[ 'user_groups_editor']: if self.cleaned_data['groups']: self.cleaned_data['groups'] |= self.cleaned_data[ 'user_groups_editor'] else: self.cleaned_data['groups'] = self.cleaned_data[ 'user_groups_editor'] if 'user_groups_viewer' in self.cleaned_data and self.cleaned_data[ 'user_groups_viewer']: if self.cleaned_data['groups']: self.cleaned_data['groups'] |= self.cleaned_data[ 'user_groups_viewer'] else: self.cleaned_data['groups'] = self.cleaned_data[ 'user_groups_viewer'] # if is_superuser or is_staff are set, remove groups if ('is_superuser' in self.cleaned_data or 'is_staff' in self.cleaned_data) and \ (('is_superuser' in self.cleaned_data and self.cleaned_data['is_superuser']) or ('is_staff' in self.cleaned_data and self.cleaned_data['is_staff'])): self.cleaned_data['groups'] = [] self.cleaned_data['user_groups_editor'] = [] self.cleaned_data['user_groups_viewer'] = [] self.save_m2m() if hasattr(user, 'userdata'): if 'department' in self.cleaned_data: user.userdata.department = self.cleaned_data['department'] if self.cleaned_data['avatar']: user.userdata.avatar = self.cleaned_data['avatar'] else: user.userdata.avatar = None user.userdata.save() else: Userdata(user=user, department=self.cleaned_data['department'], avatar=self.cleaned_data['avatar']).save() # add backend if 'backend' in self.cleaned_data: if hasattr(user, 'userbackend'): user.userbackend.backend = self.cleaned_data['backend'] user.userbackend.save() else: Userbackend(user=user, backend=self.cleaned_data['backend']).save() elif not hasattr(user, 'userbackend'): Userbackend(user=user, backend=USER_BACKEND_DEFAULT).save() # add add_group permissions to editor1 add_group = Permission.objects.get( codename='add_group', content_type=ContentType.objects.get_for_model(AuthGroup)) if userHasGroups(user, [G3W_EDITOR1]): user.user_permissions.add(add_group) else: user.user_permissions.remove(add_group) return user def clean_groups(self): """ Check for roles(groups) user can't be editor level 1 and 2 at same time. :return: cleaned_data modified """ groups = self.cleaned_data['groups'] if len( set(groups).intersection( set( AuthGroup.objects.filter( name__in=[G3W_EDITOR1, G3W_EDITOR2])))) == 2: raise ValidationError(_( 'User can\'t be Editor level 1 and at same time Editor level 2' ), code='groups_invalid') return groups def clean_user_groups_editor(self): """ Check only Editor level 2 users can belong to user groups editor. :return: cleaned_data """ user_groups_editor = self.cleaned_data['user_groups_editor'] if user_groups_editor and 'groups' in self.cleaned_data and len( set(self.cleaned_data['groups']).intersection( set(AuthGroup.objects.filter( name__in=[G3W_EDITOR2])))) == 0: raise ValidationError(_( 'User can\'t belong a **editor groups** if he isn\'t a Editor level 2' ), code='user_groups_editor_invalid') return user_groups_editor def clean_user_groups_viewer(self): """ Check only Viewer level 1 users can belong to user groups editor. :return: cleaned_data """ user_groups_viewer = self.cleaned_data['user_groups_viewer'] if user_groups_viewer and 'groups' in self.cleaned_data and len( set(self.cleaned_data['groups']).intersection( set(AuthGroup.objects.filter( name__in=[G3W_VIEWER1])))) == 0: raise ValidationError(_( 'User can\'t belong a **viewer groups** if he isn\'t a Viewer level 1' ), code='user_groups_editor_invalid') return user_groups_viewer def clean_avatar(self): """ Check if upalod file is a valid image by pillow :return: File object Cleaned data """ avatar = self.cleaned_data['avatar'] if avatar is None: return avatar try: image = Image.open(avatar) image.verify() except Exception: raise ValidationError(_('Avatar is no a valid image'), code='image_invalid') return avatar class Meta(UserCreationForm.Meta): fields = ('first_name', 'last_name', 'email', 'username', 'password1', 'password2', 'is_superuser', 'is_staff', 'groups', 'department', 'avatar', 'user_groups_editor', 'user_groups_viewer') widgets = { #'groups': G3WM2MSingleSelect }
def test_choices_not_fetched_when_not_rendering(self): # only one query is required to pull the model from DB with self.assertNumQueries(1): field = ModelChoiceField(Group.objects.order_by('-name')) self.assertEqual('a', field.clean(self.groups[0].pk).name)
def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == 'category': return ModelChoiceField( Category.objects.filter(slug='smartphones')) return super().formfield_for_foreignkey(db_field, request, **kwargs)
def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) # pop the 'user' from kwargs dictionary super(VmDefinitionForm, self).__init__(*args, **kwargs) self.fields['image'] = ModelChoiceField(queryset=user.images.all())
class NewImportApplicationForm(ModelEditForm): application_type = ModelChoiceField( queryset=ImportApplicationType.objects.filter(is_active=True), help_text='Imports of textiles and clothing or iron and steel of value \ less than £120 do not need and import license. \ This does NOT apply to firearms or sanctions derogations.') importer = ModelChoiceField( queryset=Importer.objects.none(), help_text='For Derogations from Sanctions applications, \ you must be a main importer, \ and will not be able to select and agent importer.', ) importer_office = ModelChoiceField( queryset=Office.objects.none(), help_text='The office that this licence will be issued to.') def _get_agent_importer_ids(self, user): """ Get ids for main importers of given agents""" agents = Importer.objects \ .filter(is_active=True) \ .filter(members=user) \ .filter(main_importer__isnull=False) ids = [] for agent in agents: ids.append(agent.main_importer_id) return ids def _update_agents(self, user, application_type, importer): if application_type.type == 'Derogation from Sanctions Import Ban': return # User is a member of main importer's team, no agent. if user in importer.members.all(): return agents = importer.agents.filter(is_active=True).filter(members=user) field = ModelChoiceField(queryset=agents) # Add field configuration to agent as it is a dynamic field # and configuration won't be applied as the other fields. field.config = self.fields['importer'].config self.fields['agent'] = field self.Meta.fields.append('agent') def _update_offices(self, importer): if importer in self.fields['importer'].queryset: self.fields['importer_office'].queryset = importer.offices.filter( is_active=True) def _update_importers(self, request, application_type): importers = Importer.objects.filter(is_active=True) main_importers = Q(members=request.user, main_importer__isnull=True) agent_importers = Q(pk__in=self._get_agent_importer_ids(request.user)) if application_type.type == 'Derogation from Sanctions Import Ban': importers = importers.filter(main_importers) else: importers = importers.filter(main_importers | agent_importers) self.fields['importer'].queryset = importers def _update_form(self, request): type_pk = self.data.get('application_type', None) if type_pk: type = ImportApplicationType.objects.get(pk=type_pk) self._update_importers(request, type) importer_pk = self.data.get('importer', None) if importer_pk: importer = Importer.objects.get(pk=importer_pk) self._update_offices(importer) self._update_agents(request.user, type, importer) def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) self._update_form(request) class Meta: model = ImportApplication fields = ['application_type', 'importer', 'importer_office'] config = {'__all__': {'show_optional_indicator': False}}
class UserForm(forms.ModelForm): """ User form """ perspective = ModelChoiceField(label='Perspective', queryset=[], required=False) def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) if 'instance' in kwargs: self.instance = kwargs['instance'] else: self.fields['password'] = forms.CharField( max_length=255, label=_("Password"), widget=forms.PasswordInput(render_value=False)) self.fields['password_again'] = forms.CharField( max_length=255, label=_("Confirm Password"), widget=forms.PasswordInput(render_value=False)) self.fields['name'].label = _("Username") self.fields['name'].help_text = _("Used to log in") self.fields['default_group'].label = _("Default group") self.fields['other_groups'].label = _("Other groups") self.fields['other_groups'].help_text = "" self.fields['perspective'].label = _("Perspective") self.fields['perspective'].queryset = Perspective.objects.all() if self.instance: try: self.fields[ 'perspective'].initial = self.instance.get_perspective() except: pass def clean_name(self): "Clean Name" data = self.cleaned_data['name'] query = Q(name=data) if self.instance and self.instance.id: query = query & ~Q(id=self.instance.id) existing = User.objects.filter(query) if existing: raise forms.ValidationError( _("User with username %s already exists.") % data) if self.instance and not self.instance.id: # Check Anaf Subscription user limit user_limit = settings.ANAF_SUBSCRIPTION_USER_LIMIT if user_limit > 0: user_number = User.objects.filter(disabled=False).count() if user_number >= user_limit: raise forms.ValidationError( _("Sorry, but your subscription does not allow more than %d users. You're currently at your limit." ) % (user_limit)) return data def clean_password_again(self): "Clean password again" password1 = self.cleaned_data['password'] password2 = self.cleaned_data['password_again'] if not password1 == password2: raise forms.ValidationError(_("Passwords do not match")) return password2 def clean_disabled(self): "Ensure the admin does not go over subscription limit by re-enabling users" enable = not self.cleaned_data['disabled'] if self.instance and self.instance.id and enable and self.instance.disabled: user_limit = settings.ANAF_SUBSCRIPTION_USER_LIMIT if user_limit > 0: user_number = User.objects.filter(disabled=False).count() if user_number >= user_limit: raise forms.ValidationError( _("Sorry, but your subscription does not allow more than %d users. You're currently at your limit." ) % (user_limit)) return self.cleaned_data['disabled'] def save(self, *args, **kwargs): "Form processor" if self.instance.id: self.instance.user.username = self.instance.name self.instance.user.save() super(UserForm, self).save(*args, **kwargs) else: new_user = django_auth.User(username=self.cleaned_data['name'], password='') new_user.set_password(self.cleaned_data['password']) models.signals.post_save.disconnect(user_autocreate_handler, sender=django_auth.User) new_user.save() if settings.ANAF_SIGNALS_AUTOCREATE_USER: models.signals.post_save.connect(user_autocreate_handler, sender=django_auth.User) self.instance.user = new_user super(UserForm, self).save(*args, **kwargs) if self.cleaned_data['perspective']: self.instance.set_perspective(self.cleaned_data['perspective']) return self.instance class Meta: "User Form" model = User fields = ('name', 'default_group', 'other_groups', 'disabled')
class PollVoteForm(ModelForm): first = ModelChoiceField( None, widget=CustomSelect, label='Primera opción', ) second = ModelChoiceField( None, required=False, widget=CustomSelect, label='Segunda opción (opcional)', ) third = ModelChoiceField( None, required=False, widget=CustomSelect, label='Tercera opción (opcional)', ) def __init__(self, *args, designs: 'QuerySet[PollDesign]', **kwargs) -> None: super().__init__(*args, **kwargs) # Save the choices now to avoid the field implementation to make # additional queries choices: list[tuple['int | str', str]] = [(obj.id, obj.title) for obj in designs] blank: list[tuple['int | str', str]] = [('', '---')] self.fields['first'].queryset = designs self.fields['first'].choices = choices self.fields['second'].queryset = designs self.fields['second'].choices = blank + choices self.fields['third'].queryset = designs self.fields['third'].choices = blank + choices class Meta: model = PollVote fields = ('first', 'second', 'third') def clean(self) -> dict[str, Any]: data = super().clean() if data['third'] and not data['second']: data['third'], data['second'] = data['second'], data['third'] if data['first'] == data['second']: raise ValidationError({ 'second': 'No puede ser el mismo que la primera opción', }) if data['third']: if data['first'] == data['third']: raise ValidationError({ 'third': 'No puede ser el mismo que la primera opción', }) if data['second'] == data['third']: raise ValidationError({ 'third': 'No puede ser el mismo que la segunda opción', }) return data
class ItemForm(ModelForm): class Meta: model = Item fields = ( "name", "description", "category", "dimensions", "condition", "provenance", "notes", "ref", "cost_price", "restoration_cost", "sale_price", "minimum_price", "archive", "state", "location", "visible", "show_price", "featured", "done", "book", "rank", ) widgets = { "description": forms.Textarea(attrs={"rows": 6}), "provenance": forms.Textarea(attrs={"rows": 2}), "notes": forms.Textarea(attrs={"rows": 2}), } category = ModelChoiceField(queryset=Category.objects.filter(numchild=0)) total_cost = forms.DecimalField( max_digits=8, decimal_places=2, required=False, widget=forms.Textarea(attrs={"readonly": 1}), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["cost_price"].widget.attrs["readonly"] = "readonly" def clean_rank(self): rank = self.cleaned_data["rank"] if rank < 1 or rank > 10: raise forms.ValidationError("Rank must be between 1 and 10") return self.cleaned_data["rank"] def clean(self): # remove input mask from currency fields and set cleaned data to decimal value if not self.cleaned_data["archive"]: for field in [ "cost_price", "restoration_cost", "total_cost", "sale_price", "minimum_price", ]: raw = self.data[field].replace("£ ", "").replace(",", "") if not raw: raw = 0 self.cleaned_data[field] = Decimal(raw) try: del self.errors[field] except KeyError: pass return self.cleaned_data
def __init__(self, *args, **kwargs): super(HoDanForm, self).__init__(*args, **kwargs) self.fields["tinh"] = ModelChoiceField( queryset=Tinh.objects.order_by("name"), widget=ModelSelect2Widget( model=Tinh, search_fields=['name__unaccent__icontains'], attrs={ 'style': 'min-width:250px', 'data-minimum-input-length': 0 }), required=False) self.fields["huyen"] = ModelChoiceField( queryset=Huyen.objects.order_by("name"), widget=ModelSelect2Widget( model=Huyen, search_fields=['name__unaccent__icontains'], dependent_fields={'tinh': 'tinh'}, attrs={ 'style': 'min-width:250px', 'data-minimum-input-length': 0 }), required=False) self.fields["xa"] = ModelChoiceField( queryset=Xa.objects.order_by("name"), widget=ModelSelect2Widget( model=Xa, search_fields=['name__unaccent__icontains'], dependent_fields={'huyen': 'huyen'}, attrs={ 'style': 'min-width:250px', 'data-minimum-input-length': 0 }), required=False) self.fields['volunteer'] = ModelChoiceField( queryset=TinhNguyenVien.objects.all(), widget=Select2(), required=False) self.fields['cuuho'] = ModelChoiceField(queryset=CuuHo.objects.all(), widget=Select2(), required=False) self.fields[ 'volunteer'].label_from_instance = self.label_from_volunteer self.fields['volunteer'].label = 'Tình nguyện viên' self.fields['cuuho'].label_from_instance = self.label_from_cuuho self.fields['cuuho'].label = 'Đội cứu hộ' self.fields["tinh"].label = "Tỉnh" self.fields["tinh"].help_text = "Nhấn vào để chọn tỉnh" self.fields["huyen"].label = "Huyện" self.fields["huyen"].help_text = "Bạn phải chọn tỉnh trước" self.fields["xa"].label = "Xã" self.fields["xa"].help_text = "Bạn phải chọn tỉnh, và huyện trước" self.fields['geo_location'] = LocationField( required=False, map_attrs={ "style": "mapbox://styles/mapbox/outdoors-v11", "zoom": 10, "center": [106.507467036133, 17.572843459110928], "cursor_style": 'pointer', "marker_color": "red", "rotate": False, "geocoder": True, "fullscreen_button": True, "navigation_buttons": True, "track_location_button": True, "readonly": True, "placeholder": "Chọn một địa điểm trên bản đồ", })
class UserForm(ModelForm): # profile address = CharField(label=_('Address'), max_length=255) address_detail = CharField(label=_('Address detail'), max_length=255, required=False) postal_code = CharField(label=_('Postal code'), max_length=255) city = CharField(label=_('City'), max_length=255) country = CharField(label=_('Country'), max_length=255) telephone = CharField(label=_('Telephone'), max_length=255) birthday = DateField(label=_('Birthday'), help_text="Au format jj/mm/aaaa") # student portrait = ImageField( widget=FileInput(attrs={'accept': "image/*;capture=camera"}), required=True, help_text="Veuillez utiliser une photo au format d'identité.") level = ChoiceField(label=_('Studying level'), choices=LEVEL_CHOICES) iej = ModelChoiceField(label='IEJ', queryset=IEJ.objects.all()) platform_only = forms.ChoiceField(choices=TRUE_FALSE_CHOICES, label='E-learning uniquement', widget=forms.Select()) period = ModelChoiceField( label='Période', queryset=Period.objects.filter( is_open=True, date_inscription_start__lte=datetime.datetime.now(), date_inscription_end__gte=datetime.datetime.now())) training = ModelChoiceField( label='Formation', queryset=Training.objects.filter(available=True)) procedure = ModelChoiceField( label=_('Procedure'), help_text="Matière de procédure", queryset=Course.objects.filter(procedure=True)) written_speciality = ModelChoiceField( label='Specialité écrite', queryset=Course.objects.filter(written_speciality=True), help_text="Matière juridique de spécialité") oral_1 = ModelChoiceField( label='Souscription à l\'oral de langue (option)', help_text="Matière d’oral de langue (en option)", queryset=Course.objects.filter(oral_1=True)) promo_code = CharField(label=_('Code promo'), max_length=100, required=False) payment_schedule = ChoiceField(label=_(u'Échéancier de paiement'), choices=payment_schedule_choices, required=True) fascicule = forms.ChoiceField(choices=TRUE_FALSE_CHOICES, label='Envoi postal des fascicules', required=False, widget=forms.Select()) # no model captcha = ReCaptchaField() accept = BooleanField() class Meta: model = User fields = ['first_name', 'last_name', 'email'] def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) self.fields['first_name'].required = True self.fields['last_name'].required = True self.fields['email'].required = True self.user_fields = [ 'first_name', 'last_name', 'email', 'address', 'address_detail', 'postal_code', 'city', 'country', 'telephone', 'birthday', 'portrait' ] self.training_fields = [ 'level', 'iej', 'platform_only', 'fascicule', 'period', 'training', 'procedure', 'written_speciality', 'oral_1' ] def clean_portrait(self): image = self.cleaned_data['portrait'] if not image: return image #width, height = get_image_dimensions(image) #ratio = float(height) / float(width) # if ratio > 2.5 or ratio < 1: # raise ValidationError({'portrait': "L'image n'est pas au format portrait."}) NEW_HEIGHT = 230 NEW_WIDTH = 180 # if width < NEW_WIDTH or height < NEW_HEIGHT: # raise ValidationError({'portrait': "L'image est trop petite. Elle doit faire au moins %spx de large et %spx de hauteur." % (NEW_WIDTH, NEW_HEIGHT)}) # resize image img = Image.open(image.file) new_image = img.resize((NEW_WIDTH, NEW_HEIGHT), Image.ANTIALIAS) if new_image.mode == "RGBA": new_image = new_image.convert("RGB") temp = BytesIO() new_image.save(temp, 'jpeg') temp.seek(0) return SimpleUploadedFile('temp', temp.read()) def save(self, commit=True): data = self.cleaned_data user = super(UserForm, self).save(commit=False) username = get_unique_username(data['first_name'], data['last_name']) self.username = username user.username = username user.last_name = data['last_name'].upper() user.first_name = data['first_name'].capitalize() user.is_active = False if commit: user.save() profile = UserProfile(user=user, address=data['address'], address_detail=data.get('address_detail'), postal_code=data['postal_code'], city=data['city'], country=data['country'], telephone=data['telephone'], birthday=data['birthday']) if commit: profile.save() platform_only = data.get('platform_only') == 'True' and True or False fascicule = data.get('fascicule') == 'True' and True or False training = data.get('training') subscription_fees = 0 if platform_only: if fascicule: subscription_fees = training.cost_elearning_fascicle else: subscription_fees = training.cost_elearning_nofascicle else: subscription_fees = training.cost student = Student(user=user, portrait=data['portrait'], level=data.get('level'), iej=data.get('iej'), period=data.get('period'), platform_only=platform_only, procedure=data.get('procedure'), written_speciality=data.get('written_speciality'), oral_1=data.get('oral_1'), promo_code=data.get('promo_code'), training=training, payment_schedule=data.get('payment_schedule'), fascicule=fascicule, subscription_fees=subscription_fees) student.save() student.trainings.add(data.get('training', None)) return user
class GearFinderForm(forms.Form): gear_set = ModelChoiceField(GearSet.objects.all(), required=True, initial=-1) target = FloatField(label="Required Ratio") tolerance = FloatField(initial=0.00009)
class CorrectorForm(ModelForm): # profile address = CharField(label=_('Address'), max_length=255) address_detail = CharField(label=_('Address detail'), max_length=255, required=False) postal_code = CharField(label=_('Postal code'), max_length=255) city = CharField(label=_('City'), max_length=255) country = CharField(label=_('Country'), max_length=255) telephone = CharField(label=_('Telephone'), max_length=255) birthday = DateField(label=_('Birthday'), help_text="Au format jj/mm/aaaa") birthday_place = CharField(label='Lieu de naissance', max_length=255) nationality = CharField(label='Nationalité', max_length=255) ss_number = CharField(label='N° de sécurité sociale', max_length=15) siret = CharField(label='N° SIRET', max_length=13, required=False) # corrector period = ModelChoiceField( label='Période', queryset=Period.objects.filter( is_open=True, date_inscription_start__lte=datetime.datetime.now(), date_inscription_end__gte=datetime.datetime.now())) pay_status = forms.ChoiceField(choices=PAY_STATUS_CHOICES, label='Statut', widget=forms.Select()) courses = ModelMultipleChoiceField(label='Matière', queryset=Course.objects.all().exclude( title="Aucune").order_by('title'), widget=forms.CheckboxSelectMultiple()) # no model captcha = ReCaptchaField() # accept = BooleanField() class Meta: model = User fields = ['first_name', 'last_name', 'email'] def __init__(self, *args, **kwargs): super(CorrectorForm, self).__init__(*args, **kwargs) self.fields['first_name'].required = True self.fields['last_name'].required = True self.fields['email'].required = True self.user_fields = [ 'first_name', 'last_name', 'email', 'address', 'address_detail', 'postal_code', 'city', 'country', 'telephone', 'birthday', 'birthday_place', 'nationality', 'ss_number', 'siret' ] self.training_fields = ['courses', 'period', 'pay_status'] def clean_siret(self): if self.data['pay_status'] == 'honoraires' and not self.cleaned_data[ 'siret'].strip(): raise ValidationError( "Le SIRET est obligatoire si vous choississez le statut honoraires" ) return self.data['siret'] def save(self, commit=True): data = self.cleaned_data user = super(CorrectorForm, self).save(commit=False) username = get_unique_username(data['first_name'], data['last_name']) self.username = username user.username = username user.last_name = data['last_name'].upper() user.first_name = data['first_name'].capitalize() user.is_active = False if commit: user.save() profile = UserProfile(user=user, address=data['address'], address_detail=data.get('address_detail'), postal_code=data['postal_code'], city=data['city'], country=data['country'], telephone=data['telephone'], birthday=data['birthday'], birthday_place=data['birthday_place'], ss_number=data['ss_number'], siret=data['siret'], nationality=data['nationality']) if commit: profile.save() corrector = Corrector( user=user, period=data.get('period'), pay_status=data.get('pay_status'), ) corrector.save() corrector.courses.set(data.get('courses')) return user
def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super(FindingAidsArchivalUnitForm, self).__init__(*args, **kwargs) qs = user.user_profile.allowed_archival_units.all().order_by( 'fonds', 'subfonds', 'series') qs_subfonds = ArchivalUnit.objects.filter(children__in=qs, level='SF').order_by( 'fonds', 'subfonds', 'series') qs_fonds = ArchivalUnit.objects.filter(children__in=qs_subfonds, level='F').order_by( 'fonds', 'subfonds', 'series') # If User is restricted to a particular series if len(qs) > 0: self.fields['fonds'] = ModelChoiceField( queryset=ArchivalUnit.objects.all(), widget=ModelSelect2Widget( queryset=qs_fonds, search_fields=[ 'title__icontains', 'reference_code__icontains' ], )) self.fields['subfonds'] = ModelChoiceField( queryset=ArchivalUnit.objects.all(), widget=ModelSelect2Widget(queryset=qs_subfonds, search_fields=[ 'title__icontains', 'reference_code__icontains' ], dependent_fields={'fonds': 'parent'})) self.fields['series'] = ModelChoiceField( queryset=ArchivalUnit.objects.all(), widget=ModelSelect2Widget( queryset=qs, search_fields=[ 'title__icontains', 'reference_code__icontains' ], dependent_fields={'subfonds': 'parent'})) else: self.fields['fonds'] = ModelChoiceField( queryset=ArchivalUnit.objects.all(), label='Fonds', widget=ModelSelect2Widget( queryset=ArchivalUnit.objects.filter(level='F').order_by( 'fonds', 'subfonds', 'series'), search_fields=[ 'title__icontains', 'reference_code__icontains' ], )) self.fields['subfonds'] = ModelChoiceField( queryset=ArchivalUnit.objects.all(), widget=ModelSelect2Widget(queryset=ArchivalUnit.objects.filter( level='SF').order_by('fonds', 'subfonds', 'series'), search_fields=[ 'title__icontains', 'reference_code__icontains' ], dependent_fields={'fonds': 'parent'})) self.fields['series'] = ModelChoiceField( queryset=ArchivalUnit.objects.all(), widget=ArchivalUnitSeriesContainersSelect2Widget( queryset=ArchivalUnit.objects.filter(level='S').order_by( 'fonds', 'subfonds', 'series'), search_fields=[ 'title__icontains', 'reference_code__icontains' ], dependent_fields={'subfonds': 'parent'}))
def test(): field = ModelChoiceField(Group.objects.order_by('-name')) self.assertEqual('a', field.clean(self.groups[0].pk).name)
def __init__(self, base_area, *args, **kargs): self.strip_levels = base_area.depth areas = base_area.get_descendants() ModelChoiceField.__init__(self, queryset=areas, help_text='In general, this should be a fully indented budget area, not one with children', *args, **kargs)
def test_choices_not_fetched_when_not_rendering(self): initial_queries = len(connection.queries) field = ModelChoiceField(Group.objects.order_by('-name')) self.assertEqual('a', field.clean(self.groups[0].pk).name) # only one query is required to pull the model from DB self.assertEqual(initial_queries+1, len(connection.queries))
class SithChoiceForm(forms.Form): """Форма для Ситха""" sith = ModelChoiceField(Sith.objects.all())
class OutcomeForm(ModelForm): semester = ChoiceField(choices=Outcome.SEMESTER_CHOICES, widget = Select(attrs={ 'id': 'outcome_semester', 'class': 'form-control custom-select select-fix-height', 'name': 'semester', }), required=False, ) year = ChoiceField(choices=YEAR_CHOICES, widget = Select(attrs={ 'id': 'outcome_year', 'class': 'form-control custom-select select-fix-height', 'name': 'year', }), required=False, ) section = ChoiceField( widget = Select(attrs={ 'id': 'outcome_course_section', 'class': 'form-control custom-select select-fix-height', 'name': 'section', }), required=False, ) course = ModelChoiceField(queryset=None, widget = Select(attrs={ 'id': 'outcome_course', 'class': 'form-control select-fix-height', 'name': 'course', }), required=False, empty_label="Select a course" ) class Meta: model = Outcome fields = ( 'course', 'section', 'description', 'semester', 'year', 'is_public', 'title', ) def __init__(self, *args, **kwargs): user = kwargs.pop('user') super(OutcomeForm, self).__init__(*args, **kwargs) if user.is_superuser: self.fields['course'].queryset = Course.objects.extra( select={'course_number': "CAST(substring(number FROM '^[0-9]+') AS INTEGER)"} ).order_by('subject','course_number') else: self.fields['course'].queryset = user.staffprofile.courses.all() self.fields['title'].widget = TextInput(attrs={ 'id': 'outcome_title', 'class': 'form-control', 'name': 'title', 'maxlength': '99', }) self.fields['description'].widget = Textarea(attrs={ 'id': 'outcome_description', 'class': 'form-control', 'name': 'description', 'maxlength': '2000', }) section_choices = [] course_id = None if 'course' in self.initial: course_id = self.initial.get('course') elif 'course' in self.data and self.data['course']: course_id = self.data.get('course') elif self.instance.pk and self.instance.course: course_id = self.instance.course.pk if course_id != None: course = Course.objects.get(pk=course_id) section_choices += BLANK_CHOICE_DASH for section in course.sections: section_choices.append((section, "{:02d}".format(section))) self.fields['section'].choices = section_choices else: self.fields['section'].disabled = True def clean_year(self): year = self.cleaned_data.get('year') if year: return year return None def clean_section(self): section = self.cleaned_data.get('section') if section: return section return None
class HoDanForm(ModelForm): class Meta: model = HoDan fields = "__all__" exclude = ('thon', ), labels = { "name": "Tiêu đề", "phone": "Số điện thoại", } widgets = { 'note': Textarea( attrs={ 'placeholder': 'Ví dụ:\n17:00 23/10: Có người lớn bị cảm cúm.\n20:39 23/10: Đã gọi xác minh bệnh.\n' }), 'name': TextInput(attrs={'size': 50}), 'phone': TextInput(attrs={'size': 50}) } def __init__(self, *args, **kwargs): super(HoDanForm, self).__init__(*args, **kwargs) self.fields["tinh"] = ModelChoiceField( queryset=Tinh.objects.order_by("name"), widget=ModelSelect2Widget( model=Tinh, search_fields=['name__unaccent__icontains'], attrs={ 'style': 'min-width:250px', 'data-minimum-input-length': 0 }), required=False) self.fields["huyen"] = ModelChoiceField( queryset=Huyen.objects.order_by("name"), widget=ModelSelect2Widget( model=Huyen, search_fields=['name__unaccent__icontains'], dependent_fields={'tinh': 'tinh'}, attrs={ 'style': 'min-width:250px', 'data-minimum-input-length': 0 }), required=False) self.fields["xa"] = ModelChoiceField( queryset=Xa.objects.order_by("name"), widget=ModelSelect2Widget( model=Xa, search_fields=['name__unaccent__icontains'], dependent_fields={'huyen': 'huyen'}, attrs={ 'style': 'min-width:250px', 'data-minimum-input-length': 0 }), required=False) self.fields['volunteer'] = ModelChoiceField( queryset=TinhNguyenVien.objects.all(), widget=Select2(), required=False) self.fields['cuuho'] = ModelChoiceField(queryset=CuuHo.objects.all(), widget=Select2(), required=False) self.fields[ 'volunteer'].label_from_instance = self.label_from_volunteer self.fields['volunteer'].label = 'Tình nguyện viên' self.fields['cuuho'].label_from_instance = self.label_from_cuuho self.fields['cuuho'].label = 'Đội cứu hộ' self.fields["tinh"].label = "Tỉnh" self.fields["tinh"].help_text = "Nhấn vào để chọn tỉnh" self.fields["huyen"].label = "Huyện" self.fields["huyen"].help_text = "Bạn phải chọn tỉnh trước" self.fields["xa"].label = "Xã" self.fields["xa"].help_text = "Bạn phải chọn tỉnh, và huyện trước" self.fields['geo_location'] = LocationField( required=False, map_attrs={ "style": "mapbox://styles/mapbox/outdoors-v11", "zoom": 10, "center": [106.507467036133, 17.572843459110928], "cursor_style": 'pointer', "marker_color": "red", "rotate": False, "geocoder": True, "fullscreen_button": True, "navigation_buttons": True, "track_location_button": True, "readonly": True, "placeholder": "Chọn một địa điểm trên bản đồ", }) @staticmethod def label_from_volunteer(obj): status = _display_choices(TINHNGUYEN_STATUS, obj.status) return f"{obj.name} | {obj.phone} | {status}" @staticmethod def label_from_cuuho(obj): status = _display_choices(CUUHO_STATUS, obj.status) return f"{obj.name} | {obj.phone} | {status}" volunteer = ModelChoiceField(queryset=TinhNguyenVien.objects.all(), widget=Select2(), required=False, help_text="Tên | Số điện thoại | Trạng thái") cuuho = ModelChoiceField(queryset=CuuHo.objects.all(), widget=Select2(), required=False, help_text="Tên | Số điện thoại | Trạng thái") geo_location = LocationField(required=False, map_attrs={ "style": "mapbox://styles/mapbox/outdoors-v11", "zoom": 10, "center": [106.507467036133, 17.572843459110928], "cursor_style": 'pointer', "marker_color": "red", "rotate": False, "geocoder": True, "fullscreen_button": True, "navigation_buttons": True, "track_location_button": True, "readonly": True, "placeholder": "Chọn một địa điểm", })
class BylawForm(ModelForm): raspr_date = DateField(required=False, widget=DateInput(attrs={'type': "text", 'class': "form-control col-6", 'id': "raspr_date"})) district = ModelChoiceField(required=False, queryset=DistrictsMenu.objects.all(), to_field_name="district", widget=Select(attrs={'id': "district", 'class': 'form-control col-6'})) department = ModelChoiceField(required=False, queryset=DepartmentsMenu.objects.all(), to_field_name="department", widget=Select(attrs={'id':"department", 'class': "form-control col-6"})) organization = CharField(required=False, widget=TextInput( attrs={'type': "text", 'class': "form-control col-6 org", 'id': "organization"})) inn = CharField(required=True, widget=TextInput( attrs={'type': "text", 'class': "form-control col-6", 'id': "inn"})) performer = ModelChoiceField(required=False, queryset=PerformersMenu.objects.all(), to_field_name="performer", widget=Select(attrs={'id': "performer", 'class': 'form-control col-6'})) check_type = ModelChoiceField(required=False, queryset=CheckTypesMenu.objects.all(), to_field_name="check_type", widget=Select(attrs={'id': "check_type", 'class': 'form-control col-6'})) date_proved_c = DateField(required=False, widget=DateInput(attrs={'type': "text", 'class': "form-control col-6", 'id': "date_proved_c"})) date_proved_po = DateField(required=False, widget=DateInput(attrs={'type': "text", 'class': "form-control col-6", 'id': "date_proved_po"})) base = ModelChoiceField(required=False, queryset=BaseMenu.objects.all(), to_field_name="base", widget=Select(attrs={'id': "base", 'class': 'form-control col-6'})) lab_security = ModelChoiceField(required=False, queryset=LabSecurityMenu.objects.all(), to_field_name="lab_security", widget=Select(attrs={'id': "lab_security", 'class': 'form-control col-6'})) class Meta: model = BylawModel fields = ['raspr_date', 'district', 'department', 'organization', 'inn', 'performer', 'check_type', 'date_proved_c', 'date_proved_po', 'base', 'lab_security', 'raspr_num', 'who_created' ] widgets = { # 'raspr_date': DateInput( # attrs={'type': "text", 'class': "form-control col-6", 'id':"raspr_date", 'required':"false"} # ), # 'organization': TextInput( # attrs={'type': "text", 'class': "form-control col-6 org", 'id': "organization", 'required':"false"} # ), # 'inn': TextInput( # attrs={'type': "text", 'required':"gfggfgfgfg", 'class': "form-control col-6", 'id': "inn"} # ), # 'date_proved': DateInput( # attrs={'type': "text", 'class': "form-control col-6", 'id': "date_proved", 'required':"false"} # ), 'raspr_num': TextInput( attrs={'type': "text", 'class': "form-control col-10", 'id': "raspr_num", 'readonly': ''} ), 'who_created': TextInput( attrs={'type': "text", 'class': "form-control col-10", 'id': "who_created", 'readonly': ''} ) }
class WorkupForm(ModelForm): temperature_units = fields.ChoiceField(label='', widget=RadioSelect, choices=[( 'C', 'C', ), ('F', 'F')], initial='C', required=False) weight_units = fields.ChoiceField(label='', widget=RadioSelect, choices=[('kg', 'kg'), ('lbs', 'lbs')], required=False) height_units = fields.ChoiceField(label='', widget=RadioSelect, choices=[('cm', 'cm'), ('in', 'in')], required=False) class Meta(object): model = models.Workup exclude = [ 'patient', 'author', 'signer', 'author_type', 'signed_date', 'referral_location', 'referral_type' ] # limit the options for the attending, other_volunteer field by # checking the signs charts permission. can_sign_perm_codename = 'sign_Workup' attending = ModelChoiceField( required=False, queryset=get_user_model().objects.filter( groups__in=Group.objects.filter( permissions__codename=can_sign_perm_codename)).distinct()) other_volunteer = ModelMultipleChoiceField( required=False, queryset=get_user_model().objects.all()) def __init__(self, *args, **kwargs): super(WorkupForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( Row(HTML('<h3>Clinical Team</h3>'), Div('attending', css_class='col-sm-6'), Div('other_volunteer', css_class='col-sm-6'), Div('clinic_day', css_class='col-sm-12')), Row( HTML('<h3>History</h3>'), Div('chief_complaint', css_class='col-sm-6'), Div('diagnosis', css_class='col-sm-6'), Div(InlineCheckboxes('diagnosis_categories'), css_class='col-sm-12'), Div('hpi', css_class='col-xs-12'), Div('pmh', css_class='col-md-6'), Div('psh', css_class='col-md-6'), Div('fam_hx', css_class='col-md-6'), Div('soc_hx', css_class='col-md-6'), Div('meds', css_class='col-md-6'), Div('allergies', css_class='col-md-6'), Div('ros', css_class='col-xs-12')), Row( HTML('<h3>Physical Exam</h3>'), HTML('<h4>Vital Signs</h4>'), Div(AppendedText('bp_sys', 'mmHg'), css_class='col-md-3 col-sm-3 col-xs-6'), Div(AppendedText('bp_dia', 'mmHg'), css_class='col-md-3 col-sm-3 col-xs-6'), Div(AppendedText('hr', 'bpm'), css_class='col-md-3 col-sm-3 col-xs-6'), Div(AppendedText('rr', '/min'), css_class='col-md-3 col-sm-3 col-xs-6')), Row( Div(AppendedRadios('t', 'temperature_units'), css_class='col-md-3 col-sm-3 col-xs-6'), Div(AppendedRadios('weight', 'weight_units'), css_class='col-md-3 col-sm-4 col-xs-6'), Div(AppendedRadios('height', 'height_units'), css_class='col-md-3 col-sm-4 col-xs-6'), Div('pe', css_class='col-xs-12')), Row( HTML('<h3>Assessment, Plan, & Orders</h3>'), Div('a_and_p', css_class='col-xs-12'), Div('rx', css_class='col-md-4'), Div('labs_ordered_internal', css_class='col-md-4'), Div('labs_ordered_external', css_class='col-md-4'), Div( HTML('<h4>Medication Voucher</h4>'), 'got_voucher', PrependedText('voucher_amount', '$'), PrependedText('patient_pays', '$'), css_class='col-xs-6', ), Div(HTML('<h4>Imaging Voucher</h4>'), 'got_imaging_voucher', PrependedText('imaging_voucher_amount', '$'), PrependedText('patient_pays_imaging', '$'), css_class='col-xs-6')), Submit('pending', 'Save for Later', css_class='btn btn-warning'), Submit('complete', 'Submit', css_class='btn btn-success')) self.fields['ros'].widget.attrs['rows'] = 15 self.fields['pe'].widget.attrs['rows'] = 14 if not settings.OSLER_DISPLAY_DIAGNOSIS: # delete diagnosis self.helper.layout[1].pop(2) # delete diagnosis category self.helper.layout[1].pop(2) if not settings.OSLER_DISPLAY_VOUCHERS: # delete medication voucher self.helper.layout[4].pop(5) # delete imaging voucher self.helper.layout[4].pop(5) def clean(self): """Use form's clean hook to verify that fields in Workup are consistent with one another (e.g. if pt recieved a voucher, amount is given).""" cleaned_data = super(WorkupForm, self).clean() if 'pending' in self.data: cleaned_data['is_pending'] = True return required_fields = [ 'chief_complaint', 'hpi', 'pmh', 'psh', 'meds', 'allergies', 'fam_hx', 'soc_hx', 'ros', 'pe', 'a_and_p' ] for field in required_fields: if not cleaned_data.get(field): self.add_error(field, _("This field is required.")) # we allow specification of units when the measurement is not given # because you cannot uncheck radios and the converter methods accept # Nones. form_required_if(self, 't', ['temperature_units']) form_required_if(self, 'height', ['height_units']) form_required_if(self, 'weight', ['weight_units']) form_required_if(self, 'got_voucher', ['voucher_amount', 'patient_pays']) form_required_if(self, 'got_imaging_voucher', ['imaging_voucher_amount', 'patient_pays_imaging']) attending = cleaned_data.get('attending') if attending and attending in cleaned_data.get('other_volunteer'): self.add_error( 'other_volunteer', 'Attending physician must be different from other volunteers.') if 't' in cleaned_data and cleaned_data.get('t') is not None: if cleaned_data.get('temperature_units') == 'F': c = Decimal(fahrenheit2centigrade( cleaned_data.get('t'))).quantize(Decimal('.1'), rounding=ROUND_HALF_UP) cleaned_data['t'] = c if 'weight' in cleaned_data and cleaned_data.get('weight') is not None: if cleaned_data.get('weight_units') == 'lbs': kgs = Decimal(pounds2kilos( cleaned_data.get('weight'))).quantize( Decimal('.1'), rounding=ROUND_HALF_UP) cleaned_data['weight'] = kgs if 'height' in cleaned_data and cleaned_data.get('height') is not None: if cleaned_data.get('height_units') == 'in': cm = int(inches2cm(cleaned_data.get('height'))) cleaned_data['height'] = cm for field in ['ros', 'pe'] + settings.OSLER_WORKUP_COPY_FORWARD_FIELDS: user_input = cleaned_data.get(field) if not user_input: continue cleaned_data[field] = user_input.strip() if "UPDATE" in cleaned_data.get(field): self.add_error( field, _("Please delete the heading and update contents as necessary" )) form_require_together(self, ['bp_sys', 'bp_dia']) if cleaned_data.get('bp_sys') and cleaned_data.get('bp_dia'): if cleaned_data.get('bp_sys') <= cleaned_data.get('bp_dia'): for field in ['bp_sys', 'bp_dia']: self.add_error( field, 'Systolic blood pressure must be strictly greater ' 'than diastolic blood pressure.')
class VcfImportForm(CremeModelForm): class Meta: model = Contact fields = ('user', 'civility', 'first_name', 'last_name', 'position') vcf_step = IntegerField(widget=HiddenInput) image_encoded = CharField(required=False, widget=HiddenInput) # Details phone = CharField(label=_('Phone number'), required=False) mobile = CharField(label=_('Mobile'), required=False) fax = CharField(label=_('Fax'), required=False) email = EmailField(label=_('Email address'), required=False) url_site = URLField(label=_('Web Site'), required=False) # Address homeaddr_name = CharField(label=_('Name'), required=False) homeaddr_address = CharField(label=_('Address'), required=False) homeaddr_city = CharField(label=_('City'), required=False) homeaddr_country = CharField(label=_('Country'), required=False) homeaddr_code = CharField(label=_('Zip code'), required=False) homeaddr_region = CharField(label=_('Region'), required=False) # Related Organisation create_or_attach_orga = BooleanField( label=_('Create or attach organisation'), required=False, initial=False, ) organisation = CreatorEntityField(label=_('Organisation'), required=False, model=Organisation) relation = ModelChoiceField( label=_('Position in the organisation'), queryset=RelationType.objects.none(), initial=REL_SUB_EMPLOYED_BY, required=False, empty_label='', widget=DynamicSelect(attrs={'autocomplete': True}), ) # TODO: Composite field update_work_name = BooleanField( label=_('Update name'), required=False, initial=False, help_text=_('Update organisation selected name')) update_work_phone = BooleanField( label=_('Update phone'), required=False, initial=False, help_text=_('Update organisation selected phone')) update_work_fax = BooleanField( label=_('Update fax'), required=False, initial=False, help_text=_('Update organisation selected fax')) update_work_email = BooleanField( label=_('Update email'), required=False, initial=False, help_text=_('Update organisation selected email')) update_work_url_site = BooleanField( label=_('Update web site'), required=False, initial=False, help_text=_('Update organisation selected web site')) update_work_address = BooleanField( label=_('Update address'), required=False, initial=False, help_text=_('Update organisation selected address')) # Organisation name & details work_name = CharField(label=_('Name'), required=False) work_phone = CharField(label=_('Phone number'), required=False) work_fax = CharField(label=_('Fax'), required=False) work_email = EmailField(label=_('Email address'), required=False) work_url_site = URLField(label=_('Web Site'), required=False) # Organisation address workaddr_name = CharField(label=_('Name'), required=False) workaddr_address = CharField(label=_('Address'), required=False) workaddr_city = CharField(label=_('City'), required=False) workaddr_country = CharField(label=_('Country'), required=False) workaddr_code = CharField(label=_('Zip code'), required=False) workaddr_region = CharField(label=_('Region'), required=False) error_messages = { 'required4orga': _('Required, if you want to create organisation'), 'no_orga_creation': _('Create organisation not checked'), 'orga_not_selected': _('Organisation not selected'), 'required2update': _('Required, if you want to update organisation'), } # Names of the fields corresponding to the Contact's details. contact_details = ['phone', 'mobile', 'fax', 'email', 'url_site'] # Names of the fields corresponding to the related Organisation (but not its Address). orga_fields = ['name', 'phone', 'email', 'fax', 'url_site'] # Correspondence between VCF field types & form-field names. phone_dict = { 'HOME': 'phone', 'CELL': 'mobile', 'FAX': 'fax', 'WORK': 'work_phone', } email_dict = { 'HOME': 'email', 'INTERNET': 'email', 'WORK': 'work_email', } url_dict = { 'HOME': 'url_site', 'INTERNET': 'url_site', 'WORK': 'work_url_site', } # Form-field names prefix for address + correspondence with VCF field types. address_prefixes = { 'HOME': HOME_ADDR_PREFIX, 'WORK': WORK_ADDR_PREFIX, } # Mapping between form fields names (which use vcf lib names) & Address fields names. address_mapping = [ ('name', 'name'), ('address', 'address'), ('city', 'city'), ('country', 'country'), ('code', 'zipcode'), ('region', 'department'), ] # blocks = CremeModelWithUserForm.blocks.new( blocks = CremeModelForm.blocks.new( ('details', _('Details'), contact_details), ('contact_address', _('Billing address'), [HOME_ADDR_PREFIX + n[0] for n in address_mapping]), ('organisation', _('Organisation'), [ 'create_or_attach_orga', 'organisation', 'relation', *chain.from_iterable( ('update_work_' + fn, 'work_' + fn) for fn in orga_fields) ]), ('organisation_address', _('Organisation billing address'), [ 'update_work_address', *(WORK_ADDR_PREFIX + n[0] for n in address_mapping) ]), ) type_help_text = _('Read in VCF File without type : ') other_help_text = _('Read in VCF File : ') def __init__(self, vcf_data=None, *args, **kwargs): super().__init__(*args, **kwargs) fields = self.fields if vcf_data: self._init_contact_fields(vcf_data) self._init_orga_field(vcf_data) self._init_addresses_fields(vcf_data) if vcf_data.contents.get('photo'): fields['image_encoded'].initial = vcf_data.photo.value.replace( '\n', '') # Beware: this queryset directly in the field declaration does not work on some systems in unit tests... # (it seems that the problem it caused by the M2M - other fields work, but why ???) fields['relation'].queryset = RelationType.objects.filter( subject_ctypes=_get_ct(Contact), object_ctypes=_get_ct(Organisation), ) self._hide_fields() def _hide_fields(self): fields = self.fields address_mapping = self.address_mapping fconfigs = FieldsConfig.get_4_models((Contact, Organisation, Address)) # TODO: use shipping address if not hidden ? if fconfigs[Contact].is_fieldname_hidden('billing_address'): prefix = HOME_ADDR_PREFIX for form_fname, __ in address_mapping: del fields[prefix + form_fname] is_orga_field_hidden = fconfigs[Organisation].is_fieldname_hidden for fname in [*fields ]: # NB: Cannot mutate the OrderedDict during iteration. # NB: 5 == len('work_') if fname.startswith('work_') and is_orga_field_hidden(fname[5:]): del fields[fname] del fields['update_' + fname] if is_orga_field_hidden('billing_address'): prefix = WORK_ADDR_PREFIX for form_fname, __ in address_mapping: del fields[prefix + form_fname] del fields['update_work_address'] is_addr_field_hidden = fconfigs[Address].is_fieldname_hidden addr_prefixes = self.address_prefixes.values() for form_fname, model_fname in address_mapping: if is_addr_field_hidden(model_fname): for prefix in addr_prefixes: fields.pop(prefix + form_fname, None) def _init_contact_fields(self, vcf_data): contents = vcf_data.contents fields = self.fields contact_data = contents.get('n') if contact_data: value = vcf_data.n.value last_name = value.family fields['first_name'].initial = value.given fields['last_name'].initial = last_name fields['homeaddr_name'].initial = last_name prefix = value.prefix if prefix: # TODO: find in title too ? civ = Civility.objects.filter( shortcut__icontains=prefix).first() if civ: fields['civility'].initial = civ.id else: fields[ 'civility'].help_text = self.other_help_text + prefix else: first_name, sep, last_name = vcf_data.fn.value.partition(' ') fields['first_name'].initial = first_name fields['last_name'].initial = last_name fields['homeaddr_name'].initial = last_name if contents.get('title'): title = vcf_data.title.value position = Position.objects.filter(title__icontains=title).first() if position: fields['position'].initial = position.id else: fields['position'].help_text = self.other_help_text + title init_detail = self._init_detail_field init_detail(contents.get('tel'), self.phone_dict) init_detail(contents.get('email'), self.email_dict) init_detail(contents.get('url'), self.url_dict) def _init_detail_field(self, detail_data, field_dict): if detail_data: fields = self.fields for key in detail_data: param = key.params.get('TYPE') if param: try: fields[field_dict[param[0]]].initial = key.value except KeyError: # eg: invalid type, hidden field pass else: self._generate_help_text(field_dict['HOME'], key.value) def _init_orga_field(self, vcf_data): if vcf_data.contents.get('org'): fields = self.fields org_name = vcf_data.org.value[0] orga = Organisation.objects.filter(name=org_name).first() if orga: fields['organisation'].initial = orga.id fields['create_or_attach_orga'].initial = True fields['work_name'].initial = org_name fields['workaddr_name'].initial = org_name def _init_addresses_fields(self, vcf_data): fields = self.fields get_prefix = self.address_prefixes.get for adr in vcf_data.contents.get('adr', ()): param = adr.params.get('TYPE') value = adr.value if param: prefix = get_prefix(param[0]) if prefix is None: continue box = value.box fields[prefix + 'address'].initial = ( box + ' ' + value.street) if box else value.street fields[prefix + 'city'].initial = value.city fields[prefix + 'country'].initial = value.country fields[prefix + 'code'].initial = value.code fields[prefix + 'region'].initial = value.region else: self._generate_help_text( 'homeaddr_address', ', '.join([ value.box, value.street, value.city, value.region, value.code, value.country, ]), ) def _generate_help_text(self, field_name, value): field = self.fields[field_name] help_text = field.help_text if not help_text: field.help_text = self.type_help_text + value else: field.help_text = '{} | {}'.format(help_text, value) def _clean_orga_field(self, field_name): cleaned_data = self.cleaned_data cleaned = cleaned_data.get(field_name) if cleaned_data['create_or_attach_orga'] and not cleaned: raise ValidationError( self.error_messages['required4orga'], code='required4orga', ) return cleaned clean_work_name = lambda self: self._clean_orga_field('work_name') clean_relation = lambda self: self._clean_orga_field('relation') def _clean_update_checkbox(self, checkbox_name): cleaned_data = self.cleaned_data checked = cleaned_data[checkbox_name] if checked: if not cleaned_data['create_or_attach_orga']: raise ValidationError( self.error_messages['no_orga_creation'], code='no_orga_creation', ) elif not cleaned_data['organisation']: raise ValidationError( self.error_messages['orga_not_selected'], code='orga_not_selected', ) return checked clean_update_work_name = lambda self: self._clean_update_checkbox( 'update_work_name') clean_update_work_phone = lambda self: self._clean_update_checkbox( 'update_work_phone') clean_update_work_email = lambda self: self._clean_update_checkbox( 'update_work_email') clean_update_work_fax = lambda self: self._clean_update_checkbox( 'update_work_fax') clean_update_work_url_site = lambda self: self._clean_update_checkbox( 'update_work_url_site') clean_update_work_address = lambda self: self._clean_update_checkbox( 'update_work_address') def clean_update_field(self, field_name): cleaned_data = self.cleaned_data value = cleaned_data[field_name] if not value and \ all(cleaned_data[k] for k in ('create_or_attach_orga', 'organisation', 'update_' + field_name)): raise ValidationError(self.error_messages['required2update'], code='required2update') return value clean_work_phone = lambda self: self.clean_update_field('work_phone') clean_work_email = lambda self: self.clean_update_field('work_email') clean_work_fax = lambda self: self.clean_update_field('work_fax') clean_work_url_site = lambda self: self.clean_update_field('work_url_site') clean_work_address = lambda self: self.clean_update_field('work_address') def _create_contact(self, cleaned_data): get_data = cleaned_data.get return Contact.objects.create( user=cleaned_data['user'], civility=cleaned_data['civility'], first_name=cleaned_data['first_name'], last_name=cleaned_data['last_name'], position=get_data('position'), # NB: we do not use cleaned_data.get() in order to not overload # default fields values **{ fname: cleaned_data[fname] for fname in self.contact_details if fname in cleaned_data }) def _create_address(self, cleaned_data, owner, data_prefix): # NB: we do not use cleaned_data.get() in order to not overload default fields values kwargs = {} for form_fname, model_fname in self.address_mapping: try: kwargs[model_fname] = cleaned_data[data_prefix + form_fname] except KeyError: pass address = Address(owner=owner, **kwargs) if address: address.save() return address def _create_image(self, contact): cleaned_data = self.cleaned_data image_encoded = cleaned_data['image_encoded'] if image_encoded: img_name = secure_filename('{}_{}_{}'.format( contact.last_name, contact.first_name, contact.id)) img_path = None if image_encoded.startswith(URL_START): tmp_img_path = None try: if int(urlopen(image_encoded).info() ['content-length']) <= settings.VCF_IMAGE_MAX_SIZE: tmp_img_path = path.normpath( path.join(IMG_UPLOAD_PATH, img_name)) urlretrieve( image_encoded, path.normpath( path.join(settings.MEDIA_ROOT, tmp_img_path))) except: logger.exception('Error with image') else: img_path = tmp_img_path else: # TODO: manage urls encoded in base64 ?? try: # TODO: factorise with activesync ?? img_data = base64.decodebytes(image_encoded.encode()) img_path = handle_uploaded_file( ContentFile(img_data), path=IMG_UPLOAD_PATH.split('/'), name='{}.{}'.format( img_name, get_image_format(img_data), ), ) except Exception: logger.exception('VcfImportForm.save()') if img_path: return Document.objects.create( user=cleaned_data['user'], title=gettext('Image of {contact}').format( contact=contact), filedata=img_path, linked_folder=Folder.objects.get(uuid=UUID_FOLDER_IMAGES), description=gettext('Imported by VCFs'), ) def _create_orga(self, contact): cleaned_data = self.cleaned_data if cleaned_data['create_or_attach_orga']: get_data = cleaned_data.get organisation = get_data('organisation') save_orga = False user = cleaned_data['user'] addr_prefix = WORK_ADDR_PREFIX if organisation: # TODO: select_for_update() option in CreatorEntityField ? organisation = Organisation.objects.select_for_update().get( id=organisation.id) for fname in self.orga_fields: if get_data('update_work_' + fname): setattr(organisation, fname, get_data('work_' + fname)) if get_data('update_work_address'): billing_address = organisation.billing_address if billing_address is not None: for form_fname, model_fname in self.address_mapping: value = get_data(addr_prefix + form_fname) if value: setattr(billing_address, model_fname, value) organisation.billing_address.save() else: organisation.billing_address = self._create_address( cleaned_data, owner=organisation, data_prefix=addr_prefix, ) save_orga = True else: # NB: we do not use cleaned_data.get() in order to not overload default fields values orga_kwargs = {} for fname in self.orga_fields: try: orga_kwargs[fname] = cleaned_data['work_' + fname] except KeyError: pass organisation = Organisation.objects.create(user=user, **orga_kwargs) orga_addr = self._create_address( cleaned_data, owner=organisation, data_prefix=addr_prefix, ) if orga_addr is not None: organisation.billing_address = orga_addr save_orga = True if save_orga: organisation.save() Relation.objects.create( user=user, subject_entity=contact, type=cleaned_data['relation'], object_entity=organisation, ) @atomic def save(self, *args, **kwargs): cleaned_data = self.cleaned_data save_contact = False contact = self._create_contact(cleaned_data) image = self._create_image(contact) if image is not None: contact.image = image save_contact = True contact_addr = self._create_address( cleaned_data, owner=contact, data_prefix=HOME_ADDR_PREFIX, ) if contact_addr is not None: contact.billing_address = contact_addr save_contact = True self._create_orga(contact) if save_contact: contact.save() return contact
class CoorganizationEditForm(forms.ModelForm): country = ModelChoiceField( queryset=Country.objects.filter( organizationaddress__isnull=False).distinct().order_by('name'), label=_("Country"), ) organization = ModelChoiceField( queryset=Organization.objects.all(), required=True, label=_("Institution"), widget=autocomplete.ModelSelect2(url='organization_autocomplete', attrs={ 'data-theme': 'bootstrap', 'data-width': 'null', 'data-placeholder': '---------' }, forward=['country']), ) class Meta: model = EducationGroupOrganization fields = [ 'country', 'organization', 'all_students', 'enrollment_place', 'diploma', 'is_producing_cerfificate', 'is_producing_annexe' ] class Media: css = {'all': ('css/select2-bootstrap.css', )} js = ('js/education_group/coorganization.js', ) def __init__(self, education_group_year=None, *args, **kwargs): if not education_group_year and not kwargs.get('instance'): raise ImproperlyConfigured( "Provide an education_group_year or an instance") super().__init__(*args, **kwargs) if not kwargs.get('instance'): self.instance.education_group_year = education_group_year if self.instance.pk: country = Country.objects.filter( organizationaddress__organization=self.instance.organization ).first() else: country = Country.objects.filter(organizationaddress__isnull=False, iso_code="BE").first() self.fields['country'].initial = country def check_unique_constraint_between_education_group_year_organization( self): qs = EducationGroupOrganization.objects.filter( education_group_year=self.instance.education_group_year, organization=self.cleaned_data['organization'], ) if self.instance and self.instance.pk: qs = qs.exclude(id=self.instance.pk) if qs.exists(): self.add_error( 'organization', _('There is already a coorganization with this organization')) return False return True def is_valid(self): return super(CoorganizationEditForm, self).is_valid() and \ self.check_unique_constraint_between_education_group_year_organization()
def test_queryset_manager(self): f = ModelChoiceField(ChoiceOptionModel.objects) choice = ChoiceOptionModel.objects.create(name="choice 1") self.assertEqual(list(f.choices), [('', '---------'), (choice.pk, str(choice))])
class SelectArtistForm(forms.Form): artist = ModelChoiceField(queryset=Artist.objects.all())
class ScenarioDeviceFormNew(Form): device = ModelChoiceField(label=_('Device'), queryset=Device.objects.all()) def __init__(self, *args, **kwargs): super(ScenarioDeviceFormNew, self).__init__(*args, **kwargs)
class ImageForm(ImageFormMixin, ModelForm): image_file = ModelChoiceField(queryset=Image.objects.all(), required=False, label=_("Image"))
class ChooseNeighborhoodForm(Form): neighborhood = ModelChoiceField(queryset=Neighborhood.objects.all()) auth_provider = CharField()
class IngredientWeightUnitForm(ModelForm): unit = ModelChoiceField(queryset=WeightUnit.objects.filter( language=load_language())) class Meta: model = IngredientWeightUnit
class LinkForm(EntangledModelFormMixin): LINK_TYPE_CHOICES = [ ('cmspage', _("CMS Page")), ('download', _("Download File")), ('exturl', _("External URL")), ('email', _("Mail To")), ] link_type = fields.ChoiceField( label=_("Link"), help_text=_("Type of link"), ) cms_page = LinkSearchField( required=False, label='', help_text=_("An internal link onto any CMS page of this site"), ) section = SectionChoiceField( required=False, label='', help_text=_("Page bookmark"), ) download_file = ModelChoiceField( label='', queryset=FilerFileModel.objects.all(), widget=AdminFileWidget(ManyToOneRel(FilerFileField, FilerFileModel, 'id'), admin_site), required=False, help_text=_("An internal link onto a file from filer"), ) ext_url = fields.URLField( required=False, label=_("URL"), help_text=_("Link onto external page"), ) mail_to = fields.EmailField( required=False, label=_("Email"), help_text=_("Open Email program with this address"), ) link_target = fields.ChoiceField( choices=[ ('', _("Same Window")), ('_blank', _("New Window")), ('_parent', _("Parent Window")), ('_top', _("Topmost Frame")), ], label=_("Link Target"), widget=RadioSelect, required=False, help_text=_("Open Link in other target."), ) link_title = fields.CharField( label=_("Title"), required=False, help_text=_("Link's Title"), ) class Meta: entangled_fields = {'glossary': ['link_type', 'cms_page', 'section', 'download_file', 'ext_url', 'mail_to', 'link_target', 'link_title']} def __init__(self, *args, **kwargs): link_type_choices = [] if not getattr(self, 'require_link', True): link_type_choices.append(('', _("No Link"))) self.declared_fields['link_type'].required = False link_type_choices.extend(self.LINK_TYPE_CHOICES) self.declared_fields['link_type'].choices = link_type_choices self.declared_fields['link_type'].initial = link_type_choices[0][0] instance = kwargs.get('instance') if instance and instance.glossary.get('link_type') == 'cmspage': self._preset_section(instance) super().__init__(*args, **kwargs) def _preset_section(self, instance): """ Field ``cms_page`` may refer onto any CMS page, which itself may contain bookmarks. This method creates the list of bookmarks. """ self.base_fields['section'].choices = self.base_fields['section'].choices[:1] try: cascade_page = get_related_object(instance.glossary, 'cms_page').cascadepage for key, val in cascade_page.glossary.get('element_ids', {}).items(): self.base_fields['section'].choices.append((key, val)) except (AttributeError, ObjectDoesNotExist): pass def clean(self): cleaned_data = super().clean() link_type = cleaned_data.get('link_type') error = None if link_type == 'cmspage': if cleaned_data['cms_page'] is None: error = ValidationError(_("CMS page to link to is missing.")) self.add_error('cms_page', error) elif link_type == 'download': if cleaned_data['download_file'] is None: error = ValidationError(_("File for download is missing.")) self.add_error('download_file', error) elif link_type == 'exturl': ext_url = cleaned_data['ext_url'] if ext_url: try: response = requests.head(ext_url, allow_redirects=True) if response.status_code != 200: error = ValidationError(_("No external page found on {url}.").format(url=ext_url)) except Exception as exc: error = ValidationError(_("Failed to connect to {url}.").format(url=ext_url)) else: error = ValidationError(_("No external URL provided.")) if error: self.add_error('ext_url', error) elif link_type == 'email': mail_to = cleaned_data['mail_to'] if not re.match(r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)', mail_to): error = ValidationError(_("'{email}' is not a valid email address.").format(email=mail_to)) self.add_error('mail_to', error) if error: raise error return cleaned_data @classmethod def unset_required_for(cls, sharable_fields): """ Fields borrowed by `SharedGlossaryAdmin` to build its temporary change form, only are required if they are declared in `sharable_fields`. Otherwise just deactivate them. """ if 'link_content' in cls.base_fields and 'link_content' not in sharable_fields: cls.base_fields['link_content'].required = False if 'link_type' in cls.base_fields and 'link' not in sharable_fields: cls.base_fields['link_type'].required = False
class ReadRecordForm(Form): Weapon = ModelChoiceField(queryset=Weapon.objects.all()) Price = ModelChoiceField(queryset=Price.objects.all())
class ExerciseForm(ModelForm): # Redefine some fields here to set some properties # (some of this could be done with a crispy form helper and would be # a cleaner solution) category = ModelChoiceField(queryset=ExerciseCategory.objects.all(), widget=Select()) muscles = ModelMultipleChoiceField( queryset=Muscle.objects.all(), widget=CheckboxSelectMultiple(), required=False, ) muscles_secondary = ModelMultipleChoiceField( queryset=Muscle.objects.all(), widget=CheckboxSelectMultiple(), required=False, ) equipment = ModelMultipleChoiceField( queryset=Equipment.objects.all(), widget=CheckboxSelectMultiple(), required=False, ) description = CharField( label=_('Description'), widget=Textarea, required=False, ) class Meta: model = Exercise widgets = {'equipment': TranslatedSelectMultiple()} fields = [ 'name_original', 'category', 'description', 'muscles', 'muscles_secondary', 'equipment', 'license', 'license_author', ] class Media: js = (settings.STATIC_URL + 'yarn/tinymce/tinymce.min.js', ) def clean_name_original(self): """ Throws a validation error if the newly submitted name is too similar to an existing exercise's name """ name_original = self.cleaned_data['name_original'] if not self.instance.id: language = load_language() exercises = Exercise.objects.accepted() \ .filter(language=language) for exercise in exercises: exercise_name = str(exercise) min_edit_dist = levenshtein(exercise_name.casefold(), name_original.casefold()) if min_edit_dist < MIN_EDIT_DISTANCE_THRESHOLD: raise ValidationError( _('%(name_original)s is too similar to existing exercise ' '"%(exercise_name)s"'), params={ 'name_original': name_original, 'exercise_name': exercise_name }, ) return name_original
class TaskForm(ModelForm): problem_category = ModelChoiceField(queryset=TaskCategory.objects.filter( stage=TaskCategory.Stage.INITIAL_ASSESSMENT), required=False, label="Problem category") resolution_category = ModelChoiceField( queryset=TaskCategory.objects.filter( stage=TaskCategory.Stage.COMPLETION), required=False, label="Resolution category") action = ChoiceField(choices=[('create', 'create'), ('update', 'update'), ('resolve', 'resolve')], label='Action') description = CharField(required=False, label="Description") class Meta: model = Task fields = [ 'tool', 'urgency', 'estimated_resolution_time', 'force_shutdown', 'safety_hazard' ] def __init__(self, user, *args, **kwargs): super(TaskForm, self).__init__(*args, **kwargs) self.user = user self.fields['tool'].required = False self.fields['urgency'].required = False def clean_description(self): return self.cleaned_data['description'].strip() def clean(self): if any(self.errors): return super(TaskForm, self).clean() action = self.cleaned_data['action'] if action == 'create': if not self.cleaned_data['description']: raise ValidationError('You must describe the problem.') if action == 'resolve': if self.instance.cancelled or self.instance.resolved: raise ValidationError( "This task can't be resolved because it is marked as 'cancelled' or 'resolved' already." ) def save(self, commit=True): instance = super(TaskForm, self).save(commit=False) action = self.cleaned_data['action'] description = self.cleaned_data['description'] instance.problem_category = self.cleaned_data['problem_category'] now = timezone.now() if action == 'create': instance.problem_description = description instance.urgency = Task.Urgency.HIGH if self.cleaned_data[ 'force_shutdown'] or self.cleaned_data[ 'safety_hazard'] else Task.Urgency.NORMAL instance.creator = self.user if action == 'update': instance.last_updated = timezone.now() instance.last_updated_by = self.user instance.cancelled = False instance.resolved = False if description: preface = f'On {format_datetime(now)} {self.user.get_full_name()} updated this task:\n' if instance.progress_description is None: instance.progress_description = preface + description else: instance.progress_description += '\n\n' + preface + description instance.progress_description = instance.progress_description.strip( ) if action == 'resolve': instance.cancelled = False instance.resolved = True instance.resolution_time = now instance.resolver = self.user if 'resolution_category' in self.cleaned_data: instance.resolution_category = self.cleaned_data[ 'resolution_category'] if 'description' in self.cleaned_data: if instance.resolution_description: preface = f'On {format_datetime(now)} {self.user.get_full_name()} updated the resolution information:\n' instance.resolution_description = ( instance.resolution_description + '\n\n' + preface + self.cleaned_data['description']).strip() else: instance.resolution_description = self.cleaned_data[ 'description'] return super(TaskForm, self).save(commit=True)