class TagsCreateFormField(ModelMultipleChoiceField): widget = ModelSelect2Multiple( url='tags:autocomplete', attrs={ 'data-placeholder': 'Tags..', }, )
class TagNodeForm(BaseNodeForm): tags = forms.ModelMultipleChoiceField( required=False, queryset=Tag.objects.all(), widget=ModelSelect2Multiple(url='tag_autocomplete', attrs={'data-placeholder': 'Tags...'})) class Meta: model = TagNode exclude = ANALYSIS_NODE_FIELDS widgets = { "mode": forms.RadioSelect(attrs={'class': 'horizontal-radio'}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not self.instance.visible: self.fields["mode"].widget = HiddenInput( ) # Hide in special all tags node (tags button) def save(self, commit=True): node = super().save(commit=False) # TODO: I'm sure there's a way to get Django to handle this via save_m2m() tags_set = self.instance.tagnodetag_set tags_set.all().delete() for tag in self.cleaned_data["tags"]: tags_set.create(tag=tag) if commit: node.save() return node
class PhenotypeNodeForm(BaseNodeForm): omim = forms.ModelMultipleChoiceField( required=False, queryset=OntologyTerm.objects.all(), widget=ModelSelect2Multiple(url='omim_autocomplete', attrs={'data-placeholder': 'OMIM...'})) hpo = forms.ModelMultipleChoiceField( required=False, queryset=OntologyTerm.objects.all(), widget=ModelSelect2Multiple(url='hpo_autocomplete', attrs={'data-placeholder': 'HPO...'})) class Meta: model = PhenotypeNode exclude = ANALYSIS_NODE_FIELDS widgets = { "text_phenotype": TextInput(attrs={'placeholder': 'Phenotype text'}), 'accordion_panel': HiddenInput(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['patient'].queryset = self.instance.get_patients_qs() def save(self, commit=True): node = super().save(commit=False) # TODO: I'm sure there's a way to get Django to handle this via save_m2m() ontology_term_set = self.instance.phenotypenodeontologyterm_set ontology_term_set.all().delete() for ontology_term in self.cleaned_data["omim"]: ontology_term_set.create(ontology_term=ontology_term) for ontology_term in self.cleaned_data["hpo"]: ontology_term_set.create(ontology_term=ontology_term) if commit: node.save() return node
class Meta: model = DiningList fields = [ 'owners', 'main_contact', 'dish', 'serve_time', 'min_diners', 'max_diners', 'sign_up_deadline' ] widgets = { 'owners': ModelSelect2Multiple(url='people_autocomplete', attrs={'data-minimum-input-length': '1'}), }
class Meta: model = DisplayByOptions fields = ('__all__') widgets = { 'trigger_question': ModelSelect2(url='/surveys/trigger_questions_options', forward=['shown_element']), 'options': ModelSelect2Multiple(url='/surveys/linked_options', forward=['trigger_question']) }
class PersonFilter(AMYFilterSet): badges = django_filters.ModelMultipleChoiceFilter( queryset=Badge.objects.all(), label='Badges', widget=ModelSelect2Multiple(), ) taught_workshops = django_filters.ModelMultipleChoiceFilter( queryset=Tag.objects.all(), label='Taught at workshops of type', method=filter_taught_workshops, widget=ModelSelect2Multiple(), ) order_by = NamesOrderingFilter(fields=('email', ), ) class Meta: model = Person fields = [ 'badges', 'taught_workshops', ]
class Meta: model = CommodityKeywordsRelate fields = [ 'commname',] widgets = { # 'commname': autocomplete.MultipleChoiceWidget ('CommodityKeywordAutocomplete'), 'commname': ModelSelect2Multiple(url='commoditykeyword-autocomplete',attrs={ # Set some placeholder 'data-placeholder': 'Type at least two letters ...', # Only trigger autocompletion after 3 characters have been typed 'data-minimum-input-length': 2, },) }
class UpdateSTRTagsForm(forms.ModelForm): class Meta: model = STR fields = ('tags',) tags = forms.ModelMultipleChoiceField( queryset=Tag.objects.all(), widget=ModelSelect2Multiple(url="autocomplete-tags"), required=False ) def save(self, *args, **kwargs): if 'tags' in self.changed_data: self.instance.update_tags(kwargs['user'], self.cleaned_data['tags'])
class EventFilter(AMYFilterSet): assigned_to = ForeignKeyAllValuesFilter(Person, widget=Select2()) host = ForeignKeyAllValuesFilter(Organization, widget=Select2()) administrator = ForeignKeyAllValuesFilter(Organization, widget=Select2()) STATUS_CHOICES = [ ('', 'All'), ('active', 'Active'), ('past_events', 'Past'), ('ongoing_events', 'Ongoing'), ('upcoming_events', 'Upcoming'), ('unpublished_events', 'Unpublished'), ('published_events', 'Published'), ('uninvoiced_events', 'Uninvoiced'), ('metadata_changed', 'Detected changes in metadata'), ] state = EventStateFilter(choices=STATUS_CHOICES, label='Status', widget=Select2()) invoice_status = django_filters.ChoiceFilter( choices=Event.INVOICED_CHOICES, ) tags = django_filters.ModelMultipleChoiceFilter( queryset=Tag.objects.all(), label='Tags', widget=ModelSelect2Multiple(), ) country = AllCountriesFilter(widget=Select2()) order_by = django_filters.OrderingFilter( fields=( 'slug', 'start', 'end', ), ) class Meta: model = Event fields = [ 'assigned_to', 'tags', 'host', 'administrator', 'invoice_status', 'completed', 'country', ]
class BlogPost(BasePage, PageAuthorsMixin, CanonicalMixin): parent_page_types = ['BlogPostIndexPage'] subpage_types = [] tags = ClusterTaggableManager(through=BlogTags, blank=True) search_fields = BasePage.search_fields + [ index.SearchField('tags', boost=10), ] content_panels = [ *Page.content_panels, FieldPanel('first_published_at'), FieldPanel('authors', widget=ModelSelect2Multiple(url='author-autocomplete')), StreamFieldPanel("body"), FieldPanel("tags"), ] settings_panels = CanonicalMixin.panels + BasePage.settings_panels
class BlogPost(BasePage): parent_page_types = ["BlogPostIndexPage"] subpage_types = [] authors = ParentalManyToManyField("authors.Author", blank=False, related_name="pages_%(class)s") tags = ClusterTaggableManager(through=BlogPostTag, blank=True) content_panels = [ FieldPanel("title"), FieldPanel("first_published_at"), FieldPanel("authors", widget=ModelSelect2Multiple(url="author-autocomplete")), StreamFieldPanel("body"), FieldPanel("tags"), ] def author_list(self): return (", ").join(map(lambda author: author.name, self.authors.all()))
class PanelRegionForm(forms.ModelForm): """ The goal for this form is to add a Region to a Panel. How this works: This form actually contains data for multiple models: Regopm, 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) comments = forms.CharField(widget=forms.Textarea, required=False) class Meta: model = Region fields = ( 'name', 'verbose_name', 'chromosome', 'position_37', 'position_38', 'haploinsufficiency_score', 'triplosensitivity_score', 'required_overlap_percentage', 'moi', 'penetrance', 'type_of_variants', '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['verbose_name'] = original_fields.get('verbose_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['haploinsufficiency_score'] = original_fields.get( 'haploinsufficiency_score') self.fields['triplosensitivity_score'] = original_fields.get( 'triplosensitivity_score') self.fields['required_overlap_percentage'] = original_fields.get( 'required_overlap_percentage') 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['type_of_variants'] = original_fields.get( 'type_of_variants') 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') 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_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_region(name): raise forms.ValidationError( "Region has already been added to the panel", code='region_exists_in_panel', ) elif self.instance.pk and 'name' in self.changed_data \ and name != self.instance.name \ and self.panel.has_region(name): raise forms.ValidationError( "Region has already been added to the panel", code='region_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_region(self, *args, **kwargs): """Saves the gene, increments version and returns the gene back""" region_data = self.cleaned_data region_data['sources'] = region_data.pop('source') if region_data.get('comments'): region_data['comment'] = region_data.pop('comments') if self.initial: initial_name = self.initial['name'] else: initial_name = None new_region_name = region_data['name'] if self.initial and self.panel.has_region(initial_name): self.panel = self.panel.increment_version() self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel self.panel.update_region( self.request.user, initial_name, region_data, remove_gene=True if not region_data.get('gene') else False) self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel return self.panel.get_region(new_region_name) else: increment_version = self.request.user.is_authenticated and self.request.user.reviewer.is_GEL( ) region = self.panel.add_region(self.request.user, new_region_name, region_data, increment_version) self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel self.panel.update_saved_stats() return region
class PanelGeneForm(forms.ModelForm): """The goal for this form is to add a Gene to a Panel. How this works: This form actually contains data for multiple models: GenePanelEntrySnapshot, 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, mop, 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", queryset=Gene.objects.filter(active=True), widget=ModelSelect2( url="autocomplete-gene", attrs={'data-minimum-input-length': 1})) gene_name = forms.CharField() 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 = GELSimpleArrayField(forms.CharField(), label="Publications (PMID: 1234;4321)", delimiter=";", required=False) phenotypes = GELSimpleArrayField( 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) comments = forms.CharField(widget=forms.Textarea, required=False) class Meta: model = GenePanelEntrySnapshot fields = ( 'mode_of_pathogenicity', '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['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['mode_of_pathogenicity'] = original_fields.get( 'mode_of_pathogenicity') 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') 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_gene(self): """Check if gene exists in a panel if we add a new gene or change the gene""" gene_symbol = self.cleaned_data['gene'].gene_symbol if not self.instance.pk and self.panel.has_gene(gene_symbol): raise forms.ValidationError( "Gene has already been added to the panel", code='gene_exists_in_panel', ) elif self.instance.pk and 'gene' in self.changed_data \ and gene_symbol != self.instance.gene.get('gene_symbol')\ and self.panel.has_gene(gene_symbol): raise forms.ValidationError( "Gene has already been added to the panel", code='gene_exists_in_panel', ) if not self.cleaned_data.get('gene_name'): self.cleaned_data['gene_name'] = self.cleaned_data[ 'gene'].gene_name return self.cleaned_data['gene'] def save(self, *args, **kwargs): """Don't save the original panel as we need to increment version first""" return False def save_gene(self, *args, **kwargs): """Saves the gene, increments version and returns the gene back""" gene_data = self.cleaned_data gene_data['sources'] = gene_data.pop('source') if gene_data.get('comments'): gene_data['comment'] = gene_data.pop('comments') if self.initial: initial_gene_symbol = self.initial['gene_json'].get('gene_symbol') else: initial_gene_symbol = None new_gene_symbol = gene_data.get('gene').gene_symbol if self.initial and self.panel.has_gene(initial_gene_symbol): self.panel = self.panel.increment_version() self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel self.panel.update_gene(self.request.user, initial_gene_symbol, gene_data) self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel return self.panel.get_gene(new_gene_symbol) else: increment_version = self.request.user.is_authenticated and self.request.user.reviewer.is_GEL( ) gene = self.panel.add_gene(self.request.user, new_gene_symbol, gene_data, increment_version) self.panel = GenePanel.objects.get( pk=self.panel.panel.pk).active_panel self.panel.update_saved_stats() return gene
class PanelForm(forms.ModelForm): level2 = forms.CharField(required=False) level3 = forms.CharField(required=False) level4 = forms.CharField() description = forms.CharField(widget=forms.Textarea) omim = forms.CharField(required=False) orphanet = forms.CharField(required=False) hpo = forms.CharField(required=False) status = forms.ChoiceField(required=True, choices=GenePanel.STATUS, initial=GenePanel.STATUS.internal) child_panels = forms.ModelMultipleChoiceField( label="Child Panels", required=False, queryset=GenePanelSnapshot.objects.get_active_annotated().exclude(is_super_panel=True), widget=ModelSelect2Multiple( url="autocomplete-simple-panels", attrs={'data-minimum-input-length': 3} ) ) types = forms.ModelMultipleChoiceField( label="Panel Types", required=False, queryset=PanelType.objects.all(), widget=ModelSelect2Multiple( url="autocomplete-simple-panel-types", attrs={'data-minimum-input-length': 1} ) ) class Meta: model = GenePanelSnapshot fields = ('old_panels', ) def __init__(self, *args, **kwargs): gel_curator = kwargs.pop('gel_curator') self.request = kwargs.pop('request') super().__init__(*args, **kwargs) original_fields = self.fields self.fields = OrderedDict() self.fields['level2'] = original_fields.get('level2') self.fields['level3'] = original_fields.get('level3') self.fields['level4'] = original_fields.get('level4') self.fields['description'] = original_fields.get('description') self.fields['omim'] = original_fields.get('omim') self.fields['orphanet'] = original_fields.get('orphanet') self.fields['hpo'] = original_fields.get('hpo') self.fields['old_panels'] = original_fields.get('old_panels') self.fields['types'] = original_fields.get('types') if gel_curator: # TODO (Oleg) also check if we have entities in this panel self.fields['child_panels'] = original_fields.get('child_panels') self.fields['status'] = original_fields.get('status') if self.instance.pk: self.fields['status'].initial = self.instance.panel.status if gel_curator: self.fields['child_panels'].initial = self.instance.child_panels.values_list('pk', flat=True) self.fields['types'].initial = self.instance.panel.types.values_list('pk', flat=True) def clean_level4(self): if not self.instance.pk or self.cleaned_data['level4'] != self.instance.level4title.name: if GenePanelSnapshot.objects.get_active(all=True, internal=True).exclude(panel__status=GenePanel.STATUS.deleted).filter( level4title__name=self.cleaned_data['level4']).exists(): raise forms.ValidationError('Panel with this name already exists') return self.cleaned_data['level4'] def clean_omim(self): return self._clean_array(self.cleaned_data['omim']) def clean_orphanet(self): return self._clean_array(self.cleaned_data['orphanet']) def clean_hpo(self): return self._clean_array(self.cleaned_data['hpo']) def save(self, *args, **kwargs): new_level4 = Level4Title( level2title=self.cleaned_data['level2'].strip(), level3title=self.cleaned_data['level3'].strip(), name=self.cleaned_data['level4'].strip(), description=self.cleaned_data['description'].strip(), omim=self.cleaned_data['omim'], hpo=self.cleaned_data['hpo'], orphanet=self.cleaned_data['orphanet'] ) activities = [] if self.instance.id: current_instance = GenePanelSnapshot.objects.get(pk=self.instance.id) panel = self.instance.panel level4title = self.instance.level4title data_changed = False if level4title.dict_tr() != new_level4.dict_tr(): data_changed = True new_level4.save() if level4title.name != new_level4.name: activities.append("Panel name changed from {} to {}".format( level4title.name, new_level4.name )) if level4title.hpo != new_level4.hpo: activities.append("HPO terms changed from {} to {}".format( ', '.join(level4title.hpo), ', '.join(new_level4.hpo) )) self.instance.level4title = new_level4 self.instance.panel.name = new_level4.name if 'old_panels' in self.changed_data: activities.append("List of related panels changed from {} to {}".format( "; ".join(current_instance.old_panels), "; ".join(self.cleaned_data['old_panels']) )) self.instance.old_panels = self.cleaned_data['old_panels'] if 'status' in self.changed_data: activities.append("Panel status changed from {} to {}".format( current_instance.panel.status, self.cleaned_data['status'] )) self.instance.panel.status = self.cleaned_data['status'] update_stats_superpanel = True if 'child_panels' in self.changed_data: self.instance.child_panels.set(self.cleaned_data['child_panels']) activities.append("Changed child panels to: {}".format( "; ".join(self.instance.child_panels.values_list('panel__name', flat=True)) )) update_stats_superpanel = False if 'types' in self.changed_data: panel.types.set(self.cleaned_data['types']) activities.append("Panel types changed to {}".format( "; ".join(panel.types.values_list('name', flat=True)), )) if data_changed or self.changed_data: self.instance.increment_version() panel.save() self.instance.update_saved_stats(use_db=update_stats_superpanel) else: panel.save() else: panel = GenePanel.objects.create( name=self.cleaned_data['level4'].strip(), status=self.cleaned_data['status'] ) new_level4.save() activities.append("Added Panel {}".format(panel.name)) if self.cleaned_data['old_panels']: activities.append("Set list of related panels to {}".format( "; ".join(self.cleaned_data['old_panels']))) self.instance.panel = panel self.instance.level4title = new_level4 self.instance.old_panels = self.cleaned_data['old_panels'] self.instance.save() if self.cleaned_data.get('child_panels'): self.instance.child_panels.set(self.cleaned_data['child_panels']) self.instance.major_version = max(self.instance.child_panels.values_list('major_version', flat=True)) self.instance.save(update_fields=['major_version', ]) self.instance.update_saved_stats(use_db=False) activities.append("Set child panels to: {}".format( '; '.join(list(self.instance.child_panels.values_list('panel__name', flat=True))) )) if self.cleaned_data.get('types'): panel.types.set(self.cleaned_data['types']) activities.append("Set panel types to: {}".format( '; '.join(panel.types.values_list('name', flat=True)) )) if activities: panel.add_activity(self.request.user, "\n".join(activities)) @staticmethod def _clean_array(data, separator=","): return [x.strip() for x in data.split(separator) if x.strip()]
class GeneListNodeForm(BaseNodeForm): custom_gene_list_text = forms.CharField( widget=forms.Textarea(attrs={'placeholder': 'Gene names...'}), required=False) gene_list = forms.ModelMultipleChoiceField( required=False, queryset=GeneList.objects.all(), widget=ModelSelect2Multiple(url='category_gene_list_autocomplete', attrs={'data-placeholder': 'Gene List...'}, forward=(forward.Const(None, 'category'), ))) panel_app_panel_aus = forms.ModelMultipleChoiceField( required=False, queryset=PanelAppPanel.objects.all(), widget=autocomplete.ModelSelect2Multiple( url='panel_app_panel_aus_autocomplete', attrs={ 'data-placeholder': 'Australian Genomics PanelApp panel...' })) panel_app_panel_eng = forms.ModelMultipleChoiceField( required=False, queryset=PanelAppPanel.objects.all(), widget=autocomplete.ModelSelect2Multiple( url='panel_app_panel_eng_autocomplete', attrs={'data-placeholder': 'Genomics England PanelApp panel...'})) class Meta: model = GeneListNode fields = ("pathology_test_version", "sample", "exclude", "accordion_panel") widgets = { "pathology_test_version": autocomplete.ModelSelect2( url='pathology_test_version_autocomplete', attrs={'data-placeholder': 'Pathology Test...'}, forward=(forward.Const(True, "active"), )), 'accordion_panel': HiddenInput(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) samples_queryset = Sample.objects.filter( pk__in=self.instance.get_sample_ids()) self.fields['sample'].queryset = samples_queryset def save(self, commit=True): node = super().save(commit=False) custom_gene_list_text = self.cleaned_data["custom_gene_list_text"] if custom_gene_list_text is not None: md5_hash = md5sum_str(custom_gene_list_text) if node.custom_text_gene_list: custom_text_gene_list = node.custom_text_gene_list if custom_text_gene_list.md5_hash != md5_hash: custom_text_gene_list.md5_hash = 'deleted_will_regen' if custom_text_gene_list.gene_list is not None: custom_text_gene_list.gene_list.delete() custom_text_gene_list.gene_list = None custom_text_gene_list.gene_list = None else: custom_text_gene_list = CustomTextGeneList() #logging.debug("gene_list is currently %s", custom_text_gene_list.gene_list) custom_text_gene_list.name = f"Node_{self.instance.pk}_custom" custom_text_gene_list.text = custom_gene_list_text custom_text_gene_list.save() create_custom_text_gene_list(custom_text_gene_list, self.instance.analysis.user.username, GeneListCategory.NODE_CUSTOM_TEXT, hidden=True) node.custom_text_gene_list = custom_text_gene_list # TODO: I'm sure there's a way to get Django to handle this via save_m2m() gl_set = node.genelistnodegenelist_set gl_set.all().delete() for gene_list in self.cleaned_data["gene_list"]: gl_set.create(gene_list=gene_list) # PanelAppPanel app objects are the same pap_set = node.genelistnodepanelapppanel_set pap_set.all().delete() for form_name in ["panel_app_panel_aus", "panel_app_panel_eng"]: for pap in self.cleaned_data[form_name]: pap_set.create(panel_app_panel=pap) # Make sure that if we select sample qc gene list if sample := self.cleaned_data["sample"]: node._set_sample(sample) if commit: node.save() return node