Эффективный поиск лучших кандидатов, Django

Я новичок в django и python. У меня есть модели:

 class Employee(models.Model):
    full_name = models.CharField(max_length = 64)
    title = models.CharField(max_length = 64)

    def __str__(self):
        return f"{self.full_name} ( {self.title} )"

class Skill(models.Model):
    name = models.CharField(max_length = 64)

    def __str__(self):
        return f"{self.name}"

class Candidate(models.Model):
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name="employee")
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE, related_name="skill")

    def __str__(self):
        return f"{self.id}: {self.employee} knows - {self.skill}"

class Job(models.Model):
    title = models.CharField(max_length = 64)
    skills = models.ManyToManyField(Skill, blank=True, related_name="Jobs")

    def __str__(self):
        return f"{self.title}"

В views.py у меня есть функция поиска:

def finder(job_id):
    job = Job.objects.get(id=job_id) # get the specific job
    relevant_candidates = [] # all the relevant candidates of this kob
    common = [] # number of common skills between the employee_skill and the 
    relevant_employees_by_title = Employee.objects.filter(title = job.title) # first filter the candidates by the job title 
    job_skills = []
    for skill in job.skills.all():
        print(skill.id)
        job_skills.append(skill.id)

    for employee in relevant_employees_by_title: 
        employee_skills =[]
        candidateCorrect = Candidate.objects.filter(employee__id = employee.id).values_list('skill', flat=True)
        for skill in candidateCorrect:
            employee_skills.append(skill)

        common_skills = list(set(job_skills) & set(employee_skills))
        
        if (len(common_skills)>0): #if there are common skills
            relevant_candidates.append(employee) 
            common.append(len(common_skills))

    candidates = zip(relevant_candidates,common)
    candidates = sorted(candidates,key = lambda t: t[1], reverse = True) # sort the candidates by the number of common skiils , descending order
    candidates = candidates[:50] # Select the best 50 candidates

    return candidates

Эта функция получает job_id и должна найти лучших кандидатов на эту работу: сначала путем сопоставления названия должности с названием сотрудника (например, «разработчик программного обеспечения»), а затем сопоставления навыков кандидата с необходимыми навыками работы.

Я думаю, что моя функция неэффективный. Кто-нибудь знает, как это написать эффективно?

1 ответ
1

Вы можете использовать понимание для большего эффекта (здесь: напрямую построить job_skills используя понимание набора), а также избавился от необходимости помещать все в список.

Вы также можете сохранить подходящих кандидатов в collections.Counter, чтобы получить most_common(n) метод бесплатно.

from collections import Counter

def finder(job_id, n=50):
    job_skills = {skill.id for skill in Job.objects.get(id=job_id).skills.all()}

    candidates = Counter()
    for employee in Employee.objects.filter(title=job.title): 
        employee_skills = Candidate.objects
                                   .filter(employee__id=employee.id)
                                   .values_list('skill', flat=True)
        common_skills = len(job_skills.intersection(employee_skills))
        if common_skills:
            candidates[employee] = common_skills
    return candidates.most_common(n)

Я также следил за официальным руководством по стилю Python, PEP8, который рекомендует не окружать = с пробелами при использовании его для аргументов ключевого слова, использовал тот факт, что число 0 является ложным, в то время как все другие числа являются правдивыми и сделали количество кандидатов для возврата настраиваемым (со значением по умолчанию 50).


Обратите внимание, что эта задача была бы немного проще, если бы Employee к объекту уже прикреплен навык или, по крайней мере, ссылка на Candidate объект.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *