Source code for profiles.managers

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


from django.db import models
from django.db.models import Count
from django.db.models.functions import Concat, Lower


[docs]class ProfileQuerySet(models.QuerySet):
[docs] def get_unique_from_email_or_None(self, email): try: return self.get(emails__email=email) except self.model.DoesNotExist: pass except self.model.MultipleObjectsReturned: pass return None
[docs] def potential_duplicates(self): """ Returns only potential duplicate Profiles (as identified by first and last names, and separately by (case-insensitive) email). """ # Start by treating name duplicates, excluding marked Profile non-duplicates from .models import ProfileNonDuplicates profiles = self.annotate(full_name=Concat('last_name', 'first_name')) nonduplicate_full_names = [dup.full_name for dup in ProfileNonDuplicates.objects.all()] duplicates_by_full_name = profiles.values('full_name').annotate( nr_count=Count('full_name')).filter(nr_count__gt=1 ).exclude(full_name__in=nonduplicate_full_names) from .models import ProfileEmail # Now for email duplicates. Because of case-insensitivity, we need some gymnastics pel = ProfileEmail.objects.annotate(email_lower=Lower('email')) # Build list of all duplicate lowercased emails duplicate_emails = [pe['email_lower'] for pe in pel.values('email_lower').annotate( nel=Count('email_lower')).filter(nel__gt=1)] # Then determine all ids of related Profiles with an email in this list ids_of_duplicates_by_email = [pe.profile.id for pe in pel.filter( email_lower__in=duplicate_emails)] # Now return list of potential duplicates return profiles.filter( models.Q(full_name__in=[item['full_name'] for item in duplicates_by_full_name]) | models.Q(id__in=ids_of_duplicates_by_email) ).order_by('last_name', 'first_name', '-id')
[docs] def specialties_overlap(self, discipline, expertises=[]): """ Returns all Profiles specialized in the given discipline and any of the (optional) expertises. This method is also separately implemented for Contributor and Fellowship objects. """ qs = self.filter(discipline=discipline) if expertises and len(expertises) > 0: qs = qs.filter(expertises__overlap=expertises) return qs
[docs] def specialties_contain(self, discipline, expertises=[]): """ Returns all Profiles specialized in the given discipline and all of the (optional) expertises. This method is also separately implemented for Contributor and Fellowship objects. """ qs = self.filter(discipline=discipline) if expertises and len(expertises) > 0: qs = qs.filter(expertises__contains=expertises) return qs