Как выбрать из нескольких таблиц в Django ORM? - PullRequest
1 голос
/ 02 апреля 2020

У меня есть две таблицы, oneup_backend_design и Django по умолчанию auth_user. Первая таблица имеет следующие столбцы (упрощенно): human_readable_id, manager, worker. Столбец Worker содержит username из auth_user.

. Поэтому я хочу получить human_readable_id плюс first_name и last_name работника, связанного с username в одном запросе. В raw SQL это выглядело бы так:

SELECT d.human_readable_id, u.first_name, u.last_name
FROM oneup_backend_design as d, auth_user as u
WHERE d.worker = u.username;

Я очень старался читать документы и Django ORM поваренную книгу, но ничего не нашел. Это такой простой запрос, я должен что-то упустить. Как сделать это одним попаданием в базу данных?

UPD: models.py:

class Design(models.Model):
    human_readable_id = models.CharField(max_length=10, default=id_generator, db_index=True)
    manager = models.CharField(max_length=40)
    worker = models.CharField(max_length=40, null=True)

Ответы [ 2 ]

2 голосов
/ 02 апреля 2020

Я настоятельно рекомендую превратить worker в ForeignKey, например, ссылаясь на поле username модели User:

from django.conf import settings

class Design(models.Model):
    human_readable_id = models.CharField(max_length=10, default=id_generator, db_index=True)
    manager = models.CharField(max_length=40)
    worker = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        <b>to_field='username'</b>
    )

Это означает, что worker_id будет поле VARCHAR с ограничением FOREIGN KEY для столбца username таблицы auth_user, и оно будет иметь индекс, который обеспечивает быстрое соединение. Кроме того, он, таким образом, гарантирует ссылочную целостность: если работник не является NULL, он ссылается на действительный username объекта auth_user.

Тогда мы можем выполнить запрос с помощью:

Design.objects<b>.select_related('worker')</b>

Вы можете использовать .only() [Django -doc] для сужения извлекаемых столбцов, но если они не содержат большие объемы данных, их лучше включить.

Вы также можете извлечь значения из связанной модели с помощью .annotate(..):

from django.db.models import F

Design.objects<b>.annotate(</b>
    first_name=F('worker__first_name'),
    last_name=F('worker__last_name')
<b>)</b>

Здесь объекты Design из этого набора запросов будут иметь два дополнительных атрибута: .first_name и .last_name.

1 голос
/ 02 апреля 2020

при условии, что ваша модель BackendDesign и у вас ForeignKey рабочий до User, тогда:

BackendDesign.objects.select_related(
    'worker',
).only(
    'human_readable_id',
    'worker__first_name',
    'worker__last_name',
)

Если это не поможет, пожалуйста, прочитайте о extra() в django документах Django дополнительные документы Я новичок здесь, но надеюсь, что это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...