class JobViewsetFilter(FilterSet): input_image = filters.ModelMultipleChoiceFilter( field_name="inputs__image", queryset=Image.objects.all()) output_image = filters.ModelMultipleChoiceFilter( field_name="outputs__image", queryset=Image.objects.all()) class Meta: model = Job fields = ["algorithm_image__algorithm", "input_image", "output_image"]
class ClassFilter(django_filters.FilterSet): order = filters.OrderingFilter(fields=(('created_date_time', 'date time'), ('id', 'class id'), ('name', 'name'))) datetime_range = filters.DateTimeFromToRangeFilter(name='created_date_time', widget=RangeWidget) class_description = filters.CharFilter(name='description', lookup_expr='contains') creator = filters.ModelMultipleChoiceFilter(name='creator', to_field_name='id', queryset=User.objects.all()) tags = filters.MultipleChoiceFilter(name='tags') class Meta: model = models.Class fields = []
class QuestionFilter(django_filters.FilterSet): # created_date_time = filters.DateFilter(field_name='created_date_time', label='date') order = filters.OrderingFilter(fields=(('created_date_time', 'date time'), ('id', 'question id'))) datetime_range = filters.DateFromToRangeFilter(name='created_date_time', widget=RangeWidget) tags = filters.AllValuesMultipleFilter(name='tags') creator = filters.ModelMultipleChoiceFilter(name='creator', to_field_name='id', queryset=User.objects.all()) content = filters.CharFilter(name='content_description', lookup_expr='contains') class Meta: model = models.Question fields = []
class ExportLineFilter(ExportFilter): """ FilterSet used to select lines used in an Export, for reporting. See <main.export.table.ExportSelection>. """ # overriding to lookup based on Line instead of MeasurementValue line_id = django_filters.ModelMultipleChoiceFilter( field_name="id", help_text=_( "List of ID values, separated by commas, for lines to export"), lookup_expr="in", queryset=export_queryset(models.Line), ) # overriding to lookup based on Line instead of MeasurementValue assay_id = django_filters.ModelMultipleChoiceFilter( field_name="assay", help_text=_( "List of ID values, separated by commas, for assays to export"), lookup_expr="in", queryset=export_queryset(models.Assay), ) # overriding to lookup based on Line instead of MeasurementValue measure_id = django_filters.ModelMultipleChoiceFilter( field_name="assay__measurement", help_text=_( "List of ID values, separated by commas, for measurements to export" ), lookup_expr="in", queryset=export_queryset(models.Measurement), ) class Meta: model = models.Line fields = [] def filter_queryset(self, queryset): return self._filter_ids_and_in_study(queryset)
class EventFilterSet(django_filters.FilterSet): calendars = filters.ModelMultipleChoiceFilter( field_name="calendars", queryset=Calendar.objects.all(), label="Calendriers") date = filters.DateFromToRangeFilter(field_name="start_time", lookup_expr="range", label="Entre les dates") subtype = django_filters.filterset.ModelMultipleChoiceFilter( queryset=EventSubtype.objects.all()) class Meta: model = Event fields = ["visibility"]
class ApplicationFilter(django_filters.FilterSet): name = filters.CharFilter(lookup_type='icontains') organization = filters.ModelMultipleChoiceFilter( queryset=Organization.objects.all()) business_criticality = filters.MultipleChoiceFilter( choices=Application.BUSINESS_CRITICALITY_CHOICES) platform = filters.MultipleChoiceFilter( choices=Application.PLATFORM_CHOICES) lifecycle = filters.MultipleChoiceFilter( choices=Application.LIFECYCLE_CHOICES) origin = filters.MultipleChoiceFilter(choices=Application.ORIGIN_CHOICES) asvs_level = filters.MultipleChoiceFilter(choices=Application.ASVS_CHOICES) class Meta: model = Application fields = [ 'name', 'organization', 'business_criticality', 'platform', 'lifecycle', 'origin', 'external_audience', 'internet_accessible', 'technologies', 'regulations', 'service_level_agreements', 'tags', 'asvs_level' ]
class ExportFilter(filters.FilterSet): """ FilterSet used to select data for exporting. See <main.export.table.ExportSelection>. """ study_id = django_filters.ModelMultipleChoiceFilter( lookup_expr="in", field_name="study", queryset=export_queryset(models.Study)) line_id = django_filters.ModelMultipleChoiceFilter( lookup_expr="in", field_name="measurement__assay__line", queryset=export_queryset(models.Line), ) assay_id = django_filters.ModelMultipleChoiceFilter( lookup_expr="in", field_name="measurement__assay", queryset=export_queryset(models.Assay), ) measure_id = django_filters.ModelMultipleChoiceFilter( lookup_expr="in", field_name="measurement_id", queryset=export_queryset(models.Measurement), ) class Meta: model = models.MeasurementValue fields = [] @property def qs(self): if not hasattr(self, "_qs"): # define filters for special handling names = ["study_id", "line_id", "assay_id", "measure_id"] special = {name: self.filters.get(name, None) for name in names} fields = {name: f.field for name, f in special.items()} # create a custom form for the filters with special handling form = self._custom_form(fields) if not form.is_valid(): return self.queryset.none() # now do special handling to OR together the filters id_filter = Q() for name, filter_ in special.items(): if filter_ is not None: # when a value is found, OR together with others value = form.cleaned_data.get(name) if value: id_filter |= Q(**{ f"{filter_.field_name}__{filter_.lookup_expr}": value }) self._qs = self.queryset.filter( id_filter, study__active=True, measurement__active=True, measurement__assay__active=True, measurement__assay__line__active=True, ) # add in annotations to get formal type IDs self._qs = self._add_formal_type_ids(self._qs) # filter with the aggregated filter expression return self._qs def _add_formal_type_ids(self, qs): # define the integer pubchem_cid field as CharField cast = Cast( "measurement__measurement_type__metabolite__pubchem_cid", output_field=CharField(), ) prefix = Value("cid:", output_field=CharField()) # instruct database to give PubChem ID in the cid:N format, or None qs = qs.annotate(anno_pubchem=NullIf(Concat(prefix, cast), prefix)) # grab formal type IDs if able, otherwise empty string qs = qs.annotate(anno_formal_type=Coalesce( "anno_pubchem", "measurement__measurement_type__proteinidentifier__accession_id", Value("", output_field=CharField()), output_field=CharField(), )) return qs def _custom_form(self, fields): # create a custom form for the filters with special handling Form = type(f"{self.__class__.__name__}IDForm", (self._meta.form, ), fields) if self.is_bound: form = Form(self.data, prefix=self.form_prefix) else: form = Form(prefix=self.form_prefix) return form
class EducationGroupFilter(FilterSet): academic_year = filters.ModelChoiceFilter( queryset=AcademicYear.objects.all(), required=False, label=_('Ac yr.'), empty_label=pgettext_lazy("plural", "All"), ) category = filters.ChoiceFilter( choices=list(Categories.choices()), required=False, label=_('Category'), field_name='education_group_type__category', empty_label=pgettext_lazy("plural", "All")) education_group_type = filters.ModelMultipleChoiceFilter( queryset=EducationGroupType.objects.none(), required=False, label=_('Type'), widget=autocomplete.ModelSelect2Multiple( url='education_group_type_autocomplete', forward=['category'], ), ) management_entity = filters.CharFilter( method='filter_with_entity_subordinated', label=_('Entity')) with_entity_subordinated = filters.BooleanFilter( method=lambda queryset, *args, **kwargs: queryset, label=_('Include subordinate entities'), widget=forms.CheckboxInput) acronym = filters.CharFilter( field_name="acronym", method="filter_education_group_year_field", max_length=40, required=False, label=_('Acronym/Short title'), ) title = filters.CharFilter(field_name="title", method='filter_education_group_year_field', max_length=255, required=False, label=_('Title')) partial_acronym = filters.CharFilter( field_name="partial_acronym", method='filter_education_group_year_field', max_length=15, required=False, label=_('Code'), ) order_by_field = 'ordering' ordering = OrderingFilter( fields=(('acronym', 'acronym'), ('partial_acronym', 'code'), ('academic_year__year', 'academic_year'), ('title', 'title'), ('type_ordering', 'type'), ('entity_management_version', 'management_entity')), widget=forms.HiddenInput) class Meta: model = EducationGroupYear fields = [ 'acronym', 'partial_acronym', 'title', 'education_group_type__name', 'management_entity', 'with_entity_subordinated', ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.queryset = self.get_queryset() self.form.fields[ 'education_group_type'].queryset = EducationGroupType.objects.all( ).order_by_translated_name() self.form.fields['academic_year'].initial = starting_academic_year() self.form.fields[ 'category'].initial = education_group_categories.TRAINING self.form.fields["with_entity_subordinated"].initial = kwargs.pop( 'with_entity_subordinated', True) def filter_with_entity_subordinated(self, queryset, name, value): with_subordinated = self.form.cleaned_data['with_entity_subordinated'] if value: entity_ids = get_entities_ids(value, with_subordinated) queryset = queryset.filter(management_entity__in=entity_ids) return queryset @staticmethod def filter_education_group_year_field(queryset, name, value): return filter_field_by_regex(queryset, name, value) def get_queryset(self): # Need this close so as to return empty query by default when form is unbound if not self.data: return EducationGroupYear.objects.none() management_entity = entity_version.EntityVersion.objects.filter( entity=OuterRef('management_entity'), ).current( OuterRef('academic_year__start_date')).values('acronym')[:1] return EducationGroupYear.objects.all().annotate(type_ordering=Case( *[ When(education_group_type__name=key, then=Value(str(_(val)))) for i, (key, val) in enumerate(education_group_types.ALL_TYPES) ], default=Value(''), output_field=CharField())).annotate( entity_management_version=Subquery(management_entity)) def filter_queryset(self, queryset): # Order by id to always ensure same order when objects have same values for order field (ex: title) qs = super().filter_queryset(queryset) order_fields = qs.query.order_by + ('id', ) return qs.order_by(*order_fields)
class GenomeFilter(django_filters.FilterSet): length__gte = django_filters.NumberFilter( field_name="length", lookup_expr="gte", help_text="Length (bp) greater/equal value", ) length__lte = django_filters.NumberFilter( field_name="length", lookup_expr="lte", help_text="Length (bp) less/equal value") num_contigs__gte = django_filters.NumberFilter( field_name="num_contigs", label="Number of contigs", lookup_expr="gte", help_text="Number of contigs greater/equal value", ) num_contigs__lte = django_filters.NumberFilter( field_name="num_contigs", label="Number of contigs", lookup_expr="lte", help_text="Number of contigs greater/equal value", ) n_50__gte = django_filters.NumberFilter( field_name="n_50", label="N50", lookup_expr="gte", help_text="N50 greater/equal value", ) n_50__lte = django_filters.NumberFilter( field_name="n_50", label="N50", lookup_expr="lte", help_text="N50 less/equal value", ) gc_content__gte = django_filters.NumberFilter( field_name="gc_content", label="GC%", lookup_expr="gte", help_text="GC% greater/equal value", ) gc_content__lte = django_filters.NumberFilter( field_name="gc_content", label="GC%", lookup_expr="lte", help_text="GC% less/equal value", ) completeness__gte = django_filters.NumberFilter( field_name="completeness", label="Completeness", lookup_expr="gte", help_text="Completeness greater/equal value", ) completeness__lte = django_filters.NumberFilter( field_name="completeness", label="Completeness", lookup_expr="lte", help_text="Completeness less/equal value", ) # TODO: use Range instead contamination__gte = django_filters.NumberFilter( field_name="contamination", label="Contamination", lookup_expr="gte", help_text="Contamination greater/equal value", ) contamination__lte = django_filters.NumberFilter( field_name="contamination", label="Contamination", lookup_expr="lte", help_text="Contamination less/equal value", ) num_proteins__gte = django_filters.NumberFilter( field_name="num_proteins", label="Number of proteins", lookup_expr="gte", help_text="Number of proteins greater/equal value", ) num_proteins__lte = django_filters.NumberFilter( field_name="num_proteins", label="Number of proteins", lookup_expr="lte", help_text="Number of proteins less/equal value", ) cmseq__gte = django_filters.NumberFilter( field_name="cmseq", label="Strain heterogeneity (CMseq)", lookup_expr="gte", help_text="Strain heterogeneity (CMseq) greater/equal value", ) cmseq__lte = django_filters.NumberFilter( field_name="cmseq", label="Strain heterogeneity (CMseq)", lookup_expr="lte", help_text="Strain heterogeneity (CMseq) less/equal value", ) num_genomes_total__gte = django_filters.NumberFilter( field_name="num_genomes_total", label="Total number of genomes in species", lookup_expr="gte", help_text="Total number of genomes in species greater/equal value", ) num_genomes_total__lte = django_filters.NumberFilter( field_name="num_genomes_total", label="Total number of genomes in species", lookup_expr="lte", help_text="Total number of genomes in species less/equal value", ) num_genomes_non_redundant__gte = django_filters.NumberFilter( field_name="num_genomes_non_redundant", label="Non-redundant number of genomes in species", lookup_expr="gte", help_text= "Non-redundant number of genomes in species greater/equal value", ) num_genomes_non_redundant__lte = django_filters.NumberFilter( field_name="num_genomes_non_redundant", label="Non-redundant number of genomes in species", lookup_expr="gte", help_text= "Non-redundant number of genomes in species greater/equal value", ) pangenome_size__gte = django_filters.NumberFilter( field_name="pangenome_size", label="Pan-genome size", lookup_expr="gte", help_text="Pan-genome size greater/equal value", ) pangenome_size__lte = django_filters.NumberFilter( field_name="pangenome_size", label="Pan-genome size", lookup_expr="lte", help_text="Pan-genome size less/equal value", ) pangenome_core_size__gte = django_filters.NumberFilter( field_name="pangenome_core_size", label="Pan-genome core size", lookup_expr="gte", help_text="Pan-genome core size greater/equal value", ) pangenome_core___lte = django_filters.NumberFilter( field_name="pangenome_core_size", label="Pan-genome core size", lookup_expr="lte", help_text="Pan-genome core size less/equal value", ) pangenome_accessory_size__gte = django_filters.NumberFilter( field_name="pangenome_accessory_size", label="Pan-genome core size", lookup_expr="gte", help_text="Pan-genome accessory size greater/equal value", ) pangenome_accessory_size__lte = django_filters.NumberFilter( field_name="pangenome_accessory_size", label="Pan-genome core size", lookup_expr="lte", help_text="Pan-genome accessory size less/equal value", ) accession = filters.ModelMultipleChoiceFilter( queryset=emg_models.Genome.objects, to_field_name="accession", method="filter_accession", distinct=True, label="Accession", help_text="Select by MGnify, NCBI, IMG or Patric accession", widget=QueryArrayWidget, ) def filter_accession(self, qs, name, values): """Filter by any accession: - MGnify accession - ENA genome, sample or study accession - NCBI genome, sample or study accession - IMG genome accession - PATRIC genome accesssion """ if values: qs = qs.filter( Q(accession__in=values) | Q(ena_genome_accession__in=values) | Q(ena_sample_accession__in=values) | Q(ena_study_accession__in=values) | Q(ncbi_genome_accession__in=values) | Q(ncbi_sample_accession__in=values) | Q(ncbi_study_accession__in=values) | Q(img_genome_accession__in=values) | Q(patric_genome_accession__in=values)) return qs taxon_lineage = django_filters.CharFilter( field_name="taxon_lineage", lookup_expr="contains", help_text="Taxon lineage", label="Taxon lineage", ) mag_type = django_filters.ChoiceFilter( field_name="type", help_text="MAG or isolate", label="Type", choices=emg_models.Genome.TYPE_CHOICES) geo_origin = django_filters.filters.ModelMultipleChoiceFilter( field_name="geo_origin__name", to_field_name="name", queryset=emg_models.GeographicLocation.objects.all(), ) pangenome_geographic_range = django_filters.filters.ModelMultipleChoiceFilter( field_name="pangenome_geographic_range__name", to_field_name="name", queryset=emg_models.GeographicLocation.objects.all(), ) class Meta: model = emg_models.Genome fields = ( "accession", "taxon_lineage", "mag_type", "geo_origin", "pangenome_geographic_range", "length__gte", "length__lte", "num_contigs__gte", "num_contigs__lte", "n_50__gte", "n_50__lte", "gc_content__gte", "gc_content__lte", "completeness__gte", "completeness__lte", "contamination__gte", "contamination__lte", "num_proteins__gte", "num_proteins__lte", "cmseq__gte", "cmseq__lte", "num_genomes_total__gte", "num_genomes_total__lte", "pangenome_size__gte", "pangenome_size__lte", "pangenome_accessory_size__gte", "pangenome_accessory_size__lte", )
class AssemblyFilter(django_filters.FilterSet): accession = filters.ModelMultipleChoiceFilter( queryset=emg_models.Assembly.objects, to_field_name='accession', method='filter_accession', distinct=True, label='Assembly accession', help_text='Assembly accession', widget=QueryArrayWidget) def filter_accession(self, qs, name, values): if values: qs = qs.available(self.request).filter( Q(accession__in=values) | Q(wgs_accession__in=values) | Q(legacy_accession__in=values)) return qs biome_name = django_filters.CharFilter(method='filter_biome_name', distinct=True, label='Biome name', help_text='Biome name') def filter_biome_name(self, qs, name, value): return qs.filter( samples__lineage__iregex=WORD_MATCH_REGEX.format(value)) lineage = filters.ModelChoiceFilter( queryset=emg_models.Biome.objects.all(), method='filter_lineage', distinct=True, to_field_name='lineage', label='Biome lineage', help_text='Biome lineage') def filter_lineage(self, qs, name, value): try: b = emg_models.Biome.objects.get(lineage=value) qs = qs.filter(samples__biome__lft__gte=b.lft, samples__biome__rgt__lte=b.rgt) except emg_models.Biome.DoesNotExist: pass return qs species = django_filters.CharFilter(method='filter_species', distinct=True, label='Species', help_text='Species') def filter_species(self, qs, name, value): return qs.filter( samples__species__iregex=WORD_MATCH_REGEX.format(value)) metadata_key = filters.ChoiceFilter(choices=metadata_keywords, method='filter_metadata_key', field_name='metadata_key', distinct=True, label='Metadata keyword', help_text='Metadata keyword') def filter_metadata_key(self, qs, name, value): m = emg_models.VariableNames.objects.filter(var_name=value) return qs.filter(samples__metadata__var__in=m) metadata_value_gte = django_filters.NumberFilter( method='filter_metadata_value_gte', distinct=True, label='Metadata greater/equal then value', help_text='Metadata greater/equal then value') def filter_metadata_value_gte(self, qs, name, value): return qs.annotate( float_value=Cast('samples__metadata__var_val_ucv', FloatField())) \ .filter(float_value__gte=float(value)) metadata_value_lte = django_filters.NumberFilter( method='filter_metadata_value_lte', distinct=True, label='Metadata less/equal then value', help_text='Metadata less/equal then value') def filter_metadata_value_lte(self, qs, name, value): return qs.annotate( float_value=Cast('samples__metadata__var_val_ucv', FloatField())) \ .filter(float_value__lte=float(value)) metadata_value = django_filters.CharFilter( method='filter_metadata_value', distinct=True, label='Metadata value', help_text='Metadata exact value') def filter_metadata_value(self, qs, name, value): return qs.filter(samples__metadata__var_val_ucv=value) sample_accession = django_filters.CharFilter( method='filter_sample_accession', distinct=True, label='Sample accession', help_text='Sample accession') def filter_sample_accession(self, qs, name, value): return qs.filter(samples__accession=value) run_accession = django_filters.CharFilter(method='filter_run_accession', distinct=True, label='Run accession', help_text='Run accession') def filter_runs_accession(self, qs, name, value): return qs.filter(runs__accession=value) # include include = django_filters.CharFilter( method='filter_include', distinct=True, label='Include', help_text=('Include related sample in the same response.')) def filter_include(self, qs, name, value): return qs class Meta: model = emg_models.Assembly fields = ( 'accession', 'biome_name', 'lineage', 'species', 'metadata_key', 'metadata_value_gte', 'metadata_value_lte', 'metadata_value', 'sample_accession', 'include', )
class RunFilter(django_filters.FilterSet): accession = filters.ModelMultipleChoiceFilter( queryset=emg_models.Run.objects, to_field_name='accession', method='filter_accession', distinct=True, label='Run accession', help_text='Run accession', widget=QueryArrayWidget) def filter_accession(self, qs, name, values): if values: qs = qs.available(self.request).filter(accession__in=values) return qs experiment_type = filters.ModelMultipleChoiceFilter( queryset=emg_models.ExperimentType.objects, to_field_name='experiment_type', field_name='experiment_type__experiment_type', distinct=True, label='Experiment type', help_text='Experiment type', widget=QueryArrayWidget) biome_name = django_filters.CharFilter(method='filter_biome_name', distinct=True, label='Biome name', help_text='Biome name') def filter_biome_name(self, qs, name, value): return qs.filter( sample__biome__lineage__iregex=WORD_MATCH_REGEX.format(value)) lineage = filters.ModelChoiceFilter( queryset=emg_models.Biome.objects.all(), method='filter_lineage', distinct=True, to_field_name='lineage', label='Biome lineage', help_text='Biome lineage') def filter_lineage(self, qs, name, value): try: b = emg_models.Biome.objects.get(lineage=value) qs = qs.filter(sample__biome__lft__gte=b.lft, sample__biome__rgt__lte=b.rgt) except emg_models.Biome.DoesNotExist: pass return qs species = django_filters.CharFilter(method='filter_species', distinct=True, label='Species', help_text='Species') def filter_species(self, qs, name, value): return qs.filter( sample__species__iregex=WORD_MATCH_REGEX.format(value)) instrument_platform = django_filters.CharFilter( method='filter_instrument_platform', distinct=True, label='Instrument platform', help_text='Instrument platform') def filter_instrument_platform(self, qs, name, value): return qs.filter( instrument_platform__iregex=WORD_MATCH_REGEX.format(value)) instrument_model = django_filters.CharFilter( method='filter_instrument_model', distinct=True, label='Instrument model', help_text='Instrument model') def filter_instrument_model(self, qs, name, value): return qs.filter( instrument_model__iregex=WORD_MATCH_REGEX.format(value)) metadata_key = filters.ChoiceFilter(choices=metadata_keywords, method='filter_metadata_key', field_name='metadata_key', distinct=True, label='Metadata keyword', help_text='Metadata keyword') def filter_metadata_key(self, qs, name, value): m = emg_models.VariableNames.objects.filter(var_name=value) return qs.filter(sample__metadata__var__in=m) metadata_value_gte = django_filters.NumberFilter( method='filter_metadata_value_gte', distinct=True, label='Metadata greater/equal then value', help_text='Metadata greater/equal then value') def filter_metadata_value_gte(self, qs, name, value): return qs.annotate( float_value=Cast('sample__metadata__var_val_ucv', FloatField())) \ .filter(float_value__gte=float(value)) metadata_value_lte = django_filters.NumberFilter( method='filter_metadata_value_lte', distinct=True, label='Metadata less/equal then value', help_text='Metadata less/equal then value') def filter_metadata_value_lte(self, qs, name, value): return qs.annotate( float_value=Cast('sample__metadata__var_val_ucv', FloatField())) \ .filter(float_value__lte=float(value)) metadata_value = django_filters.CharFilter( method='filter_metadata_value', distinct=True, label='Metadata value', help_text='Metadata exact value') def filter_metadata_value(self, qs, name, value): return qs.filter(sample__metadata__var_val_ucv=value) sample_accession = django_filters.CharFilter( method='filter_sample_accession', distinct=True, label='Sample accession', help_text='Sample accession') def filter_sample_accession(self, qs, name, value): return qs.filter(sample__accession=value) study_accession = django_filters.CharFilter( method='filter_study_accession', distinct=True, label='Study, ENA or BioProject accession', help_text='Study, ENA or BioProject accession') def filter_study_accession(self, qs, name, value): return qs.filter(*emg_utils.related_study_accession_query(value)) # include include = django_filters.CharFilter( method='filter_include', distinct=True, label='Include', help_text=('Include related sample in the same response.')) def filter_include(self, qs, name, value): return qs class Meta: model = emg_models.Run fields = ( 'accession', 'experiment_type', 'biome_name', 'lineage', 'species', 'instrument_platform', 'instrument_model', 'metadata_key', 'metadata_value_gte', 'metadata_value_lte', 'metadata_value', 'sample_accession', 'study_accession', 'include', )
class SampleFilter(django_filters.FilterSet): accession = filters.ModelMultipleChoiceFilter( queryset=emg_models.Sample.objects, to_field_name='accession', method='filter_accession', distinct=True, label='Sample accession', help_text='Sample accession', widget=QueryArrayWidget) def filter_accession(self, qs, name, values): if values: qs = qs.available(self.request).filter(accession__in=values) return qs experiment_type = filters.ModelMultipleChoiceFilter( queryset=emg_models.ExperimentType.objects, to_field_name='experiment_type', method='filter_experiment_type', distinct=True, label='Experiment type', help_text='Experiment type', widget=QueryArrayWidget) def filter_experiment_type(self, qs, name, values): analyses = emg_models.AnalysisJob.objects \ .filter(experiment_type__in=values) \ .values('sample') if len(analyses) > 0: qs = qs.filter(pk__in=analyses) return qs biome_name = django_filters.CharFilter(method='filter_biome_name', distinct=True, label='Biome name', help_text='Biome name') def filter_biome_name(self, qs, name, value): return qs.filter(biome__lineage__iregex=WORD_MATCH_REGEX.format(value)) lineage = filters.ModelChoiceFilter( queryset=emg_models.Biome.objects.all(), method='filter_lineage', distinct=True, to_field_name='lineage', label='Biome lineage', help_text='Biome lineage') def filter_lineage(self, qs, name, value): try: b = emg_models.Biome.objects.get(lineage=value) qs = qs.filter(biome__lft__gte=b.lft, biome__rgt__lte=b.rgt) except emg_models.Biome.DoesNotExist: pass return qs instrument_platform = django_filters.CharFilter( method='filter_instrument_platform', distinct=True, label='Instrument platform', help_text='Instrument platform') def filter_instrument_platform(self, qs, name, value): samples = emg_models.Run.objects.values('sample_id') \ .available(self.request) \ .filter(instrument_platform__iregex=WORD_MATCH_REGEX.format(value)) return qs.filter(pk__in=samples) instrument_model = django_filters.CharFilter( method='filter_instrument_model', distinct=True, label='Instrument model', help_text='Instrument model') def filter_instrument_model(self, qs, name, value): samples = emg_models.Run.objects.values('sample_id') \ .available(self.request) \ .filter(instrument_model__iregex=WORD_MATCH_REGEX.format(value)) return qs.filter(pk__in=samples) metadata_key = filters.ChoiceFilter(choices=metadata_keywords, method='filter_metadata_key', field_name='metadata_key', distinct=True, label='Metadata keyword', help_text='Metadata keyword') def filter_metadata_key(self, qs, name, value): m = emg_models.VariableNames.objects.filter(var_name=value) return qs.filter(metadata__var__in=m) metadata_value_gte = django_filters.NumberFilter( method='filter_metadata_value_gte', distinct=True, label='Metadata greater/equal then value', help_text='Metadata greater/equal then value') def filter_metadata_value_gte(self, qs, name, value): return qs.filter(metadata__var_val_ucv__iregex=FLOAT_MATCH_REGEX) \ .annotate(float_value=Cast( 'metadata__var_val_ucv', FloatField())) \ .filter(float_value__gte=float(value)) metadata_value_lte = django_filters.NumberFilter( method='filter_metadata_value_lte', distinct=True, label='Metadata less/equal then value', help_text='Metadata less/equal then value') def filter_metadata_value_lte(self, qs, name, value): return qs.filter(metadata__var_val_ucv__iregex=FLOAT_MATCH_REGEX) \ .annotate(float_value=Cast( 'metadata__var_val_ucv', FloatField())) \ .filter(float_value__lte=float(value)) metadata_value = django_filters.CharFilter( method='filter_metadata_value', distinct=True, label='Metadata value', help_text='Metadata exact value') def filter_metadata_value(self, qs, name, value): return qs.filter(metadata__var_val_ucv__iregex=FLOAT_MATCH_REGEX) \ .filter(metadata__var_val_ucv=value) species = django_filters.CharFilter(method='filter_species', distinct=True, label='Species', help_text='Species') def filter_species(self, qs, name, value): return qs.filter(species__iregex=WORD_MATCH_REGEX.format(value)) geo_loc_name = django_filters.CharFilter( method='filter_geo_loc_name', distinct=True, label='Geological location name', help_text='Geological location name') def filter_geo_loc_name(self, qs, name, value): return qs.filter(geo_loc_name__iregex=WORD_MATCH_REGEX.format(value)) latitude_gte = django_filters.NumberFilter( method='filter_latitude_gte', distinct=True, label='Latitude greater/equal then value', help_text='Latitude greater/equal then value') def filter_latitude_gte(self, qs, name, value): return qs.filter(latitude__gte=Decimal(str(value))) latitude_lte = django_filters.NumberFilter( method='filter_latitude_lte', distinct=True, label='Latitude less/equal then value', help_text='Latitude less/equal then value') def filter_latitude_lte(self, qs, name, value): return qs.filter(latitude__lte=Decimal(str(value))) longitude_gte = django_filters.NumberFilter( method='filter_longitude_gte', distinct=True, label='Longitude greater/equal then value', help_text='Longitude greater/equal then value') def filter_longitude_gte(self, qs, name, value): return qs.filter(longitude__gte=Decimal(str(value))) longitude_lte = django_filters.NumberFilter( method='filter_longitude_lte', distinct=True, label='Longitude less/equal then value', help_text='Longitude less/equal then value') def filter_longitude_lte(self, qs, name, value): return qs.filter(longitude__lte=Decimal(str(value))) study_accession = django_filters.CharFilter( method='filter_study_accession', distinct=True, label='Study, ENA or BioProject accession', help_text='Study, ENA or BioProject accession') def filter_study_accession(self, qs, name, value): return qs.filter(*emg_utils.sample_study_accession_query(value)) # include include = django_filters.CharFilter( method='filter_include', distinct=True, label='Include', help_text=('Include related run, metadata and/or biome in the same ' 'response.')) def filter_include(self, qs, name, value): return qs class Meta: model = emg_models.Sample fields = ( 'accession', 'experiment_type', 'biome_name', 'lineage', 'geo_loc_name', 'latitude_gte', 'latitude_lte', 'longitude_gte', 'longitude_lte', 'species', 'instrument_model', 'instrument_platform', 'metadata_key', 'metadata_value_gte', 'metadata_value_lte', 'metadata_value', 'environment_material', 'environment_feature', 'study_accession', 'include', )
class EducationGroupFilter(FilterSet): academic_year = filters.ModelChoiceFilter( queryset=AcademicYear.objects.all(), required=False, empty_label=pgettext_lazy("plural", "All"), label=_('Ac yr.')) category = filters.ChoiceFilter( choices=list(Categories.choices()), required=False, label=_('Category'), field_name='education_group_type__category', empty_label=pgettext_lazy("plural", "All")) education_group_type = filters.ModelMultipleChoiceFilter( queryset=EducationGroupType.objects.none(), required=False, label=_('Type'), widget=autocomplete.ModelSelect2Multiple( url='education_group_type_autocomplete', forward=['category'], ), ) management_entity = filters.CharFilter( method='filter_with_entity_subordinated', label=_('Entity')) with_entity_subordinated = filters.BooleanFilter( method=lambda queryset, *args, **kwargs: queryset, label=_('Include subordinate entities'), widget=forms.CheckboxInput) acronym = filters.CharFilter( field_name="acronym", lookup_expr='icontains', max_length=40, required=False, label=_('Acronym/Short title'), ) title = filters.CharFilter(field_name="title", lookup_expr='icontains', max_length=255, required=False, label=_('Title')) partial_acronym = filters.CharFilter( field_name="partial_acronym", lookup_expr='icontains', max_length=15, required=False, label=_('Code'), ) order_by_field = 'ordering' ordering = OrderingFilter( fields=(('acronym', 'acronym'), ('partial_acronym', 'code'), ('academic_year__year', 'academic_year'), ('title', 'title'), ('education_group_type__name', 'type'), ('management_entity__entityversion__acronym', 'management_entity')), widget=forms.HiddenInput) class Meta: model = EducationGroupYear fields = [ 'acronym', 'partial_acronym', 'title', 'education_group_type__name', 'management_entity', 'with_entity_subordinated', ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form.fields[ 'education_group_type'].queryset = EducationGroupType.objects.all( ).order_by_translated_name() self.form.fields['academic_year'].initial = starting_academic_year() self.form.fields[ 'category'].initial = education_group_categories.TRAINING self.form.fields["with_entity_subordinated"].initial = kwargs.pop( 'with_entity_subordinated', True) def filter_with_entity_subordinated(self, queryset, name, value): with_subordinated = self.form.cleaned_data['with_entity_subordinated'] if value: entity_ids = get_entities_ids(value, with_subordinated) queryset = queryset.filter(management_entity__in=entity_ids) return queryset
class ExportFilter(filters.FilterSet): """ FilterSet used to select data for exporting. See <main.export.table.ExportSelection>. """ study_id = django_filters.ModelMultipleChoiceFilter( lookup_expr='in', name='study', queryset=export_queryset(models.Study), ) line_id = django_filters.ModelMultipleChoiceFilter( lookup_expr='in', name='measurement__assay__line', queryset=export_queryset(models.Line), ) assay_id = django_filters.ModelMultipleChoiceFilter( lookup_expr='in', name='measurement__assay', queryset=export_queryset(models.Assay), ) measure_id = django_filters.ModelMultipleChoiceFilter( lookup_expr='in', name='measurement_id', queryset=export_queryset(models.Measurement), ) class Meta: model = models.MeasurementValue fields = [] @property def qs(self): if not hasattr(self, '_qs'): # define filters for special handling names = ['study_id', 'line_id', 'assay_id', 'measure_id'] special = {name: self.filters.get(name, None) for name in names} fields = {name: f.field for name, f in special.items()} # create a custom form for the filters with special handling form = self._custom_form(fields) if not form.is_valid(): return self.queryset.none() # now do special handling to OR together the filters id_filter = Q() for name, filter_ in special.items(): if filter_ is not None: # when a value is found, OR together with others value = form.cleaned_data.get(name) if value: id_filter |= Q(**{ f'{filter_.field_name}__{filter_.lookup_expr}': value }) self._qs = self.queryset.filter( id_filter, study__active=True, measurement__active=True, measurement__assay__active=True, measurement__assay__line__active=True, ) # filter with the aggregated filter expression return self._qs def _custom_form(self, fields): # create a custom form for the filters with special handling Form = type(f'{self.__class__.__name__}IDForm', (self._meta.form, ), fields) if self.is_bound: form = Form(self.data, prefix=self.form_prefix) else: form = Form(prefix=self.form_prefix) return form
class ExportFilter(filters.FilterSet): """ FilterSet used to select data for exporting. See <main.export.table.ExportSelection>. """ in_study = django_filters.CharFilter( field_name="study", help_text=_("An identifier for the study; can use ID, UUID, or Slug"), method=filter_in_study, ) study_id = django_filters.ModelMultipleChoiceFilter( field_name="study", help_text=_( "List of ID values, separated by commas, for studies to export"), lookup_expr="in", queryset=export_queryset(models.Study), ) line_id = django_filters.ModelMultipleChoiceFilter( field_name="measurement__assay__line", help_text=_( "List of ID values, separated by commas, for lines to export"), lookup_expr="in", queryset=export_queryset(models.Line), ) assay_id = django_filters.ModelMultipleChoiceFilter( field_name="measurement__assay", help_text=_( "List of ID values, separated by commas, for assays to export"), lookup_expr="in", queryset=export_queryset(models.Assay), ) measure_id = django_filters.ModelMultipleChoiceFilter( field_name="measurement_id", help_text=_( "List of ID values, separated by commas, for measurements to export" ), lookup_expr="in", queryset=export_queryset(models.Measurement), ) class Meta: model = models.MeasurementValue fields = [] def filter_queryset(self, queryset): queryset = self._filter_ids_and_in_study(queryset) queryset = self._add_formal_type_ids(queryset) queryset = self._add_replicate_id(queryset) return queryset def _add_formal_type_ids(self, qs): # define the integer pubchem_cid field as CharField cast = Cast( "measurement__measurement_type__metabolite__pubchem_cid", output_field=CharField(), ) prefix = Value("cid:", output_field=CharField()) # instruct database to give PubChem ID in the cid:N format, or None qs = qs.annotate(anno_pubchem=NullIf(Concat(prefix, cast), prefix)) # grab formal type IDs if able, otherwise empty string qs = qs.annotate(anno_formal_type=Coalesce( "anno_pubchem", "measurement__measurement_type__proteinidentifier__accession_id", Value("", output_field=CharField()), output_field=CharField(), )) return qs def _add_replicate_id(self, qs): replicate_type = models.MetadataType.system("Replicate") replicate = Func( F("measurement__assay__line__metadata"), Value(f"{replicate_type.id}"), function="jsonb_extract_path_text", output_field=CharField(), ) line_uuid = Cast("measurement__assay__line__uuid", output_field=CharField()) replicate_key = Coalesce(replicate, line_uuid) return qs.annotate(replicate_key=replicate_key) def _compose_id_filters(self): # define filters for special handling names = ["study_id", "line_id", "assay_id", "measure_id"] # now do special handling to OR together the filters id_filter = Q() # create filter by OR together the ID fields for name in names: f = self.filters.get(name) value = self.form.cleaned_data.get(name) if value: id_filter |= Q(**{f"{f.field_name}__{f.lookup_expr}": value}) return id_filter def _filter_ids_and_in_study(self, queryset): """ Filters the queryset by doing an OR-query on the ID types, plus an AND-query on the in_study filter, if specified. """ queryset = queryset.filter(self._compose_id_filters()) in_study = self.form.cleaned_data.get("in_study", None) if in_study: queryset = self.filters["in_study"].filter(queryset, in_study) return queryset