Оптимизация запросов к базе данных django

вопрос новичка по оптимизации запросов django db:

У меня есть настраиваемая форма модели для редактирования объекта Destination, и я в конструкторе получаю набор запросов из связанной модели Visitor, которая имеет поле ManyToMany в Destination (см. EDIT, чтобы узнать причину использования настраиваемой формы модели)

    print "loading initial choices"
    visitor_choices, visitor_initial = [], []
    visitor_set = self.instance.visitor_set.all()
    print visitor_set
    for obj in Visitor.objects.all():
        visitor_choices.append((obj.pk, obj.name))
        #if visitor_set.filter(pk=obj.pk # this hits the db every time!
        if obj in visitor_set:
            visitor_initial.append(obj.pk)

    self.fields['visitors'].choices = visitor_choices
    self.fields['visitors'].initial = visitor_initial

    print "finished loading initial choices"

Идея заключалась в том, чтобы загрузить связанный visitor_set в переменную, чтобы избежать повторных запросов, чтобы проверить, присутствует ли каждый посетитель в visitor_set. Это лучший подход?

Кроме того, если я включу ведение журнала базы данных (как описано в этом вопросе , второй ответ), я вижу повторяющийся запрос (3-й оператор SELECT) для выбора всех посетителей для целевого идентификатора 1, но этого нет в написанном мной коде, откуда он взялся?

loading initial choices
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testapp_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1  LIMIT 21; args=(1,
)
[<Visitor: MIMA>, <Visitor: MIMO>, <Visitor: MIMU>]
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor"; args=()
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testapp_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 ; args=(1,)
finished loading initial choices

ИЗМЕНИТЬ

Объект Destination, о котором я говорю, является связанной стороной поля ManyToMany объекта Visitor. Если бы моя форма редактировала сам объект Visitor, то Django автоматически обрабатывал бы поле ManyToMany. Но чтобы сделать это в модельной форме для Destination, мне нужно добавить поле множественного выбора для Visitor и настроить метод __init__ для загрузки вариантов выбора и начального выбора для него.

Однако вопрос заключается в том, как обрабатывать набор запросов и таинственный второй sql для загрузки многих значений, которые я также могу видеть из оболочки:

>>> from testapp.forms import DestinationForm
>>> from testapp.models import Destination, Visitor
>>> dest = Destination.objects.get(pk=1)
(0.001) SELECT "testapp_destination"."id", "testapp_destination"."destination" FROM "testapp_destination" WHERE "testapp_destination"."id" =
 1 ; args=(1,)
>>> destinationForm = DestinationForm(instance=dest)
loading initial choices
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testap
p_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1  LIMIT 21; args=(1,
)
[<Visitor: MIMA>, <Visitor: MIMO>, <Visitor: MIMU>]
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor"; args=()
(0.000) SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testap
p_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 ; args=(1,)
finished loading initial choices
>>>

Спасибо


person xuloChavez    schedule 30.11.2011    source источник
comment
Вы можете объяснить, чего пытаетесь достичь? Мне кажется, что вы делаете то, что django должен делать по умолчанию, если вы генерируете ModelForm для модели, в которой visitor является ManyToManyField?   -  person Bernhard Vallant    schedule 30.11.2011
comment
да, вы правы, моя форма пытается сохранить модель «Место назначения», которая находится в соответствующем конце полей ManytoMany в моей модели «Посетитель», я опубликую модели, чтобы уточнить. Таким образом, у меня может быть форма для сохранения «Посетителя», которая будет автоматически обрабатывать ManyToMany, однако я хотел изучить этот способ сделать это. Однако мой вопрос касается того, как я обрабатываю наборы запросов, и странного дополнительного оператора sql, который я вижу в журнале   -  person xuloChavez    schedule 30.11.2011


Ответы (1)


Чтобы ответить на то, что вы говорите, это ваш вопрос: я думаю, что запрос

SELECT "testapp_visitor"."id", "testapp_visitor"."name" FROM "testapp_visitor" INNER JOIN "testapp_visitor_destinations" ON ("testapp_visitor"."id" = "testapp_visitor_destinations"."visitor_id") WHERE "testapp_visitor_destinations"."destination_id" = 1 ; args=(1,)

происходит от линии

if obj in visitor_set:

где Django повторно выполняет запрос visitor_set (см. Когда QuerySets оцениваются в документации Django). Вы можете избежать этого, сразу же преобразовав visitor_set в set (чтобы Django был вынужден немедленно выполнить запрос), как в:

visitor_set = set(self.instance.visitor_set.all())

Это также улучшит производительность тестирования, находится ли объект в этом наборе (по сравнению с list или аналогичным итерабельным).

person Jan Pöschko    schedule 14.12.2011