Получите набор запросов django, который включает данные из 5 связанных моделей - PullRequest
1 голос
/ 27 мая 2020

У меня есть 5 моделей, которые связаны с внешними ключами следующим образом:

Section (Registration.section)
^ 1
|
v ∞
Registration < ∞ --- 1 > Event (Registration.event)
^ ∞
|
v 1
User (Registration.user, Profile.user)
^ 1
|
v 1
Profile

Из этих связанных моделей я пытаюсь отобразить данные в такой таблице:

| ID             | Other Profile fields    | Section1                     | Section2                    | SectionN |
|----------------|-------------------------|------------------------------|-----------------------------|----------|
| user1.username | eg. user1.profile.grade | Registration.objects.get(    | Registration.objects.get(   |
                                           |    section=Section1,         |   section=Section1,         |
                                           |    user=user1   |   user=user1   |
                                           | ).event                      | ).event                     |
|----------------|-------------------------|------------------------------|-----------------------------|----------|
| user2.username | user2.profile.grade     | ...event                     |None (needs to handle this)  | 
|----------------|-------------------------|------------------------------|-----------------------------|----------|
| user3.username | user3.profile.grade     | None (needs to handle this)  |None (needs to handle this)  |          |

Где у каждого пользователя есть отдельная строка. Что я не могу понять, как сделать это эффективно, так это получить регистрацию (и) для каждого раздела.

Я МОГУ сделать это, вручную манипулируя данными в python с помощью словарей и циклов et c, но это настолько неэффективно, что у моего сервера истекает время ожидания, прежде чем он сможет завершить процесс, если список пользователей слишком велик.

Какую структуру набора запросов мне нужно создать, чтобы иметь возможность выводить такие данные в шаблоне ?

В каждом разделе будет только один объект регистрации на пользователя:

class Registration(models.Model):

    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    section = models.ForeignKey(section, on_delete=models.CASCADE)

    class Meta:
        unique_together = ("event", "user", "section")

1 Ответ

0 голосов
/ 27 мая 2020

На практике я предлагаю вам выполнить разбиение на страницы:

  1. запросить только первые 100 пользователей -> у вас есть список идентификаторов пользователей.
  2. Registration.objects.filter(user__in=[1,42,...]).values_list()
  3. объедините данные в пары (они могут даже поступить из базы данных в правильном порядке).
  4. Сделайте это для других связанных моделей.

Это должно быть довольно быстро. В любом случае вы не хотите, чтобы на странице было больше 100 пользователей.

Ответ на ваш вопрос:

Вы можете попробовать использовать values_list, который приведет к единственному запросу join SQL к БД, если вы сделаете Registration.objects.values_list('event__property', 'user__username', 'user__profile__grade'). (см. https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django .db.models.query.QuerySet.values ​​)

и values_list не создают объекты модели, поэтому это будет быстрее.

Если вам нужны все данные вместе, самое надежное решение - это просто кэшировать. Ежедневно запускайте скрипт с cron, который делает вашу таблицу в фоновом режиме и сохраняет ее в таблице (через PickleField), если это возможно. (Даже если вам нужны более свежие данные, я бы предложил фоновый процесс для тяжелых запросов, подобных этому, с флагом состояния в базе данных (key: input, status: processing or ready, data: PickleField).)

Если пользователей много, даже запрос к базе данных join будет медленным при использовании реляционной базы данных. Ваш подход должен быть одним из самых быстрых, поскольку это всего лишь 4-5 запросов к БД + обработка.

...