__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" import requests import json from django.contrib import messages from django.contrib.auth.decorators import permission_required from django.urls import reverse, reverse_lazy from django.db import transaction from django.db.models import Q from django.utils.decorators import method_decorator from django.views.generic.edit import CreateView, UpdateView from django.shortcuts import get_object_or_404, render, redirect from dal import autocomplete from .models import Funder, Grant from .forms import FunderRegistrySearchForm, FunderForm, FunderOrganizationSelectForm, GrantForm from scipost.mixins import PermissionsMixin class FunderAutocompleteView(autocomplete.Select2QuerySetView): """ View to feed the Select2 widget. """ def get_queryset(self): if not self.request.user.has_perm('scipost.can_draft_publication'): return None qs = Funder.objects.all() if self.q: qs = qs.filter( Q(name__icontains=self.q) | Q(acronym__icontains=self.q) | Q(identifier__icontains=self.q) | Q(organization__name__icontains=self.q) | Q(organization__name_original__icontains=self.q) | Q(organization__acronym__icontains=self.q)).order_by('name')[:10] return qs class GrantAutocompleteView(autocomplete.Select2QuerySetView): """ View to feed the Select2 widget. """ def get_queryset(self): if not self.request.user.has_perm('scipost.can_draft_publication'): return None qs = Funder.objects.all() if self.q: qs = qs.filter( Q(funder__name__icontains=self.q) | Q(funder__acronym__icontains=self.q) | Q(number__icontains=self.q) | Q(recipient_name__icontains=self.q) | Q(recipient__user__last_name__icontains=self.q) | Q(recipient__user__first_name__icontains=self.q) | Q(further_details__icontains=self.q)).order_by('funder__name', 'number')[:10] return qs @permission_required('scipost.can_view_all_funding_info', raise_exception=True) def funders_dashboard(request): """Administration of Funders and Grants.""" funders = Funder.objects.all() form = FunderRegistrySearchForm() grants = Grant.objects.all() grant_form = GrantForm(request=request) context = {'form': form, 'funders': funders, 'grants': grants, 'grant_form': grant_form} return render(request, 'funders/funders_dashboard.html', context) @permission_required('scipost.can_view_all_funding_info', raise_exception=True) def query_crossref_for_funder(request): """ Checks Crossref's Fundref Registry for an entry corresponding to the funder name being looked for. If found, creates a funders.Funder instance. """ form = FunderRegistrySearchForm(request.POST or None) context = {'form': form} if form.is_valid(): queryurl = 'http://api.crossref.org/funders?query=%s' % form.cleaned_data['name'] query = requests.get(queryurl) response = json.loads(query.text) context['response_headers'] = query.headers context['response_text'] = query.text context['response'] = response context['funder_form'] = FunderForm() return render(request, 'funders/query_crossref_for_funder.html', context) @permission_required('scipost.can_view_all_funding_info', raise_exception=True) def add_funder(request): form = FunderForm(request.POST or None) if form.is_valid(): funder = form.save() messages.success(request, ('<h3>Funder %s successfully created</h3>') % str(funder)) elif form.has_changed(): messages.warning(request, 'The form was invalidly filled.') return redirect(reverse('funders:funders_dashboard')) def funders(request): """List page of Funders.""" funders = Funder.objects.has_publications().distinct() context = { 'funders': funders } return render(request, 'funders/funder_list.html', context) def funder_publications(request, funder_id): """Detail page of a specific Funder (publicly accessible).""" funder = get_object_or_404(Funder, id=funder_id) context = {'funder': funder} return render(request, 'funders/funder_details.html', context) class HttpRefererMixin: def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['request'] = self.request return kwargs def form_valid(self, form): if form.cleaned_data.get('http_referer'): self.success_url = form.cleaned_data['http_referer'] return super().form_valid(form) class LinkFunderToOrganizationView(PermissionsMixin, UpdateView): """ For an existing Funder instance, specify the link to an Organization. """ permission_required = 'scipost.can_create_grants' model = Funder form_class = FunderOrganizationSelectForm template_name = 'funders/funder_link_organization.html' success_url = reverse_lazy('funders:funders_dashboard') def form_valid(self, form): form.instance.organization = form.cleaned_data['organization'] return super().form_valid(form) @method_decorator(transaction.atomic, name='dispatch') class CreateGrantView(PermissionsMixin, HttpRefererMixin, CreateView): """ Create a Grant in a separate window which may also be used by Production Supervisors. """ permission_required = 'scipost.can_create_grants' model = Grant form_class = GrantForm success_url = reverse_lazy('funders:funders_dashboard')