Я новичок в 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 ответ
Вы можете использовать понимание для большего эффекта (здесь: напрямую построить 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
объект.