def organisation_directory(request): """REST view for the update directory.""" page = request.rsr_page all_organisations = Organisation.objects.all() if not page else _page_organisations(page) # Filter updates based on query parameters filter_, text_filter = _create_filters_query(request) organisations = ( all_organisations.filter(filter_).distinct() if filter_ is not None else all_organisations ) organisations_text_filtered = ( organisations.filter(text_filter) if text_filter is not None else organisations ) if organisations_text_filtered.exists(): organisations = organisations_text_filtered # Get the relevant data for typeaheads based on filtered organisations (minus # text filtering, if no organisations were found) locations = [ {'id': choice[0], 'name': choice[1]} for choice in location_choices(organisations) ] display_organisations = get_qs_elements_for_page(organisations_text_filtered, request) # Get related objects of page at once response = { 'project_count': organisations_text_filtered.count(), 'projects': OrganisationDirectorySerializer(display_organisations, many=True).data, 'location': locations, } return Response(response)
def organisation_directory(request): """REST view for the update directory.""" page = request.rsr_page all_organisations = Organisation.objects.all() if not page else page.partners() # Filter updates based on query parameters filter_, text_filter = _create_filters_query(request) organisations = ( all_organisations.filter(filter_).distinct() if filter_ is not None else all_organisations ) organisations_text_filtered = ( organisations.filter(text_filter) if text_filter is not None else organisations ) if organisations_text_filtered.exists(): organisations = organisations_text_filtered # Get the relevant data for typeaheads based on filtered organisations (minus # text filtering, if no organisations were found) locations = [ {'id': choice[0], 'name': choice[1]} for choice in location_choices(organisations) ] count = organisations_text_filtered.count() display_organisations = get_qs_elements_for_page(organisations_text_filtered, request, count) # Get related objects of page at once response = { 'project_count': organisations_text_filtered.count(), 'projects': OrganisationDirectorySerializer(display_organisations, many=True).data, 'location': locations, 'page_size_default': settings.PROJECT_DIRECTORY_PAGE_SIZES[0], } return Response(response)
def update_directory(request): """REST view for the update directory.""" # Fetch updates based on whether we are on Akvo site or RSR main site page = request.rsr_page all_updates = _all_updates() if not page else page.updates() # Filter updates based on query parameters filter_, text_filter = _create_filters_query(request) updates = all_updates.filter( filter_).distinct() if filter_ is not None else all_updates updates_text_filtered = updates.filter( text_filter) if text_filter is not None else updates if updates_text_filtered.exists(): updates = updates_text_filtered # Get the relevant data for typeaheads based on filtered updates (minus # text filtering, if no updates were found) locations = [{ 'id': choice[0], 'name': choice[1] } for choice in location_choices(updates)] project_ids = updates.values_list('project__id', flat=True) projects = Project.objects.filter(id__in=project_ids) organisations = projects.all_partners().values('id', 'name', 'long_name') # FIXME: Currently only vocabulary 2 is supported (as was the case with # static filters). This could be extended to other vocabularies, in future. valid_sectors = dict(codelist_choices(SECTOR_CATEGORY)) sectors = projects.sectors().filter( vocabulary='2', sector_code__in=valid_sectors).values('sector_code').distinct() count = updates_text_filtered.count() display_updates = get_qs_elements_for_page(updates_text_filtered, request, count) display_updates = display_updates.select_related( 'project', 'project__primary_location', 'project__primary_organisation', 'user', ).prefetch_related('project__partners', 'project__sectors', 'locations', 'locations__country') response = { 'project_count': count, 'projects': ProjectUpdateDirectorySerializer(display_updates, many=True).data, 'organisation': TypeaheadOrganisationSerializer(organisations, many=True).data, 'location': locations, 'sector': TypeaheadSectorSerializer(sectors, many=True).data, 'page_size_default': settings.PROJECT_DIRECTORY_PAGE_SIZES[0], } return Response(response)
def update_directory(request): """REST view for the update directory.""" # Fetch updates based on whether we are on Akvo site or RSR main site page = request.rsr_page all_updates = _all_updates() if not page else _page_updates(page) # Filter updates based on query parameters filter_, text_filter = _create_filters_query(request) updates = all_updates.filter(filter_).distinct() if filter_ is not None else all_updates updates_text_filtered = updates.filter(text_filter) if text_filter is not None else updates if updates_text_filtered.exists(): updates = updates_text_filtered # Get the relevant data for typeaheads based on filtered updates (minus # text filtering, if no updates were found) locations = [ {'id': choice[0], 'name': choice[1]} for choice in location_choices(updates) ] project_ids = updates.values_list('project__id', flat=True) projects = Project.objects.filter(id__in=project_ids) organisations = projects.all_partners().values('id', 'name', 'long_name') # FIXME: Currently only vocabulary 2 is supported (as was the case with # static filters). This could be extended to other vocabularies, in future. valid_sectors = dict(codelist_choices(SECTOR_CATEGORY)) sectors = projects.sectors().filter( vocabulary='2', sector_code__in=valid_sectors ).values('sector_code').distinct() display_updates = get_qs_elements_for_page(updates_text_filtered, request) count = updates_text_filtered.count() display_updates = display_updates.select_related( 'project', 'project__primary_location', 'project__primary_organisation', 'user', ).prefetch_related( 'project__partners', 'project__sectors', 'locations', 'locations__country' ) response = { 'project_count': count, 'projects': ProjectUpdateDirectorySerializer(display_updates, many=True).data, 'organisation': TypeaheadOrganisationSerializer(organisations, many=True).data, 'location': locations, 'sector': TypeaheadSectorSerializer(sectors, many=True).data, 'page_size_default': settings.PROJECT_DIRECTORY_PAGE_SIZES[0], } return Response(response)
def directory(request): """The Organisation list view.""" qs = remove_empty_querydict_items(request.GET) # Set show_filters to "in" if any filter is selected filter_class = show_filter_class(qs, [ 'location', ]) # Yank Organisation collection all_organisations = _organisation_directory_coll(request) # Easter egg feature creator_organisations = request.GET.get('creator', False) if creator_organisations: all_organisations = all_organisations.filter(can_create_projects=True) f = OrganisationFilter(qs, queryset=all_organisations) # Change filter options further when on an Akvo Page if request.rsr_page: # Filter location filter list to only populated locations f.filters['location'].extra['choices'] = location_choices( all_organisations) # Build page page = request.GET.get('page') page, paginator, page_range = pagination(page, f.qs.distinct(), 10) # Get organisations to be displayed on the map if request.rsr_page and request.rsr_page.all_maps: map_orgs = all_organisations else: map_orgs = page.object_list map_orgs = map_orgs # Get related objects of page at once page.object_list = page.object_list.prefetch_related('locations') return render( request, 'organisation_directory.html', { 'orgs_count': f.qs.distinct().count(), 'filter': f, 'page': page, 'paginator': paginator, 'page_range': page_range, 'show_filters': filter_class, 'q': filter_query_string(qs), 'map_organisations': map_orgs, })
def directory(request): """The Organisation list view.""" qs = remove_empty_querydict_items(request.GET) # Set show_filters to "in" if any filter is selected filter_class = show_filter_class(qs, ['location', ]) # Yank Organisation collection all_organisations = _organisation_directory_coll(request) # Easter egg feature creator_organisations = request.GET.get('creator', False) if creator_organisations: all_organisations = all_organisations.filter(can_create_projects=True) f = OrganisationFilter(qs, queryset=all_organisations) # Change filter options further when on an Akvo Page if request.rsr_page: # Filter location filter list to only populated locations f.filters['location'].extra['choices'] = location_choices(all_organisations) # Build page page = request.GET.get('page') page, paginator, page_range = pagination(page, f.qs.distinct(), 10) # Get organisations to be displayed on the map if request.rsr_page and request.rsr_page.all_maps: map_orgs = all_organisations else: map_orgs = page.object_list map_orgs = map_orgs # Get related objects of page at once page.object_list = page.object_list.prefetch_related('locations') return render(request, 'organisation_directory.html', { 'orgs_count': f.qs.distinct().count(), 'filter': f, 'page': page, 'paginator': paginator, 'page_range': page_range, 'show_filters': filter_class, 'q': filter_query_string(qs), 'map_organisations': map_orgs, })
def project_directory(request): """Return the values for various project filters. Based on the current filters, it returns new options for all the (other) filters. This is used to generate dynamic filters. """ # Fetch projects based on whether we are an Akvo site or RSR main site page = request.rsr_page projects = page.projects() if page else Project.objects.all().public().published() # Exclude projects which don't have an image or a title # FIXME: This happens silently and may be confusing? projects = projects.exclude(Q(title='') | Q(current_image='')) # Filter projects based on query parameters filter_, text_filter = _create_filters_query(request) projects = projects.filter(filter_).distinct() if filter_ is not None else projects # NOTE: The text filter is handled differently/separately from the other filters. # The text filter allows users to enter free form text, which could result in no # projects being found for the given text. Other fields only allow selecting from # a list of options, and for every combination that is shown to users and # selectable by them, at least one project exists. # When no projects are returned for a given search string, if the text search is # not handled separately, the options for all the other filters are empty, and # this causes the filters to get cleared automatically. This is very weird UX. projects_text_filtered = ( projects.filter(text_filter) if text_filter is not None else projects ) if projects_text_filtered.exists(): projects = projects_text_filtered # Pre-fetch related fields to make things faster projects = projects.select_related( 'primary_location', 'primary_organisation', ).prefetch_related( 'locations', 'locations__country', 'recipient_countries', 'recipient_countries__country', ) # Get the relevant data for typeaheads based on filtered projects (minus # text filtering, if no projects were found) cached_locations, _ = get_cached_data(request, 'locations', None, None) if cached_locations is None: cached_locations = [ {'id': choice[0], 'name': choice[1]} for choice in location_choices(projects) ] set_cached_data(request, 'locations', cached_locations) organisations = projects.all_partners().values('id', 'name', 'long_name') # FIXME: Currently only vocabulary 2 is supported (as was the case with # static filters). This could be extended to other vocabularies, in future. valid_sectors = dict(codelist_choices(SECTOR_CATEGORY)) sectors = projects.sectors().filter( vocabulary='2', sector_code__in=valid_sectors ).values('sector_code').distinct() # NOTE: We use projects_text_filtered for displaying projects count = projects_text_filtered.count() display_projects = get_qs_elements_for_page(projects_text_filtered, request).select_related( 'primary_organisation' ) # NOTE: We use the _get_cached_data function to individually cache small # bits of data to avoid the response from never getting saved in the cache, # because the response is larger than the max size of data that can be # saved in the cache. cached_projects, showing_cached_projects = get_cached_data( request, 'projects', display_projects, ProjectDirectorySerializer ) cached_organisations, _ = get_cached_data( request, 'organisations', organisations, TypeaheadOrganisationSerializer ) response = { 'project_count': count, 'projects': cached_projects, 'showing_cached_projects': showing_cached_projects, 'organisation': cached_organisations, 'sector': TypeaheadSectorSerializer(sectors, many=True).data, 'location': cached_locations, 'page_size_default': settings.PROJECT_DIRECTORY_PAGE_SIZES[0], } return Response(response)
def project_directory(request): """Return the values for various project filters. Based on the current filters, it returns new options for all the (other) filters. This is used to generate dynamic filters. """ # Fetch projects based on whether we are an Akvo site or RSR main site page = request.rsr_page projects = page.projects() if page else Project.objects.all().public( ).published() # Exclude projects which don't have an image or a title # FIXME: This happens silently and may be confusing? projects = projects.exclude(Q(title='') | Q(current_image='')) # Filter projects based on query parameters filter_, text_filter = _create_filters_query(request) projects = projects.filter( filter_).distinct() if filter_ is not None else projects # NOTE: The text filter is handled differently/separately from the other filters. # The text filter allows users to enter free form text, which could result in no # projects being found for the given text. Other fields only allow selecting from # a list of options, and for every combination that is shown to users and # selectable by them, at least one project exists. # When no projects are returned for a given search string, if the text search is # not handled separately, the options for all the other filters are empty, and # this causes the filters to get cleared automatically. This is very weird UX. projects_text_filtered = (projects.filter(text_filter) if text_filter is not None else projects) if projects_text_filtered.exists(): projects = projects_text_filtered # Pre-fetch related fields to make things faster projects = projects.select_related( 'primary_location', 'primary_organisation', ).prefetch_related( 'locations', 'locations__country', 'recipient_countries', 'recipient_countries__country', ) # Get the relevant data for typeaheads based on filtered projects (minus # text filtering, if no projects were found) cached_locations, _ = get_cached_data(request, 'locations', None, None) if cached_locations is None: cached_locations = [{ 'id': choice[0], 'name': choice[1] } for choice in location_choices(projects)] set_cached_data(request, 'locations', cached_locations) organisations = projects.all_partners().values('id', 'name', 'long_name') # FIXME: Currently only vocabulary 2 is supported (as was the case with # static filters). This could be extended to other vocabularies, in future. valid_sectors = dict(codelist_choices(SECTOR_CATEGORY)) sectors = projects.sectors().filter( vocabulary='2', sector_code__in=valid_sectors).values('sector_code').distinct() # NOTE: We use projects_text_filtered for displaying projects count = projects_text_filtered.count() display_projects = get_qs_elements_for_page( projects_text_filtered, request).select_related('primary_organisation') # NOTE: We use the _get_cached_data function to individually cache small # bits of data to avoid the response from never getting saved in the cache, # because the response is larger than the max size of data that can be # saved in the cache. cached_projects, showing_cached_projects = get_cached_data( request, 'projects', display_projects, ProjectDirectorySerializer) cached_organisations, _ = get_cached_data(request, 'organisations', organisations, TypeaheadOrganisationSerializer) response = { 'project_count': count, 'projects': cached_projects, 'showing_cached_projects': showing_cached_projects, 'organisation': cached_organisations, 'sector': TypeaheadSectorSerializer(sectors, many=True).data, 'location': cached_locations, 'page_size_default': settings.PROJECT_DIRECTORY_PAGE_SIZES[0], } return Response(response)