def get_base_queryset(self, all_aids=False): """Return the list of aids based on the initial search querysting.""" from aids.forms import AidSearchForm data = self.get_base_querystring_data() form = AidSearchForm(data) if all_aids: qs = form.filter_queryset( qs=Aid.objects.all(), apply_generic_aid_filter=False).distinct() else: qs = form.filter_queryset( apply_generic_aid_filter=False).distinct() # Annotate aids contained in the highlighted_aids field # This field will be helpful to order the queryset # source: https://stackoverflow.com/a/44048355 highlighted_aids_id_list = self.highlighted_aids.values_list( 'id', flat=True) # noqa qs = qs.annotate(is_highlighted_aid=Count( Case(When(id__in=highlighted_aids_id_list, then=1), output_field=IntegerField()))) # Simpler approach, but error-prone (aid could be highlighted in another SearchPage) # noqa # qs = qs.annotate(is_highlighted_aid=Count('highlighted_in_search_pages')) # noqa # Also exlude aids contained in the excluded_aids field excluded_aids_id_list = self.excluded_aids.values_list('id', flat=True) qs = qs.exclude(id__in=excluded_aids_id_list) return qs
def get_queryset(self): """Filter data according to search query.""" qs = self.get_base_queryset() filter_form = AidSearchForm(data=self.request.GET) results = filter_form.filter_queryset(qs) ordered_results = filter_form.order_queryset(results).distinct() return ordered_results
def get_queryset(self): """Filter data according to search query.""" qs = self.get_base_queryset() filter_form = AidSearchForm(data=self.request.GET) apply_filter = 'prevent_generic_filter' not in self.request.GET results = filter_form.filter_queryset(qs, apply_generic_aid_filter=apply_filter) ordered_results = filter_form.order_queryset(results).distinct() return ordered_results
def send_alert_confirmation_email(user_email, alert_token): """Send an alert confirmation link to the user. The email contains a token that can be used to validate the email ownership. """ try: alert = Alert.objects.get(token=alert_token) except (Alert.DoesNotExist): # In case we could not find any valid user with the given email # we don't raise any exception, because we can't give any hints # about whether or not any particular email has an account # on our site. return # Use the search form to parse the search querydict and # extract the perimeter querydict = QueryDict(alert.querystring) search_form = AidSearchForm(querydict) if search_form.is_valid(): perimeter = search_form.cleaned_data.get('perimeter', None) else: perimeter = None site = Site.objects.get_current() scheme = 'https' base_url = '{scheme}://{domain}'.format(scheme=scheme, domain=site.domain) alert_validation_link = reverse('alert_validate_view', args=[alert_token]) alert_date = '{:%d/%m/%Y %H:%M:%S}'.format(alert.date_created) subject = _('Please confirm your Aides-territoires alert (%(date)s)') % { 'date': alert_date } if alert.alert_frequency == Alert.FREQUENCIES.daily: frequency = _( 'You will receive a daily email whenever new matching aids will be published.' ) # noqa else: frequency = _( 'You will receive a weekly email whenever new matching aids will be published.' ) # noqa email_body = render_to_string( TEMPLATE, { 'base_url': base_url, 'alert': alert, 'frequency': frequency, 'perimeter': perimeter, 'alert_validation_link': '{}{}'.format(base_url, alert_validation_link) }) send_mail(subject, email_body, settings.DEFAULT_FROM_EMAIL, [user_email], fail_silently=False)
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) initial = self.get_initial() filter_form = AidSearchForm(initial) theme_aids = filter_form.filter_queryset() context['total_aids'] = theme_aids \ .values('id') \ .distinct() \ .count() return context
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) current_search = self.request.session.get(settings.SEARCH_COOKIE_NAME, '') context['current_search'] = current_search # Here we reconstruct the AidSearchForm from the current_search # querystring. This is needed to display some of the search filters. current_search_form = AidSearchForm(data=QueryDict(current_search)) if current_search_form.is_valid(): context['current_search_dict'] = clean_search_form( current_search_form.cleaned_data, remove_extra_fields=True) if self.request.GET.get('open-modal'): context['open_modal'] = True context['programs'] = self.object.programs \ .exclude(logo__isnull=True) \ .exclude(logo='') \ .distinct() financers = self.object.financers.all() # We don't want to display instructors if they are the same as the # financers all_instructors = self.object.instructors.all() instructors = [i for i in all_instructors if i not in financers] context.update({ 'financers': financers, 'instructors': instructors, }) context['financers_with_logo'] = financers \ .exclude(logo__isnull=True) \ .exclude(logo='') \ .distinct() context['idf_financer'] = financers \ .filter(pk=40) context['eligibility_criteria'] = any(( self.object.mobilization_steps, self.object.destinations, self.object.project_examples, self.object.eligibility)) context['alert_form'] = AlertForm(label_suffix='') if self.request.user.is_authenticated: context['aid_match_project_form'] = AidMatchProjectForm(label_suffix='') if self.request.user.beneficiary_organization: context['projects'] = Project.objects \ .filter(organizations=self.request.user.beneficiary_organization.pk) \ .order_by('name') return context
def get_queryset(self): """Filter data according to search query.""" qs = Aid.objects \ .published() \ .open() \ .select_related('perimeter') \ .prefetch_related('backers') \ .order_by('perimeter__scale', 'submission_deadline') filter_form = AidSearchForm(data=self.request.GET) filtered_qs = filter_form.filter_queryset(qs) return filtered_qs
def get_new_aids(self): """Get the list of aids that match the stored search params.""" querydict = QueryDict(self.querystring) search_form = AidSearchForm(querydict) base_qs = Aid.objects \ .published() \ .open() \ .select_related('perimeter', 'author') \ .prefetch_related('financers') \ .filter(date_published__gte=self.latest_alert_date) \ .order_by('date_published') qs = search_form.filter_queryset(base_qs) return qs
def send_alert_confirmation_email(user_email, alert_token): """Send an alert confirmation link to the user. The email contains a token that can be used to validate the email ownership. """ try: alert = Alert.objects.get(token=alert_token) except (Alert.DoesNotExist): # In case we could not find any valid user with the given email # we don't raise any exception, because we can't give any hints # about whether or not any particular email has an account # on our site. return # Use the search form to parse the search querydict and # extract the perimeter querydict = QueryDict(alert.querystring) search_form = AidSearchForm(querydict) perimeter = '' if search_form.is_valid(): perimeter = search_form.cleaned_data.get('perimeter') or '' perimeter = str(perimeter) base_url = get_base_url() alert_validation_link = reverse('alert_validate_view', args=[alert_token]) alert_date = '{:%d/%m/%Y %H:%M:%S}'.format(alert.date_created) if alert.alert_frequency == Alert.FREQUENCIES.daily: frequency = 'quotidien' else: frequency = 'hebdomadaire' data = { 'URL_SITE': base_url, 'FREQUENCE': frequency, 'PERIMETRE': perimeter, 'DATE_ALERTE': alert_date, 'LIEN_VALIDATION': '{}{}'.format(base_url, alert_validation_link) } send_email_with_template( recipient_list=[user_email], template_id=settings.SIB_ALERT_CONFIRMATION_EMAIL_TEMPLATE_ID, data=data, tags=['alerte_confirmation', settings.ENV_NAME], fail_silently=False)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # We have a problem here. # We want to return the list of existing themes, but we also want to # count the number of aids **matching the current search** for each # theme. # # Since the search query is already quite complex to generate, we # use it as a base and then we do a join on categories and themes, # then we group by theme and count. filter_form = AidSearchForm(self.initial) themes_with_aid_count = filter_form.filter_queryset() \ .exclude(categories__isnull=True) \ .values('categories__theme__slug', 'categories__theme__name') \ .annotate(nb_aids=Count('id', distinct=True)) \ .order_by('categories__theme__name') self.fields['themes'].queryset = themes_with_aid_count
def get_base_queryset(self, all_aids=False): """Return the list of aids based on the initial search querysting.""" from aids.forms import AidSearchForm # Sometime, the admin person enters a prefix "?" character # and we don't want it here. querystring = self.search_querystring.strip('?') data = QueryDict(querystring) form = AidSearchForm(data) if all_aids: qs = form.filter_queryset(Aid.objects.all()).distinct() else: qs = form.filter_queryset().distinct() # Also exlude aids contained in the excluded_aids field qs = qs.exclude(id__in=self.excluded_aids.values_list('id', flat=True)) return qs
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # See `ThemeSearchForm` for explanation about the following lines. filter_form = AidSearchForm(self.initial) filtered_qs = filter_form.filter_queryset() \ .exclude(categories__isnull=True) # We list categories for selected themes # Special case: if no theme was selected, we return all of them themes = self.initial.get('themes', []) if themes: filtered_qs = filtered_qs \ .filter(categories__theme__slug__in=themes) categories_with_aid_count = filtered_qs \ .values( 'categories__theme__name', 'categories__name', 'categories__slug') \ .annotate(nb_aids=Count('id', distinct=True)) \ .order_by('categories__theme__name', 'categories__name') self.fields['categories'].queryset = categories_with_aid_count
def test_search_form_filter_by_types(aids): form = AidSearchForm({'aid_types': ['grant']}) qs = form.filter_queryset(aids) assert qs.count() == 8 for aid in qs: assert 'grant' in aid.aid_types form = AidSearchForm({'aid_types': ['grant', 'networking']}) qs = form.filter_queryset(aids) for aid in qs: print(aid.aid_types) assert qs.count() == 9 for aid in qs: assert 'grant' in aid.aid_types or 'networking' in aid.aid_types
def test_search_form_filter_by_types(aids): form = AidSearchForm({'financial_aids': ['grant']}) qs = form.filter_queryset(aids) assert qs.count() == 8 for aid in qs: assert 'grant' in aid.aid_types form = AidSearchForm({ 'financial_aids': ['grant'], 'technical_aids': ['technical'] }) qs = form.filter_queryset(aids) assert qs.count() == 9 for aid in qs: assert 'grant' in aid.aid_types or 'technical' in aid.aid_types
def test_search_from_filter_by_audiences(aids): form = AidSearchForm({'targeted_audiences': ['commune']}) qs = form.filter_queryset(aids) assert qs.count() == 1 for aid in qs: assert 'commune' in aid.targeted_audiences form = AidSearchForm({'targeted_audiences': ['commune', 'department']}) qs = form.filter_queryset(aids) assert qs.count() == 2 for aid in qs: assert any(('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences)) form = AidSearchForm( {'targeted_audiences': ['commune', 'department', 'region']}) qs = form.filter_queryset(aids) assert qs.count() == 3 for aid in qs: assert any( ('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences)) form = AidSearchForm( {'targeted_audiences': ['commune', 'department', 'region', 'epci']}) qs = form.filter_queryset(aids) assert qs.count() == 4 for aid in qs: assert any( ('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences, 'epci' in aid.targeted_audiences)) form = AidSearchForm({ 'targeted_audiences': ['commune', 'department', 'region', 'epci', 'public_cies'] }) qs = form.filter_queryset(aids) assert qs.count() == 5 for aid in qs: assert any(('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences, 'epci' in aid.targeted_audiences, 'public_cies' in aid.targeted_audiences)) form = AidSearchForm({ 'targeted_audiences': [ 'commune', 'department', 'region', 'epci', 'public_cies', 'association' ] }) qs = form.filter_queryset(aids) assert qs.count() == 6 for aid in qs: assert any( ('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences, 'epci' in aid.targeted_audiences, 'public_cies' in aid.targeted_audiences, 'association' in aid.targeted_audiences)) form = AidSearchForm({ 'targeted_audiences': [ 'commune', 'department', 'region', 'epci', 'public_cies', 'association', 'private_person' ] }) qs = form.filter_queryset(aids) assert qs.count() == 7 for aid in qs: assert any( ('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences, 'epci' in aid.targeted_audiences, 'public_cies' in aid.targeted_audiences, 'association' in aid.targeted_audiences, 'private_person' in aid.targeted_audiences)) form = AidSearchForm({ 'targeted_audiences': [ 'commune', 'department', 'region', 'epci', 'public_cies', 'association', 'private_person', 'researcher' ] }) qs = form.filter_queryset(aids) assert qs.count() == 8 for aid in qs: assert any(( 'commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences, 'epci' in aid.targeted_audiences, 'public_cies' in aid.targeted_audiences, 'association' in aid.targeted_audiences, 'private_person' in aid.targeted_audiences, 'researcher' in aid.targeted_audiences, )) form = AidSearchForm({ 'targeted_audiences': [ 'commune', 'department', 'region', 'epci', 'public_cies', 'association', 'private_person', 'researcher', 'private_sector' ] }) qs = form.filter_queryset(aids) assert qs.count() == 9 for aid in qs: assert any( ('commune' in aid.targeted_audiences, 'department' in aid.targeted_audiences, 'region' in aid.targeted_audiences, 'epci' in aid.targeted_audiences, 'public_cies' in aid.targeted_audiences, 'association' in aid.targeted_audiences, 'private_person' in aid.targeted_audiences, 'researcher' in aid.targeted_audiences, 'private_sector' in aid.targeted_audiences))
def test_search_form_filter_by_deadline(aids): form = AidSearchForm({'apply_before': '2018-12-01'}) qs = form.filter_queryset(aids) assert qs.count() == 12 form = AidSearchForm({'apply_before': '2018-08-01'}) qs = form.filter_queryset(aids) assert qs.count() == 8 form = AidSearchForm({'apply_before': '2018-04-01'}) qs = form.filter_queryset(aids) assert qs.count() == 4 form = AidSearchForm({'apply_before': '2018-01-01'}) qs = form.filter_queryset(aids) assert qs.count() == 4 form = AidSearchForm({'apply_before': '2017-12-31'}) qs = form.filter_queryset(aids) assert qs.count() == 0
def test_search_form_filter_mobilization_step(aids): form = AidSearchForm({'mobilization_step': ['preop']}) qs = form.filter_queryset(aids) assert qs.count() == 9 for aid in qs: assert 'preop' in aid.mobilization_steps form = AidSearchForm({'mobilization_step': ['op']}) qs = form.filter_queryset(aids) assert qs.count() == 6 for aid in qs: assert 'op' in aid.mobilization_steps form = AidSearchForm({'mobilization_step': ['postop']}) qs = form.filter_queryset(aids) assert qs.count() == 4 for aid in qs: assert 'postop' in aid.mobilization_steps form = AidSearchForm({'mobilization_step': ['preop', 'postop']}) qs = form.filter_queryset(aids) assert qs.count() == 12 for aid in qs: assert any(('preop' in aid.mobilization_steps, 'postop' in aid.mobilization_steps))