#python #django #django-queryset
#python #django #django-набор запросов
Вопрос:
Имея следующую модель:
class Company(models.Model):
name = models.CharField(max_length=10)
class Department(models.Model):
name = models.CharField(max_length=10)
company = models.ForeignKeyField(to=Company)
persons = models.ManyToManyField(to=Person, on_delete=models.PROTECT)
class Person(models.Model):
name = models.CharField(max_length=10)
Я хотел бы получить queryset
список всех людей в компании
Использование
def persons_by_company(company_name):
l = []
for d in Department.objects.filter(company__name=company_name):
for p in d.persons:
l.append(p)
return l
было бы
- медленно
- возвращает список, а не набор запросов (не поддается фильтрации и т. Д.)
Каков был бы способ получить здесь набор запросов?
Комментарии:
1. Как насчет этого
Person.objects.filter(departement__company__id=company_id)
?
Ответ №1:
В моем случае, я думаю, это довольно просто, просто
Person.objects.filter(departement__company__id=company_id).distinct()
или с названием компании:
Person.objects.filter(departement__company__name__iexact=company_name).distinct()
Ваша функция станет:
def persons_by_company(company_name):
return Person.objects.filter(departement__company__name__iexact=company_name).distinct()
Он возвращает набор запросов, и это быстрее. Я использую iexact
, чтобы избежать учета регистра.
ОБНОВЛЕНО: .distinct()
Просто чтобы удалить повторяющиеся записи.
Комментарии:
1. Я не думаю, что это работает — отдел — это поле «многие ко многим» (у человека может быть несколько отделов
2. Правильно, но вы используете department только для поиска в company, он просто перечислит все записи person, связанные с данным названием компании. Вы его тестировали?
3. Вы были правы, в моем случае для отдела больше ограничений, тогда я использую Q-запрос? т.Е. Я хотел бы получить его из
Department.objects.filter(name__icontains="A")
4. Да, вы можете использовать его для поиска по разным полям
5. К сожалению, это решение не работает — если человек находится в двух отделах компании, он возвращается дважды
Ответ №2:
Сначала у вас должен быть внешний ключ, привязанный к вашей компании или отделу
class Department(models.Model):
name = models.CharField(max_length=10)
company = models.ForeignKeyField(to=Company, related_name="department_company_key")
class Person(models.Model):
name = models.CharField(max_length=10)
person_department = models.ForeignKey(
'Department',
related_name="person_department_key"
on_delete=models.CASCADE,
blank=False,
null=False
)
затем в вашей функции:
def persons_by_company(company_name):
l = []
for d in Department.objects.filter(company__name=company_name):
for p in d.person_department_key.all(): # You also apply some filter()
l.append(p) # Remember This will append object not string or dictionary
return l
Не забывайте, что связанное имя должно быть уникальным
Комментарии:
1. (Моя реальная модель намного сложнее, это был всего лишь минимальный пример). Я не могу изменить модель — особенно ваша технически отличается — она имеет отношение от N до 1 человека к отделу, моя модель имеет отношение от M до N
2. Имеет ли в вашей модели один человек ccacn более одного отдела?