def _annotate_is_bookmarked(datasets, user): """ Adds a boolean annotation to queryset from *dataset bookmarks @param datasets: django querysey @param user: request.user @return: """ if datasets.model is ReferenceDataset: datasets = datasets.annotate(user_bookmark=FilteredRelation( "referencedatasetbookmark", condition=Q(referencedatasetbookmark__user=user), )) if datasets.model is DataSet: datasets = datasets.annotate(user_bookmark=FilteredRelation( "datasetbookmark", condition=Q(datasetbookmark__user=user))) if datasets.model is VisualisationCatalogueItem: datasets = datasets.annotate(user_bookmark=FilteredRelation( "visualisationbookmark", condition=Q(visualisationbookmark__user=user))) datasets = datasets.annotate(is_bookmarked=BoolOr( Case( When(user_bookmark__user__isnull=False, then=True), default=False, output_field=BooleanField(), )), ) return datasets
def withDetailStats(self): return self.annotate( deko_fahrzeuge=BoolOr('fahrzeuge__dekozug')).annotate( zug_max_speed=Least(F('speed_zug'), Min('fahrzeuge__speed_max')), fz_max_speed=Min('fahrzeuge__speed_max'), deko_zug=Case(When(deko_fahrzeuge=True, then=True), default='deko'))
def withTableStats(self): return self.annotate( position_count=Max('eintraege__position'), deko_fahrzeuge=BoolOr('fahrzeuge__dekozug')).annotate( fz_max_speed=Least(F('speed_zug'), Min('fahrzeuge__speed_max')), gesamt_zeit=Case( When(position_count=0, then=Value(datetime.timedelta(0))), default=Max(Coalesce('eintraege__an', 'eintraege__ab')) - Min(Coalesce('eintraege__ab', 'eintraege__an'))), anfang_zeit=Min(Coalesce('eintraege__an', 'eintraege__ab')), deko_zug=Case(When(deko_fahrzeuge=True, then=True), default='deko'))
def _annotate_has_access(datasets, user): """ Adds a bool annotation to queryset if user has access to the dataset @param datasets: django queryset @param user: request.user @return: queryset """ if datasets.model is ReferenceDataset: datasets = datasets.annotate(has_access=Value(True, BooleanField())) if datasets.model is DataSet or datasets.model is VisualisationCatalogueItem: if datasets.model is DataSet: datasets = datasets.annotate(user_permission=FilteredRelation( "datasetuserpermission", condition=Q(datasetuserpermission__user=user), ), ) if datasets.model is VisualisationCatalogueItem: datasets = datasets.annotate(user_permission=FilteredRelation( "visualisationuserpermission", condition=Q(visualisationuserpermission__user=user), ), ) datasets = datasets.annotate(has_access=BoolOr( Case( When( Q(user_access_type__in=[ UserAccessType.REQUIRES_AUTHENTICATION, UserAccessType.OPEN, ]) | (Q( user_access_type=UserAccessType.REQUIRES_AUTHORIZATION, user_permission__user__isnull=False, )) | Q(authorized_email_domains__contains=[ user.email.split("@")[1] ]), then=True, ), default=False, output_field=BooleanField(), )), ) return datasets
def _annotate_source_table_match(datasets, query): if datasets.model is DataSet or datasets.model is ReferenceDataset: schema, table = _schema_table_from_search_term(query) search_filter = Q() if datasets.model is ReferenceDataset: search_filter |= Q(table_name=table) else: table_match = Q(sourcetable__table=table) if schema: table_match &= Q(sourcetable__schema=schema) search_filter |= table_match return datasets.annotate(table_match=BoolOr( Case( When(search_filter, then=True), default=False, output_field=BooleanField(), ), ), ) return datasets.annotate(table_match=Value(False, BooleanField()), )
def _annotate_is_subscribed(datasets, user): """ Adds a bool annotation which is True if the user has a subscription to the dataset @param datasets: django queryset @param user: request.user @return: """ if datasets.model is ReferenceDataset or datasets.model is VisualisationCatalogueItem: return datasets.annotate(is_subscribed=Value(False, BooleanField())) if datasets.model is DataSet: datasets = datasets.annotate(user_subscription=FilteredRelation( "subscriptions", condition=Q(subscriptions__user=user)), ) datasets = datasets.annotate(is_subscribed=BoolOr( Case( When(user_subscription__user__isnull=False, then=True), default=False, output_field=BooleanField(), ))) return datasets
def get_annotation(self, cte): resource_condition = self.build_topic_condition(F('kind_id'), '!=') whens = [ # when selected node is not a topic, just use its changed status When(condition=WhenQ(*resource_condition), then=F('changed')), ] if self.include_self: # when selected node is a topic and it's changed and including self, then return that whens.append( When(condition=WhenQ(*[F('changed')]), then=F('changed'))) return Coalesce( Case( *whens, # fallback to aggregating descendant changed status when a unchanged topic default=BoolOr(cte.col.changed)), Value(False), output_field=BooleanField())
def get_datasets_data_for_user_matching_query(datasets: QuerySet, query, use=None, user=None, id_field='id'): """ Filters the dataset queryset for: 1) visibility (whether the user can know if the dataset exists) 2) matches the search terms Annotates the dataset queryset with: 1) `has_access`, if the user can use the dataset's data. """ is_reference_query = datasets.model is ReferenceDataset # Filter out datasets that the user is not allowed to even know about. visibility_filter = Q(published=True) if user: if is_reference_query: reference_type = DataSetType.REFERENCE.value reference_perm = dataset_type_to_manage_unpublished_permission_codename( reference_type) if user.has_perm(reference_perm): visibility_filter |= Q(published=False) if datasets.model is DataSet: master_type, datacut_type = ( DataSetType.MASTER.value, DataSetType.DATACUT.value, ) master_perm = dataset_type_to_manage_unpublished_permission_codename( master_type) datacut_perm = dataset_type_to_manage_unpublished_permission_codename( datacut_type) if user.has_perm(master_perm): visibility_filter |= Q(published=False, type=master_type) if user.has_perm(datacut_perm): visibility_filter |= Q(published=False, type=datacut_type) datasets = datasets.filter(visibility_filter) # Filter out datasets that don't match the search terms search = (SearchVector('name', weight='A', config='english') + SearchVector('short_description', weight='B', config='english') + SearchVector(StringAgg('tags__name', delimiter='\n'), weight='B', config='english')) search_query = SearchQuery(query, config='english') datasets = datasets.annotate(search=search, search_rank=SearchRank(search, search_query)) if query: datasets = datasets.filter(search=search_query) # Mark up whether the user can access the data in the dataset. access_filter = Q() if user and datasets.model is not ReferenceDataset: access_filter &= (Q(user_access_type='REQUIRES_AUTHENTICATION') & (Q(datasetuserpermission__user=user) | Q(datasetuserpermission__isnull=True))) | Q( user_access_type='REQUIRES_AUTHORIZATION', datasetuserpermission__user=user) datasets = datasets.annotate(_has_access=Case( When(access_filter, then=True), default=False, output_field=BooleanField(), ) if access_filter else Value(True, BooleanField()), ) # Pull in the source tag IDs for the dataset datasets = datasets.annotate(source_tag_ids=ArrayAgg( 'tags', filter=Q(tags__type=TagType.SOURCE.value), distinct=True)) datasets = datasets.annotate(source_tag_names=ArrayAgg( 'tags__name', filter=Q( tags__type=TagType.SOURCE.value), distinct=True)) # Pull in the topic tag IDs for the dataset datasets = datasets.annotate(topic_tag_ids=ArrayAgg( 'tags', filter=Q(tags__type=TagType.TOPIC.value), distinct=True)) datasets = datasets.annotate(topic_tag_names=ArrayAgg( 'tags__name', filter=Q(tags__type=TagType.TOPIC.value), distinct=True)) # Define a `purpose` column denoting the dataset type. if is_reference_query: datasets = datasets.annotate( purpose=Value(DataSetType.REFERENCE.value, IntegerField())) else: datasets = datasets.annotate(purpose=F('type')) # We are joining on the user permissions table to determine `_has_access`` to the dataset, so we need to # group them and remove duplicates. We aggregate all the `_has_access` fields together and return true if any # of the records say that access is available. datasets = datasets.values( id_field, 'name', 'slug', 'short_description', 'search_rank', 'source_tag_names', 'source_tag_ids', 'topic_tag_names', 'topic_tag_ids', 'purpose', 'published', 'published_at', ).annotate(has_access=BoolOr('_has_access')) return datasets.values( id_field, 'name', 'slug', 'short_description', 'search_rank', 'source_tag_names', 'source_tag_ids', 'topic_tag_names', 'topic_tag_ids', 'purpose', 'published', 'published_at', 'has_access', )
def get_visualisations_data_for_user_matching_query(visualisations: QuerySet, query, user=None): """ Filters the visualisation queryset for: 1) visibility (whether the user can know if the visualisation exists) 2) matches the search terms Annotates the visualisation queryset with: 1) `has_access`, if the user can use the visualisation. """ # Filter out visualisations that the user is not allowed to even know about. if not (user and user.has_perm( dataset_type_to_manage_unpublished_permission_codename( DataSetType.VISUALISATION.value))): visualisations = visualisations.filter(published=True) # Filter out visualisations that don't match the search terms search = SearchVector('name', weight='A', config='english') + SearchVector( 'short_description', weight='B', config='english') search_query = SearchQuery(query, config='english') visualisations = visualisations.annotate(search=search, search_rank=SearchRank( search, search_query)) if query: visualisations = visualisations.filter(search=search_query) # Mark up whether the user can access the visualisation. if user: access_filter = (Q(user_access_type='REQUIRES_AUTHENTICATION') & (Q(visualisationuserpermission__user=user) | Q(visualisationuserpermission__isnull=True))) | Q( user_access_type='REQUIRES_AUTHORIZATION', visualisationuserpermission__user=user, ) else: access_filter = Q() visualisations = visualisations.annotate(_has_access=Case( When(access_filter, then=True), default=False, output_field=BooleanField(), ) if access_filter else Value(True, BooleanField()), ) # Pull in the source tag IDs for the dataset visualisations = visualisations.annotate(source_tag_ids=ArrayAgg( 'tags', filter=Q(tags__type=TagType.SOURCE.value), distinct=True)) visualisations = visualisations.annotate(source_tag_names=ArrayAgg( 'tags__name', filter=Q( tags__type=TagType.SOURCE.value), distinct=True)) # Pull in the topic tag IDs for the dataset visualisations = visualisations.annotate(topic_tag_ids=ArrayAgg( 'tags', filter=Q(tags__type=TagType.TOPIC.value), distinct=True)) visualisations = visualisations.annotate(topic_tag_names=ArrayAgg( 'tags__name', filter=Q(tags__type=TagType.TOPIC.value), distinct=True)) # Define a `purpose` column denoting the dataset type visualisations = visualisations.annotate( purpose=Value(DataSetType.VISUALISATION.value, IntegerField())) # We are joining on the user permissions table to determine `_has_access`` to the visualisation, so we need to # group them and remove duplicates. We aggregate all the `_has_access` fields together and return true if any # of the records say that access is available. visualisations = visualisations.values( 'id', 'name', 'slug', 'short_description', 'search_rank', 'source_tag_names', 'source_tag_ids', 'topic_tag_names', 'topic_tag_ids', 'purpose', 'published', 'published_at', ).annotate(has_access=BoolOr('_has_access')) return visualisations.values( 'id', 'name', 'slug', 'short_description', 'search_rank', 'source_tag_names', 'source_tag_ids', 'topic_tag_names', 'topic_tag_ids', 'purpose', 'published', 'published_at', 'has_access', )