def test_has_changed_empty(self): field = SimpleArrayField(forms.CharField()) self.assertIs(field.has_changed(None, None), False) self.assertIs(field.has_changed(None, ''), False) self.assertIs(field.has_changed(None, []), False) self.assertIs(field.has_changed([], None), False) self.assertIs(field.has_changed([], ''), False)
def test_validate_fail_base_field_error_params(self): field = SimpleArrayField(forms.CharField(max_length=2)) with self.assertRaises(exceptions.ValidationError) as cm: field.clean('abc,c,defg') errors = cm.exception.error_list self.assertEqual(len(errors), 2) first_error = errors[0] self.assertEqual( first_error.message, 'Item 0 in the array did not validate: Ensure this value has at most 2 characters (it has 3).' ) self.assertEqual(first_error.code, 'item_invalid') self.assertEqual(first_error.params, {'nth': 0, 'value': 'abc', 'limit_value': 2, 'show_value': 3}) second_error = errors[1] self.assertEqual( second_error.message, 'Item 2 in the array did not validate: Ensure this value has at most 2 characters (it has 4).' ) self.assertEqual(second_error.code, 'item_invalid') self.assertEqual(second_error.params, {'nth': 2, 'value': 'defg', 'limit_value': 2, 'show_value': 4})
def test_validate_fail_base_field_error_params(self): field = SimpleArrayField(forms.CharField(max_length=2)) with self.assertRaises(exceptions.ValidationError) as cm: field.clean("abc,c,defg") errors = cm.exception.error_list self.assertEqual(len(errors), 2) first_error = errors[0] self.assertEqual( first_error.message, "Item 0 in the array did not validate: Ensure this value has at most 2 characters (it has 3).", ) self.assertEqual(first_error.code, "item_invalid") self.assertEqual(first_error.params, {"nth": 0, "value": "abc", "limit_value": 2, "show_value": 3}) second_error = errors[1] self.assertEqual( second_error.message, "Item 2 in the array did not validate: Ensure this value has at most 2 characters (it has 4).", ) self.assertEqual(second_error.code, "item_invalid") self.assertEqual(second_error.params, {"nth": 2, "value": "defg", "limit_value": 2, "show_value": 4})
class NotificationCreationForm(forms.Form): content = forms.CharField( label=ugettext_lazy('Content'), max_length=140, widget=forms.Textarea, ) url = forms.URLField(label=ugettext_lazy('URL')) type = forms.ChoiceField( label=ugettext_lazy("Type"), choices=NOTIFICATION_TYPES, ) domain_specific = forms.BooleanField( label=ugettext_lazy("This notification is not for all domains"), required=False) domains = SimpleArrayField( base_field=forms.CharField(), label=ugettext_lazy("Domains"), widget=forms.Textarea, help_text=ugettext_lazy( "Enter a comma separated list of domains for this notification. " "This is only required if you have checked the box above."), required=False) def __init__(self, *args, **kwargs): from corehq.apps.notifications.views import ManageNotificationView super(NotificationCreationForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'POST' self.helper.form_class = 'form-horizontal' self.helper.form_action = '#' self.helper.label_class = 'col-sm-3 col-md-2' self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' self.helper.layout = crispy.Layout( crispy.Field('content'), crispy.Field('url'), crispy.Field('type'), hqcrispy.B3MultiField("Domain Specific", crispy.Field('domain_specific')), crispy.Field('domains'), hqcrispy.FormActions( twbscrispy.StrictButton( _("Submit Information"), type="submit", css_class="btn btn-primary", name="submit", ), hqcrispy.LinkButton( _("Cancel"), reverse(ManageNotificationView.urlname), css_class="btn btn-default", name="cancel", ), ), ) def save(self): data = self.cleaned_data Notification(content=data.get('content'), url=data.get('url'), type=data.get('type'), domain_specific=data.get('domain_specific'), domains=data.get('domains')).save()
def test_max_length(self): field = SimpleArrayField(forms.CharField(), max_length=2) with self.assertRaises(exceptions.ValidationError) as cm: field.clean("a,b,c") self.assertEqual(cm.exception.messages[0], "List contains 3 items, it should contain no more than 2.")
def test_delimiter_with_nesting(self): field = SimpleArrayField(SimpleArrayField(forms.CharField()), delimiter="|") value = field.clean("a,b|c,d") self.assertEqual(value, [["a", "b"], ["c", "d"]])
def test_delimiter_with_nesting(self): field = SimpleArrayField(SimpleArrayField(forms.CharField()), delimiter='|') value = field.clean('a,b|c,d') self.assertEqual(value, [['a', 'b'], ['c', 'd']])
def test_required(self): field = SimpleArrayField(forms.CharField(), required=True) with self.assertRaises(exceptions.ValidationError) as cm: field.clean('') self.assertEqual(cm.exception.messages[0], 'This field is required.')
def test_delimiter(self): field = SimpleArrayField(forms.CharField(), delimiter='|') value = field.clean('a|b|c') self.assertEqual(value, ['a', 'b', 'c'])
class ModifyItemsForm(forms.Form): """Form for ADDING new items and names for an org.""" id = forms.IntegerField(min_value=1, max_value=9223372036854775807, required=False) entity = forms.IntegerField(min_value=1, max_value=9223372036854775807, required=False) item = SimpleArrayField( forms.IntegerField(min_value=1, max_value=9223372036854775807), max_length=20000, required=False, ) item_condition = SimpleArrayField( forms.IntegerField(min_value=0, max_value=_max_condition_value), max_length=20000, required=False, ) # TODO Add delete. I'm just scared that automating deletes can be devastating in bot attacks names = SimpleArrayField(forms.CharField(max_length=100), max_length=1500, required=False) names_condition = SimpleArrayField( forms.IntegerField(min_value=0, max_value=_max_condition_value), max_length=1500, required=False, ) def clean_item(self): item: List[int] = self.cleaned_data["item"] if item is []: item: Type[list] = list else: if Item.objects.filter(id__in=item, is_appropriate=False).exists(): raise forms.ValidationError( _("You can only select appropriate items.")) return item def clean_names(self): names = self.cleaned_data["names"] if names is []: names = list else: names = [escape(name) for name in names] return names def clean(self): cleaned_data = super().clean() try: item: List[int] = self.cleaned_data["item"] item_error = forms.ValidationError( "Item list and conditions for them are not equal in size.") if item is []: if len(self.cleaned_data["item_condition"]) != 0: self.add_error("item", item_error) self.add_error("item_condition", item_error) else: if len(self.cleaned_data["item_condition"]) != len(item): self.add_error("item", item_error) self.add_error("item_condition", item_error) except KeyError: # In case item is just left null pass try: names = self.cleaned_data["names"] names_error = forms.ValidationError( "Name list and conditions for them are not equal in size.") if names is []: if len(self.cleaned_data["names_condition"]) != 0: self.add_error("names", names_error) self.add_error("names_condition", names_error) else: if len(self.cleaned_data["names_condition"]) != len(names): self.add_error("names", names_error) self.add_error("names_condition", names_error) except KeyError: # In case item is just left null pass return cleaned_data def clean_entity(self): entity = self.cleaned_data["entity"] if entity is None and self.cleaned_data["id"] is None: raise forms.ValidationError( _("You must specify either the id of your form " "or the entity's id to create a new form.")) if entity is not None: if not Charity.objects.filter(id=entity).exists(): raise forms.ValidationError( _("Entity with that ID does not exist.")) return entity
def test_to_python_fail(self): field = SimpleArrayField(forms.IntegerField()) with self.assertRaises(exceptions.ValidationError) as cm: field.clean('a,b,9') self.assertEqual(cm.exception.messages[0], 'Item 0 in the array did not validate: Enter a whole number.')
class RegistrationForm(forms.ModelForm): username = forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': _("Username") } ) ) first_name = forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': _("First Name") } ) ) last_name = forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': _("Last Name") } ) ) phones = SimpleArrayField(forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': _("Phone Number") } ), help_text=_("if you have multiple phones, enter them separated by a coma.") )) password = forms.CharField( widget=forms.PasswordInput( attrs={ 'placeholder': _("Password") } ) ) c_password = forms.CharField( widget=forms.PasswordInput( attrs={ 'placeholder': _("Confirm Password") } ), label=_('Confirm Password') ) email = forms.EmailField( required=False, widget=forms.EmailInput( attrs={ 'placeholder': _("Email") } ) ) user_type = forms.ChoiceField(widget=forms.HiddenInput, choices=(('C', _('Client')), ('S', _('Staff')))) class Meta: model = User fields = ['username', "first_name", "last_name", 'user_type', 'phones', 'email'] def clean(self): cleaned_data = super(RegistrationForm, self).clean() if not self.cleaned_data.get('password') == self.cleaned_data.get('c_password'): raise forms.ValidationError(_("Un-matching passwords!")) return cleaned_data def save(self, commit=True): user = super(RegistrationForm, self).save(commit=False) user.set_password(self.cleaned_data['password']) user.is_active = True user.save() user_type = self.cleaned_data['user_type'] if user_type == 'C': group, created = Group.objects.get_or_create(name='Client') user.groups.add(group) user.save() return user
class GetEventsForm(forms.Form): interests = SimpleArrayField(forms.CharField())
class CategoryTableForm(forms.ModelForm): """ Form to filter products by attributes, and build dataset for use in category table. """ x_axis_values = SimpleArrayField(base_field=forms.CharField()) y_axis_values = SimpleArrayField(base_field=forms.CharField()) brands = forms.ModelMultipleChoiceField(label=_('Brands'), queryset=Brand.objects.published(), required=False, help_text=_("Only show products for these brands.")) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) attributes_queryset = AttributeType.objects.order_by('name') self.fields['x_axis_values'].widget = TagWidget() self.fields['x_axis_attribute'].label = _('Horizontal label') self.fields['x_axis_values'].label = _('Horizontal values') self.fields['x_axis_values'].required = False self.fields['x_axis_attribute'].required = False self.fields['x_axis_attribute'].queryset = attributes_queryset self.fields['y_axis_values'].widget = TagWidget() self.fields['y_axis_attribute'].label = _('Vertical label') self.fields['y_axis_values'].label = _('Vertical values') self.fields['y_axis_values'].required = False self.fields['y_axis_attribute'].required = False self.fields['y_axis_attribute'].queryset = attributes_queryset self.fields['websites'].queryset = Website.objects.published() self.fields['websites'].required = False self.fields['products'].queryset = Product.objects.published() self.fields['products'].required = False class Meta: model = CategoryTable fields = ['name', 'x_axis_attribute', 'x_axis_values', 'y_axis_attribute', 'y_axis_values', 'category', 'query', 'websites', 'brands', 'products'] def clean_x_axis_values(self) -> List[str]: return self.clean_axis_attributes(self.cleaned_data['x_axis_values'], self.cleaned_data['x_axis_attribute']) def clean_y_axis_values(self) -> List[str]: return self.clean_axis_attributes(self.cleaned_data['y_axis_values'], self.cleaned_data['y_axis_attribute']) def clean_axis_attributes(self, values: List[str], attribute_type: AttributeType): """ Ensures that string values submitted for attribute exist and can be used to filter products. If values are numeric, cleaned data is returned. Numeric data can be used for value ranges and an attribute doesn't need to exist with that exact value. """ if not values and not attribute_type: return values if (values and not attribute_type) or (attribute_type and not values): raise ValidationError(_("Pivot values and labels must either be both selected or empty.")) if is_value_numeric(values[0]): return serialized_values_for_attribute_type(values, attribute_type) for value in values: if not attribute_type.productattributes.filter(data__value=value).exists() \ and not attribute_type.websiteproductattributes.filter(data__value=value).exists() \ and not Brand.objects.filter(name=value).exists(): raise ValidationError(_("'{attribute}' with value '{value}' does not exist.").format(attribute=attribute_type.name, value=value)) return serialized_values_for_attribute_type(values, attribute_type) def clean(self): category = self.cleaned_data['category'] self.validate_attribute_type('x_axis_attribute', self.cleaned_data['x_axis_attribute'], category) self.validate_attribute_type('y_axis_attribute', self.cleaned_data['y_axis_attribute'], category) return self.cleaned_data def validate_attribute_type(self, field, attribute_type: AttributeType, category: Category): if attribute_type.category and attribute_type.category != category: raise ValidationError({field: _("'{attribute}' from category '{attribute.category}' can't be used with '{category}'.").format( attribute=attribute_type, category=category )}) class Media: js = 'js/select2.min.js', 'js/category_line_up.js', css = { 'all': ( 'css/select2.min.css', ), }
class PostGuideForm(PostForm): title = forms.CharField( label="Заголовок", required=True, max_length=128, widget=forms.TextInput( attrs={ "placeholder": "Клубный Путеводитель: ******", "value": "Клубный Путеводитель: ******", }), ) text = forms.CharField( label="Текст путеводителя", required=True, max_length=500000, initial= "Ниже приведён шаблон, который вы можете редактировать как вам будет удобнее.\b\b" "Напишите пару предложений введения: чем славится ваш город, как он появился и зачем в него ехать?\n\n" "# Карта города\n\n" "Обведите на ней все главные места — где центр, где тусить, где жить, где есть, где ходить. " "Можете использовать скриншоты с сервиса hoodmaps.com, можете нарисовать свою карту, как удобнее. " "Можно даже несколько.\n\n" "# Основная информация\n\n" "- **Валюта**\n" " - [название, курс и как проще его запомнить]\n" "- **Население**\n" " - [количество человек]\n" "- **Визы**\n" " - [нужна ли соклубникам виза, паспорт и какой]\n" "- **Когда лучше всего приезжать?**\n" " - [месяц или сезон]\n" "- **Что обязательно взять с собой?**\n" " - [переходник для розеток, крем от солнца, или просто ничего]\n" "- **Как лучше добраться из аэропорта?**\n" " - [можно несколько вариантов, укажите примерные цены]\n" "- **Как лучше перемещаться по городу?**\n" " - [взять билет на транспорт или пользоваться такси?]\n" "- **Как вызывать такси?**\n" " - [название приложения или телефон]\n" "- **Есть ли доставка еды?**\n" " - [название приложения]\n" "- **Какую купить туристическую симку?**\n" " - [название и как купить]\n" "- **Можно ли везде платить картой?**\n" " - [да, либо сумма денег, которую надо снять]\n" "- **Можно ли пить воду из крана?**\n" " - [да/нет/ваш вариант]\n" "- **Главные супермаркеты для еды?**\n" " - [названия и чем отличаются]\n" "- **Говорят ли люди на улице по-английски?**\n" " - [и как к ним обращаться за помощью]\n" "- **Что нужно 100% увидеть и попробовать?**\n" " - [места, люди, явления]\n" "- **Чего остерегаться?**\n" " - [места, люди, явления]\n" "- **Сколько в среднем стоит 1 шаурма?**\n" " - [в местной валюте]\n\n" "# Основной маршрут туриста\n\n" "...\n\n" "# «Нетуристические» маршруты\n\n" "...\n\n" "# Где жить?\n\n" "...\n\n" "# Где и что поесть/выпить?\n\n" "...\n\n" "# Где затусить вечером?\n\n" "...\n\n" "# Опционально: где еще стоит побывать? Советы от местных\n\n" "...\n\n" "# Опционально: что можно купить чтобы увезти с собой\n\n" "...\n\n" "# Опционально: разговорник и основные фразы\n\n" "...\n\n", widget=forms.Textarea(attrs={ "maxlength": 500000, "class": "markdown-editor-full", }), ) coauthors = SimpleArrayField( forms.CharField(max_length=32), max_length=10, label="Соавторы поста", required=False, ) class Meta: model = Post fields = ["title", "text", "topic", "is_public", "coauthors"] def clean(self): cleaned_data = super().clean() self.validate_coauthors(cleaned_data) return cleaned_data
def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) super(UploadForm, self).__init__(*args, **kwargs) for item in FORM_ITEMS: if 'id' not in item: continue help_text = item.get('docstring', '') label = item['label'] if item['required']: label += ' *' if item['type'] == 'text': if not item['list']: self.fields[item['id']] = forms.CharField( max_length=255, label=label, help_text=help_text, required=False) else: self.fields[item['id']] = SimpleArrayField( forms.CharField(max_length=255, required=False), label=label, help_text=help_text, required=False) elif item['type'] == 'select': if not item['list']: self.fields[item['id']] = forms.ChoiceField( label=label, help_text=help_text, required=False, choices=item['options']) else: self.fields[item['id']] = SimpleArrayField( forms.CharField(max_length=255, required=False), label=label, help_text=help_text, required=False, widget=forms.Select(choices=item['options'])) elif item['type'] == 'number': if not item['list']: self.fields[item['id']] = forms.DecimalField( label=label, help_text=help_text, required=False) else: self.fields[item['id']] = SimpleArrayField( forms.DecimalField(required=False), label=label, help_text=help_text, required=False) elif item['type'] == 'date': if not item['list']: self.fields[item['id']] = forms.DateField( label=label, input_formats=[ '%m/%d/%Y', ], help_text=help_text, required=False) else: self.fields[item['id']] = SimpleArrayField( forms.DateField(input_formats=[ '%m/%d/%Y', ], required=False), label=label, help_text=help_text, required=False) if item['required']: add_clean_field(UploadForm, item['id'])
class numberForm(forms.Form): numbers = SimpleArrayField(forms.FloatField()) rows = forms.IntegerField() cols = forms.IntegerField()
class RuleForm(forms.Form): target_type = forms.ChoiceField(choices=Target.TYPE_CHOICES) target_sha256 = forms.CharField(validators=[validate_sha256]) policy = forms.ChoiceField(choices=Rule.POLICY_CHOICES) custom_msg = forms.CharField(label="Custom message", required=False, widget=forms.Textarea(attrs={"cols": "40", "rows": "10"})) serial_numbers = SimpleArrayField(forms.CharField(), required=False) primary_users = SimpleArrayField(forms.CharField(), required=False) tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all(), required=False) def __init__(self, *args, **kwargs): self.configuration = kwargs.pop("configuration") self.binary = kwargs.pop("binary", None) self.bundle = kwargs.pop("bundle", None) self.certificate = kwargs.pop("certificate", None) super().__init__(*args, **kwargs) if self.binary or self.bundle or self.certificate: del self.fields["target_type"] del self.fields["target_sha256"] if self.bundle: self.fields["policy"].choices = ( (k, v) for k, v in Rule.POLICY_CHOICES if k in Rule.BUNDLE_POLICIES ) if not any(k == Rule.BLOCKLIST for k, _ in self.fields["policy"].choices): del self.fields["custom_msg"] def clean(self): cleaned_data = super().clean() if self.binary: target_type = Target.BINARY target_sha256 = self.binary.sha_256 elif self.bundle: target_type = Target.BUNDLE target_sha256 = self.bundle.target.sha256 elif self.certificate: target_type = Target.CERTIFICATE target_sha256 = self.certificate.sha_256 else: target_type = cleaned_data.get("target_type") target_sha256 = cleaned_data.get("target_sha256") if target_type and target_sha256 and Rule.objects.filter(configuration=self.configuration, target__type=target_type, target__sha256=target_sha256).count(): self.add_error(None, "A rule for this target already exists") try: policy = int(cleaned_data.get("policy")) except (TypeError, ValueError): pass if target_type == Target.BUNDLE: try: bundle = Bundle.objects.get(target__sha256=target_sha256) except Bundle.DoesNotExist: self.add_error("bundle", 'Unknown bundle.') else: if not bundle.uploaded_at: self.add_error("bundle", "This bundle has not been uploaded yet.") if policy and policy not in Rule.BUNDLE_POLICIES: self.add_error("policy", "Policy not allowed for bundles.") if policy and policy != Rule.BLOCKLIST: custom_msg = cleaned_data.get("custom_msg") if custom_msg: self.add_error("custom_msg", "Can only be set on BLOCKLIST rules") cleaned_data["target_type"] = target_type cleaned_data["target_sha256"] = target_sha256 return cleaned_data def save(self): target, _ = Target.objects.get_or_create(type=self.cleaned_data["target_type"], sha256=self.cleaned_data["target_sha256"]) rule = Rule.objects.create(configuration=self.configuration, target=target, policy=self.cleaned_data["policy"], custom_msg=self.cleaned_data.get("custom_msg", ""), serial_numbers=self.cleaned_data.get("serial_numbers") or [], primary_users=self.cleaned_data.get("primary_users") or []) tags = self.cleaned_data.get("tags") if tags: rule.tags.set(tags) return rule
def test_prepare_value(self): field = SimpleArrayField(forms.CharField()) value = field.prepare_value(['a', 'b', 'c']) self.assertEqual(value, 'a,b,c')
class MessageForm(forms.Form): body = forms.CharField(max_length=1600, strip=True, required=False) media_url = forms.CharField(strip=True, required=False) numbers = SimpleArrayField(forms.CharField(strip=True), required=True) contact_book = forms.IntegerField()
class ZakenFiltersForm(forms.Form): zaaktypen = SimpleArrayField(forms.URLField(), required=False) bronorganisaties = SimpleArrayField(forms.CharField(max_length=9), required=False) startdatum = forms.DateField(required=False)
class FingerprintForm(forms.ModelForm): "Override the default Fingerprint model form to show the fingerprint as image" fingerprint = SimpleArrayField(forms.IntegerField(), widget=FingerprintWidget)
def test_valid(self): field = SimpleArrayField(forms.CharField()) value = field.clean("a,b,c") self.assertEqual(value, ["a", "b", "c"])
def test_validate_fail(self): field = SimpleArrayField(forms.CharField(required=True)) with self.assertRaises(exceptions.ValidationError) as cm: field.clean('a,b,') self.assertEqual(cm.exception.messages[0], 'Item 2 in the array did not validate: This field is required.')
def test_delimiter(self): field = SimpleArrayField(forms.CharField(), delimiter="|") value = field.clean("a|b|c") self.assertEqual(value, ["a", "b", "c"])
def test_validators_fail(self): field = SimpleArrayField(forms.RegexField('[a-e]{2}')) with self.assertRaises(exceptions.ValidationError) as cm: field.clean('a,bc,de') self.assertEqual(cm.exception.messages[0], 'Item 0 in the array did not validate: Enter a valid value.')
def test_prepare_value(self): field = SimpleArrayField(forms.CharField()) value = field.prepare_value(["a", "b", "c"]) self.assertEqual(value, "a,b,c")
def test_min_length(self): field = SimpleArrayField(forms.CharField(), min_length=4) with self.assertRaises(exceptions.ValidationError) as cm: field.clean('a,b,c') self.assertEqual(cm.exception.messages[0], 'List contains 3 items, it should contain no fewer than 4.')
def test_has_changed(self): field = SimpleArrayField(forms.IntegerField()) self.assertIs(field.has_changed([1, 2], [1, 2]), False) self.assertIs(field.has_changed([1, 2], '1,2'), False) self.assertIs(field.has_changed([1, 2], '1,2,3'), True) self.assertIs(field.has_changed([1, 2], 'a,b'), True)
def test_already_converted_value(self): field = SimpleArrayField(forms.CharField()) vals = ['a', 'b', 'c'] self.assertEqual(field.clean(vals), vals)
def test_valid(self): field = SimpleArrayField(forms.CharField()) value = field.clean('a,b,c') self.assertEqual(value, ['a', 'b', 'c'])
class PhotoForm(forms.ModelForm): tags = SimpleArrayField(forms.CharField(), label=_("tags"), required=False) class Meta: model = Photo fields = ['title', 'image', 'tags']
class PanelSTRForm(forms.ModelForm): """ The goal for this form is to add a STR to a Panel. How this works: This form actually contains data for multiple models: STR, Evidence, Evaluation. Some of this data is duplicated, and it's not clear if it needs to stay this way or should be refactored and moved to the models where it belongs. I.e. GenePanelEntrySnapshot has moi, comments, etc. It's not clear if we need to keep it here, or move it to Evaluation model since it has the same values. When user clicks save we: 1) Get Gene data and add it to the JSONField 2) Create Comment 3) Create Evaluation 4) Create Evidence 5) Create new copy of GenePanelSnapshot, increment minor version 6) Create new GenePanelEntrySnapshot with a link to the new GenePanelSnapshot """ gene = forms.ModelChoiceField(label="Gene symbol", required=False, queryset=Gene.objects.filter(active=True), widget=ModelSelect2( url="autocomplete-gene", attrs={'data-minimum-input-length': 1})) position_37 = IntegerRangeField(require_all_fields=True, required=False) position_38 = IntegerRangeField(require_all_fields=True, required=True) gene_name = forms.CharField(required=False) source = Select2ListMultipleChoiceField( choice_list=Evidence.ALL_SOURCES, required=False, widget=Select2Multiple(url="autocomplete-source")) tags = forms.ModelMultipleChoiceField( queryset=Tag.objects.all(), required=False, widget=ModelSelect2Multiple(url="autocomplete-tags")) publications = SimpleArrayField(forms.CharField(), label="Publications (PMID: 1234;4321)", delimiter=";", required=False) phenotypes = SimpleArrayField( forms.CharField(), label="Phenotypes (separate using a semi-colon - ;)", delimiter=";", required=False) rating = forms.ChoiceField(choices=[('', 'Provide rating')] + Evaluation.RATINGS, required=False) current_diagnostic = forms.BooleanField(required=False) clinically_relevant = forms.BooleanField( label="Interruptions are clinically relevant", required=False, help_text= "Interruptions in the repeated sequence are reported as part of standard diagnostic practice" ) comments = forms.CharField(widget=forms.Textarea, required=False) class Meta: model = STR fields = ( 'name', 'chromosome', 'position_37', 'position_38', 'repeated_sequence', 'normal_repeats', 'pathogenic_repeats', 'moi', 'penetrance', 'publications', 'phenotypes', ) def __init__(self, *args, **kwargs): self.panel = kwargs.pop('panel') self.request = kwargs.pop('request') super().__init__(*args, **kwargs) original_fields = self.fields self.fields = OrderedDict() self.fields['name'] = original_fields.get('name') self.fields['chromosome'] = original_fields.get('chromosome') self.fields['position_37'] = original_fields.get('position_37') self.fields['position_37'].widget.widgets[0].attrs = { 'placeholder': 'Position start (GRCh37)' } self.fields['position_37'].widget.widgets[1].attrs = { 'placeholder': 'Position end (GRCh37)' } self.fields['position_38'] = original_fields.get('position_38') self.fields['position_38'].widget.widgets[0].attrs = { 'placeholder': 'Position start (GRCh38)' } self.fields['position_38'].widget.widgets[1].attrs = { 'placeholder': 'Position end (GRCh38)' } self.fields['repeated_sequence'] = original_fields.get( 'repeated_sequence') self.fields['normal_repeats'] = original_fields.get('normal_repeats') self.fields['pathogenic_repeats'] = original_fields.get( 'pathogenic_repeats') self.fields['gene'] = original_fields.get('gene') if self.instance.pk: self.fields['gene_name'] = original_fields.get('gene_name') self.fields['source'] = original_fields.get('source') self.fields['moi'] = original_fields.get('moi') self.fields['moi'].required = False self.fields['penetrance'] = original_fields.get('penetrance') self.fields['publications'] = original_fields.get('publications') self.fields['phenotypes'] = original_fields.get('phenotypes') if self.request.user.is_authenticated and self.request.user.reviewer.is_GEL( ): self.fields['tags'] = original_fields.get('tags') if not self.instance.pk: self.fields['rating'] = original_fields.get('rating') self.fields['current_diagnostic'] = original_fields.get( 'current_diagnostic') if self.instance.is_str(): self.fields['clinically_relevant'] = original_fields.get( 'clinically_relevant') self.fields['comments'] = original_fields.get('comments') def clean_source(self): if len(self.cleaned_data['source']) < 1: raise forms.ValidationError('Please select a source') return self.cleaned_data['source'] def clean_moi(self): if not self.cleaned_data['moi']: raise forms.ValidationError('Please select a mode of inheritance') return self.cleaned_data['moi'] def clean_repeated_sequence(self): if len( set(self.cleaned_data['repeated_sequence']).difference( {'A', 'T', 'C', 'G', 'N'})) > 0: raise forms.ValidationError( 'Repeated sequence contains incorrect nucleotides') return self.cleaned_data['repeated_sequence'] def clean_name(self): """Check if gene exists in a panel if we add a new gene or change the gene""" name = self.cleaned_data['name'] if not self.instance.pk and self.panel.has_str(name): raise forms.ValidationError( "STR has already been added to the panel", code='str_exists_in_panel', ) elif self.instance.pk and 'name' in self.changed_data \ and name != self.instance.name \ and self.panel.has_str(name): raise forms.ValidationError( "STR has already been added to the panel", code='str_exists_in_panel', ) if not self.cleaned_data.get('name'): self.cleaned_data['name'] = self.cleaned_data['name'] return self.cleaned_data['name'] def save(self, *args, **kwargs): """Don't save the original panel as we need to increment version first""" return False def save_str(self, *args, **kwargs): """Saves the gene, increments version and returns the gene back""" str_data = self.cleaned_data str_data['sources'] = str_data.pop('source') if str_data.get('comments'): str_data['comment'] = str_data.pop('comments') if self.initial: initial_name = self.initial['name'] else: initial_name = None new_str_name = str_data['name'] if self.initial and self.panel.has_str(initial_name): self.panel = self.panel.increment_version() self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel self.panel.update_str( self.request.user, initial_name, str_data, remove_gene=True if not str_data.get('gene') else False) self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel return self.panel.get_str(new_str_name) else: increment_version = self.request.user.is_authenticated and self.request.user.reviewer.is_GEL( ) str_item = self.panel.add_str(self.request.user, new_str_name, str_data, increment_version) self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel self.panel.update_saved_stats() return str_item
class Meta: model = Shop brand_service_available = SimpleArrayField(forms.CharField()) fields = ('name', 'lattitude','longitude','cover_image','image_with_Aadhar', 'address')