def __init__(self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs): if DJANGO_FILTER_INSTALLED: _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) kwargs.setdefault('args', {}) kwargs['args'].update(self.filtering_args) if 'id' not in kwargs['args'].keys(): self.filtering_args.update({'id': Argument(ID, description='Django object unique identification field')}) kwargs['args'].update({ 'id': Argument(ID, description='Django object unique identification field') }) if not kwargs.get('description', None): kwargs['description'] = '{} list'.format( _type._meta.model.__name__ ) super(DjangoFilterListField, self).__init__( List(_type), *args, **kwargs )
class ProjectByRegionGqlFilterSet(django_filters.FilterSet): RegionProjectFilterData = type( 'RegionProjectFilterData', (graphene.InputObjectType,), get_filtering_args_from_filterset(ProjectGqlFilterSet, 'project.schema.ProjectListType') ) project_filter = SimpleInputFilter(RegionProjectFilterData, method='filter_project_filter') class Meta: model = Region fields = () def filter_project_filter(self, qs, *_): # Used in def qs return qs def get_project_queryset(self): return Project.get_for_gq(self.request.user) @property def qs(self): project_qs = self.get_project_queryset() # Filter project if filter is provided project_filter = self.data.get('project_filter') if project_filter: project_qs = ProjectGqlFilterSet(data=project_filter, queryset=project_qs, request=self.request).qs return super().qs.annotate( projects_id=ArrayAgg('project', distinct=True, ordering='project', filter=models.Q(project__in=project_qs)), ).filter(projects_id__isnull=False).only('id', 'centroid')
def generate_list_search_parameters(schema_type): """Generate list of query parameters for the list resolver based on a filterset.""" search_params = {} if schema_type._meta.filterset_class is not None: # We need an instance for custom fields generation to happen for the # filterset_class or the `cf_*` fields won't be detected. filterset = schema_type._meta.filterset_class() # Patch base_filters because `get_filtering_args_from_filterset` looks there filterset.base_filters = filterset.filters search_params = get_filtering_args_from_filterset( filterset, schema_type, ) # Hack to swap `type` fields to `_type` since they will conflict with # `graphene.types.fields.Field.type` in Graphene 2.x. # TODO(jathan): Once we upgrade to Graphene 3.x we can remove this, but we # will still need to do an API migration to deprecate it. This argument was # validated to be safe to keep even in Graphene 3. if "type" in search_params: search_params["_type"] = search_params.pop("type") return search_params
def __init__( self, _type, pagination=None, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs, ): _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): self.filtering_args.update({ "id": Argument( ID, description="Django object unique identification field") }) kwargs["args"].update({ "id": Argument( ID, description="Django object unique identification field") }) pagination = pagination or graphql_api_settings.DEFAULT_PAGINATION_CLASS( ) if pagination is not None: assert isinstance(pagination, BaseDjangoGraphqlPagination), ( 'You need to pass a valid DjangoGraphqlPagination in DjangoFilterPaginateListField, received "{}".' ).format(pagination) pagination_kwargs = pagination.to_graphql_fields() self.pagination = pagination kwargs.update(**pagination_kwargs) if not kwargs.get("description", None): kwargs["description"] = "{} list".format( _type._meta.model.__name__) super(DjangoFilterPaginateListField, self).__init__(List(_type), *args, **kwargs)
def __init__(self, _type, pagination=None, fields=None, extra_filter_meta=None, filterset_class=None, preprocess_kwargs=None, *args, **kwargs): _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault('args', {}) kwargs['args'].update(self.filtering_args) if 'id' not in kwargs['args'].keys(): self.filtering_args.update({ 'id': Argument( ID, description='Django object unique identification field') }) kwargs['args'].update({ 'id': Argument( ID, description='Django object unique identification field') }) pagination = pagination or graphql_api_settings.DEFAULT_PAGINATION_CLASS if pagination is not None: assert isinstance(pagination, BaseDjangoGraphqlPagination), ( 'You need to pass a valid DjangoGraphqlPagination in DjangoFilterPaginateListField, received "{}".' ).format(pagination) pagination_kwargs = list_pagination_factory(pagination) self.pagination = pagination kwargs.update(**pagination_kwargs) if not kwargs.get('description', None): kwargs['description'] = '{} list'.format( _type._meta.model.__name__) preprocess_kwargs = preprocess_kwargs or kwargs_formatter kwargs = preprocess_kwargs(**kwargs) super(DjangoFilterPaginateListField, self).__init__(List(_type), *args, **kwargs)
def __init__(self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs): _fields = _type._meta.filter_fields _model = _type._meta.model self._model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) self._base_args = None super().__init__(List(_type), *args, **kwargs)
def __init__(self, _type, pagination=None, fields=None, extra_filter_meta=None, filterset_class=None, preprocess_kwargs=None, *args, **kwargs): _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault('args', {}) kwargs['args'].update(self.filtering_args) if 'id' not in kwargs['args'].keys(): self.filtering_args.update({ 'id': Argument( ID, description='Django object unique identification field') }) kwargs['args'].update({ 'id': Argument( ID, description='Django object unique identification field') }) if pagination: pagination_kwargs = list_pagination_factory(pagination) self.pagination = pagination kwargs.update(**pagination_kwargs) if not kwargs.get('description', None): kwargs['description'] = '{} list'.format( _type._meta.model.__name__) preprocess_kwargs = preprocess_kwargs or kwargs_formatter kwargs = preprocess_kwargs(**kwargs) super(DjangoFilterPaginateListField, self).__init__(List(_type), *args, **kwargs)
def __init__(self, _type, permission_classes=(), output_type=None, fields=None, extra_filter_meta=None, filterset_class=None, skip_filters=False, *args, **kwargs): self.filterset_class = {} self.filtering_args = {} assert isinstance( permission_classes, (tuple, list)), ("Permissions can only be a `List` of `Tuple` - ".format( self.__class__.__name__)) self.permission_classes = permission_classes if DJANGO_FILTER_INSTALLED and not skip_filters: _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): kwargs["args"].update({ "id": Argument( ID, description="Django object unique identification field" ) }) if not kwargs.get("description", None): kwargs["description"] = "{} list".format( _type._meta.model.__name__) self.skip_filters = skip_filters super(DjangoBaseListField, self).__init__(output_type or _type, *args, **kwargs)
def __init__( self, _type, pagination=None, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs, ): ''' If pagination is None, then we will only allow Ordering fields. - The page size will respect the settings. - Client will not be able to add pagination params ''' _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) pagination = pagination or OrderingOnlyArgumentPagination() if pagination is not None: assert isinstance(pagination, BaseDjangoGraphqlPagination), ( 'You need to pass a valid DjangoGraphqlPagination in DjangoFilterPaginateListField, received "{}".' ).format(pagination) pagination_kwargs = pagination.to_graphql_fields() self.pagination = pagination kwargs.update(**pagination_kwargs) if not kwargs.get("description", None): kwargs["description"] = "{} list".format( _type._meta.model.__name__) # accessor will be used with m2m or reverse_fk fields self.accessor = kwargs.pop('accessor', None) super(DjangoFilterPaginateListField, self).__init__(_type, *args, **kwargs)
def __init__(self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs): _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) kwargs.setdefault('args', {}) kwargs['args'].update(self.filtering_args) super().__init__(List(_type), *args, **kwargs)
def get_filter_args(self, _type, kwargs, inner_field=None): self.filterset_class = get_filterset_class( getattr(_type._meta, 'filterset_class', None), model=_type._meta.model, fields=_type._meta.filter_fields, ) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault('args', {}) order_args = { to_camel_case(k): i for (i, k) in enumerate(set(_type._meta.order_fields + ['id'])) } if len(order_args.items()) == 0: raise Exception(f'No ordering args found on {_type}') order_by_enum = enum.Enum( f'{_type}_{inner_field.model.__name__}_{inner_field.name}_OrderingFilter' if inner_field else f'{_type}OrderingFilter', order_args) self.order_by_enum = order_by_enum OrderByEnumObject = type( order_by_enum.__name__ + 'Object', (graphene.InputObjectType, ), { 'field': graphene.Enum.from_enum(order_by_enum)(), 'direction': OrderingDirectionEnumType( default_value=OrderingDirectionEnum.ASC.value), 'modifiers': graphene.List(OrderingModifierEnumType, default_value=[]), }) kwargs['args']['order_by'] = graphene.List(OrderByEnumObject, default_value=[], name='orderBy').Argument() kwargs['args']['limit'] = graphene.Int(default_value=0, name='limit').Argument() kwargs['args']['offset'] = graphene.Int(default_value=0, name='offset').Argument() kwargs['args'].update(self.filtering_args) return kwargs
def __init__( self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs, ): if DJANGO_FILTER_INSTALLED: _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): id_description = "Django object unique identification field" self.filtering_args.update( {"id": Argument(ID, description=id_description)}) kwargs["args"].update( {"id": Argument(ID, description=id_description)}) if not kwargs.get("description", None): kwargs["description"] = "{} list".format( _type._meta.model.__name__) super(DjangoListObjectField, self).__init__(_type, *args, **kwargs)
def __init__(self, _type, pagination=None, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs): _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) kwargs.setdefault('args', {}) kwargs['args'].update(self.filtering_args) if 'id' not in kwargs['args'].keys(): self.filtering_args.update({'id': Argument(ID, description='Django object unique identification field')}) kwargs['args'].update({'id': Argument(ID, description='Django object unique identification field')}) pagination = pagination or graphql_api_settings.DEFAULT_PAGINATION_CLASS() if pagination is not None: assert isinstance(pagination, BaseDjangoGraphqlPagination), ( 'You need to pass a valid DjangoGraphqlPagination in DjangoFilterPaginateListField, received "{}".' ).format(pagination) pagination_kwargs = pagination.to_graphql_fields() self.pagination = pagination kwargs.update(**pagination_kwargs) if not kwargs.get('description', None): kwargs['description'] = '{} list'.format(_type._meta.model.__name__) super(DjangoFilterPaginateListField, self).__init__(List(_type), *args, **kwargs)
def __init__( self, _type, pagination=None, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs, ): _fields = _type._meta.filter_fields _model = _type._meta.model self.fields = fields or _fields meta = dict(model=_model, fields=self.fields) if extra_filter_meta: meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) self.filtering_args = get_filtering_args_from_filterset( self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) """ # filtering by primary key or id seems unnecessary... if "id" not in kwargs["args"].keys(): self.filtering_args.update( { "id": Argument( ID, description="Django object unique identification field" ) } ) kwargs["args"].update( { "id": Argument( ID, description="Django object unique identification field" ) } ) """ pagination = pagination or OrderingOnlyArgumentPagination() if pagination is not None: assert isinstance(pagination, BaseDjangoGraphqlPagination), ( 'You need to pass a valid DjangoGraphqlPagination in DjangoFilterPaginateListField, received "{}".' ).format(pagination) pagination_kwargs = pagination.to_graphql_fields() self.pagination = pagination kwargs.update(**pagination_kwargs) if not kwargs.get("description", None): kwargs["description"] = "{} list".format( _type._meta.model.__name__) # accessor will be used with m2m or reverse_fk fields self.accessor = kwargs.pop('accessor', None) super(DjangoFilterPaginateListField, self).__init__(_type, *args, **kwargs)
class LeadGQFilterSet(UserResourceGqlFilterSet): ids = IDListFilter(method='filter_leads_id', help_text='Empty ids are ignored.') exclude_provided_leads_id = django_filters.BooleanFilter( method='filter_exclude_provided_leads_id', help_text='Only used when ids are provided.') created_by = IDListFilter() modified_by = IDListFilter() source_types = MultipleInputFilter(LeadSourceTypeEnum, field_name='source_type') priorities = MultipleInputFilter(LeadPriorityEnum, field_name='priority') confidentiality = SimpleInputFilter(LeadConfidentialityEnum) statuses = MultipleInputFilter(LeadStatusEnum, field_name='status') extraction_status = SimpleInputFilter(LeadExtractionStatusEnum, field_name='extraction_status') assignees = IDListFilter(field_name='assignee') authoring_organization_types = IDListFilter(method='authoring_organization_types_filter') author_organizations = IDListFilter(method='authoring_organizations_filter') source_organizations = IDListFilter(method='source_organizations_filter') # Filter-only enum filter has_entries = django_filters.BooleanFilter(method='filter_has_entries', help_text='Lead has entries.') has_assessment = django_filters.BooleanFilter(method='filter_has_assessment', help_text='Lead has assessment.') entries_filter_data = SimpleInputFilter( type( 'LeadEntriesFilterData', (graphene.InputObjectType,), get_filtering_args_from_filterset(EntryGQFilterSet, 'entry.schema.EntryListType') ), method='filtered_entries_filter_data', ) search = django_filters.CharFilter(method='search_filter') published_on = django_filters.DateFilter() published_on_gte = DateGteFilter(field_name='published_on') published_on_lte = DateLteFilter(field_name='published_on') emm_entities = django_filters.CharFilter(method='emm_entities_filter') emm_keywords = django_filters.CharFilter(method='emm_keywords_filter') emm_risk_factors = django_filters.CharFilter(method='emm_risk_factors_filter') ordering = MultipleInputFilter(LeadOrderingEnum, method='ordering_filter') class Meta: model = Lead fields = { **{ x: ['exact'] for x in ['text', 'url'] }, } filter_overrides = { models.CharField: { 'filter_class': django_filters.CharFilter, 'extra': lambda _: { 'lookup_expr': 'icontains', }, }, } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.custom_context = {} @property def active_project(self) -> Project: if self.request is None: raise Exception(f'{self.request=} should be defined') if self.request.active_project is None: raise Exception(f'{self.request.active_project=} should be defined') return self.request.active_project @staticmethod def get_dummy_request(project): """ Use this if request is not available """ return type('DummyRequest', (object,), dict(active_project=project))() # Filters methods def search_filter(self, qs, name, value): # NOTE: This exists to make it compatible with post filter if not value: return qs return qs.filter( # By title models.Q(title__icontains=value) | # By source models.Q(source_raw__icontains=value) | models.Q(source__title__icontains=value) | models.Q(source__parent__title__icontains=value) | # By author models.Q(author__title__icontains=value) | models.Q(author__parent__title__icontains=value) | models.Q(author_raw__icontains=value) | models.Q(authors__title__icontains=value) | models.Q(authors__parent__title__icontains=value) | # By URL models.Q(url__icontains=value) ).distinct() def ordering_filter(self, qs, name, value): active_entry_count_field = self.custom_context.get('active_entry_count_field') for ordering in value: # Custom for entries count (use filter or normal entry count) if active_entry_count_field and ordering in [ LeadOrderingEnum.ASC_ENTRIES_COUNT, LeadOrderingEnum.DESC_ENTRIES_COUNT, ]: if ordering == LeadOrderingEnum.ASC_ENTRIES_COUNT: qs = qs.order_by(active_entry_count_field) else: qs = qs.order_by(f'-{active_entry_count_field}') # Custom for page count with nulls_last elif ordering == LeadOrderingEnum.DESC_PAGE_COUNT: qs = qs.order_by(models.F('leadpreview__page_count').desc(nulls_last=True)) elif ordering == LeadOrderingEnum.ASC_PAGE_COUNT: qs = qs.order_by(models.F('leadpreview__page_count').asc(nulls_first=True)) # For remaining else: qs = qs.order_by(ordering) return qs def emm_entities_filter(self, qs, name, value): splitted = [x for x in value.split(',') if x] return qs.filter(emm_entities__in=splitted) def emm_keywords_filter(self, qs, name, value): splitted = [x for x in value.split(',') if x] return qs.filter(emm_triggers__emm_keyword__in=splitted) def emm_risk_factors_filter(self, qs, name, value): splitted = [x for x in value.split(',') if x] return qs.filter(emm_triggers__emm_risk_factor__in=splitted) def authoring_organization_types_filter(self, qs, name, value): if value: qs = qs.annotate( organization_types=Coalesce( 'authors__parent__organization_type', 'authors__organization_type' ) ) if type(value[0]) == OrganizationType: return qs.filter(organization_types__in=[ot.id for ot in value]).distinct() return qs.filter(organization_types__in=value).distinct() return qs def authoring_organizations_filter(self, qs, _, value): if value: qs = qs.annotate(authoring_organizations=Coalesce('authors__parent_id', 'authors__id')) return qs.filter(authoring_organizations__in=value).distinct() return qs def source_organizations_filter(self, qs, _, value): if value: qs = qs.annotate(source_organizations=Coalesce('source__parent_id', 'source__id')) return qs.filter(source_organizations__in=value).distinct() return qs def filter_exclude_provided_leads_id(self, qs, *_): # NOTE: Used in filter_leads_id return qs def filter_leads_id(self, qs, _, value): if value is None: return qs if self.data.get('exclude_provided_leads_id'): return qs.exclude(id__in=value) return qs.filter(id__in=value) def filter_has_entries(self, qs, _, value): if value is None: return qs if value: return qs.filter(entry_count__gt=0) return qs.filter(entry_count=0) def filter_has_assessment(self, qs, _, value): if value is None: return qs return qs.filter(assessment__isnull=not value) def filtered_entries_filter_data(self, qs, _, value): if value is None: return qs return qs.filter(filtered_entry_count__gt=0) def filter_queryset(self, qs): def _entry_subquery(entry_qs: models.QuerySet): subquery_qs = entry_qs.\ filter( project=self.active_project, analysis_framework=self.active_project.analysis_framework_id, lead=models.OuterRef('pk'), )\ .values('lead').order_by()\ .annotate(count=models.Count('id'))\ .values('count') return Coalesce( models.Subquery( subquery_qs[:1], output_field=models.IntegerField() ), 0, ) # Pre-annotate required fields for entries count (w/wo filters) entries_filter_data = self.data.get('entries_filter_data') has_entries = self.data.get('has_entries') has_entries_count_ordering = any( ordering in [ LeadOrderingEnum.ASC_ENTRIES_COUNT, LeadOrderingEnum.DESC_ENTRIES_COUNT, ] for ordering in self.data.get('ordering') or [] ) # With filter if entries_filter_data is not None: qs = qs.annotate( filtered_entry_count=_entry_subquery( EntryGQFilterSet( data=entries_filter_data, request=self.request, ).qs ) ) self.custom_context['active_entry_count_field'] = 'filtered_entry_count' # Without filter if has_entries is not None or ( entries_filter_data is None and has_entries_count_ordering ): self.custom_context['active_entry_count_field'] = self.custom_context.\ get('active_entry_count_field', 'entry_count') qs = qs.annotate( entry_count=_entry_subquery(Entry.objects.all()) ) # Call super function return super().filter_queryset(qs) @property def qs(self): return super().qs.distinct()
class ExportCreateGqlSerializer(ProjectPropertySerializerMixin, serializers.ModelSerializer): title = serializers.CharField(required=False) class Meta: model = Export fields = ( 'title', 'type', # Data type (entries, assessments, ..) 'format', # xlsx, docx, pdf, ... 'export_type', # excel, report, json, ... 'is_preview', 'filters', 'analysis', # Specific arguments for exports additional configuration 'excel_decoupled', 'report_show_groups', 'report_show_lead_entry_id', 'report_show_assessment_data', 'report_show_entry_widget_data', 'report_text_widget_ids', 'report_exporting_widgets', 'report_levels', 'report_structure', ) # Excel excel_decoupled = serializers.BooleanField( help_text='Don\'t group entries tags. Slower export generation.', required=False) # Report report_show_groups = serializers.BooleanField(required=False) report_show_lead_entry_id = serializers.BooleanField(required=False) report_show_assessment_data = serializers.BooleanField(required=False) report_show_entry_widget_data = serializers.BooleanField(required=False) report_text_widget_ids = serializers.ListField( child=serializers.IntegerField(), allow_empty=True, required=False) report_exporting_widgets = serializers.ListField( child=serializers.IntegerField(), allow_empty=True, required=False) report_levels = ExportReportLevelWidgetSerializer( required=False, many=True, help_text=ExportReportLevelWidgetSerializer.__doc__) report_structure = ExportReportStructureWidgetSerializer( required=False, many=True, help_text=ExportReportStructureWidgetSerializer.__doc__) filters = generate_serializer_field_class( type( 'ExportLeadsEntriesFilterData', (graphene.InputObjectType, ), get_filtering_args_from_filterset(LeadGQFilterSet, 'lead.schema.LeadListType')), GraphqlSupportDrfSerializerJSONField, )() @property def widget_qs(self): return Widget.objects.filter( analysis_framework=self.project.analysis_framework_id) @property def exportable_qs(self): return Exportable.objects.filter( analysis_framework=self.project.analysis_framework_id) def validate_filters(self, filters): filter_set = LeadGQFilterSet(data=filters, request=self.context['request']) if not filter_set.is_valid(): raise serializers.ValidationError(filter_set.errors) return filters def validate_report_text_widget_ids(self, widget_ids): if widget_ids: text_widgets_id = self.widget_qs.filter( widget_id=Widget.WidgetType.TEXT).values_list('id', flat=True) return [ widget_id for widget_id in widget_ids if widget_id in text_widgets_id ] return [] def validate_report_exporting_widgets(self, widget_ids): if widget_ids: widgets_id = self.widget_qs.values_list('id', flat=True) return [ widget_id for widget_id in widget_ids if widget_id in widgets_id ] return [] # TODO: def validate_report_levels(self, widget_ids): # TODO: def validate_report_structure(self, widget_ids): def validate_analysis(self, analysis): if analysis and analysis.project != self.project: raise serializers.ValidationError( f'Analysis project {analysis.project_id} doesn\'t match current project {self.project.id}' ) return analysis def validate(self, data): # NOTE: We only need to check with create logic (as update is not allowed) # Validate type, export_type and format data_type = data['type'] export_type = data['export_type'] _format = data['format'] if (data_type, export_type, _format) not in Export.DEFAULT_TITLE_LABEL: raise serializers.ValidationError( f'Unsupported Export request: {(data_type, export_type, _format)}' ) return data def update(self, _): raise serializers.ValidationError('Update isn\'t allowed for Export') def create(self, data): data['title'] = data.get('title') or Export.generate_title( data['type'], data['export_type'], data['format']) data['exported_by'] = self.context['request'].user data['project'] = self.project data['extra_options'] = { key: data.pop(key) for key in ( 'excel_decoupled', # Report 'report_show_groups', 'report_show_lead_entry_id', 'report_show_assessment_data', 'report_show_entry_widget_data', 'report_text_widget_ids', 'report_exporting_widgets', 'report_levels', 'report_structure', ) if key in data } export = super().create(data) transaction.on_commit( lambda: export.set_task_id(export_task.delay(export.id).id)) return export
def filtering_args(self): return get_filtering_args_from_filterset(self.filterset_class, self.node_type)