Переопределение метода Queryset администратора Django;Плохо выполняющийся запрос - PullRequest
0 голосов
/ 25 июня 2010

У меня есть система с несколькими сайтами. Каждый пользовательский объект в системе получает прикрепленный к нему объект профиля, который определяет, с какими сайтами они имеют право взаимодействовать. Система также имеет модель статьи, которая может принадлежать нескольким сайтам. Поэтому, когда пользователь загружает страницу администрирования статьи, я хочу, чтобы он видел только статьи, назначенные сайтам, к которым он имеет доступ. Итак, я переопределил метод queryset в классе Admin Статьи следующим образом:

qs = model.objects.filter(sites__id__in=[x.id for x in user.get_profile().group_profile.allowed_sites.all()]).distinct()

Взятие пользователя, получение Сайтов, к которым он имеет доступ, и получение Статей, назначение сайта которых находится в этом списке. Проблема в том, что этот запрос становится реальной собакой, когда вы получаете до нескольких сотен тысяч статей, и он усугубляется большой моделью, что означает, что Django извлекает много данных и запускает DISTINCT в большом списке столбцов.

Я ищу способы улучшить его, но метод набора запросов, похоже, не дает мне особого результата. Первоначально я пытался использовать функцию QuerySet only () для извлечения только столбцов, которые мне нужны, чтобы нарисовать список изменений, но потом обнаружил, что это приводит к тому, что сигналы post_save для модели не срабатывают при сохранении. Я не могу избавиться от отдельных, потому что если я это сделаю, я получу несколько результатов для каждого сайта: то есть, если пользователь может видеть сайт A и сайт B, и статья принадлежит обоим сайтам, запрос будет возвращать статью в два раза.

1 Ответ

1 голос
/ 25 июня 2010

Если у вас есть отношения ManyToMany, вы не можете избавиться от distinct(), потому что для каждого экземпляра необходимо выполнить несколько соединений. Что-то, что вы можете сделать со своим запросом (хотя я не думаю, что это приведет к значительному увеличению производительности), вам не нужно выполнять запросы __in с идентификаторами:

qs = model.objects.filter(\
        sites__in=user.get_profile().group_profile.allowed_sites.all()).distinct()
...