Джанго - почему это дважды попадает в базу данных - PullRequest
2 голосов
/ 08 февраля 2011

У меня есть свойство в моей модели:

def _get_image(self):
    return Media.objects.get_for_object(self)

image = property(_get_image)

В моей модели мультимедиа вызывается следующая функция:

def get_for_object(self, obj):
        ctype = ContentType.objects.get_for_model(obj)
        return self.filter(items__content_type__pk=ctype.pk, items__object_id=obj.pk)

Затем в моем шаблоне я повторяю результаты примерно так:

{% if entry.image %}
<h2>Current image:</h2>
{% for m in entry.image %}
    {{ m }}
{% endfor %}
{% endif %}

По какой-то причине мои данные SQL показывают эти два запроса, расположенные рядом друг с другом:

0.40    SELECT
EXPLAIN
Toggle Stacktrace
SELECT `media_media`.`id`, `media_media`.`file`, `media_media`.`content_type`, `media_media`.`created` FROM `media_media` INNER JOIN `media_mediaattachment` ON (`media_media`.`id` = `media_mediaattachment`.`media_id`) WHERE (`media_mediaattachment`.`content_type_id` = 12 AND `media_mediaattachment`.`object_id` = 20 )
0.38    SELECT
EXPLAIN
Toggle Stacktrace
SELECT `media_media`.`id`, `media_media`.`file`, `media_media`.`content_type`, `media_media`.`created` FROM `media_media` INNER JOIN `media_mediaattachment` ON (`media_media`.`id` = `media_mediaattachment`.`media_id`) WHERE (`media_mediaattachment`.`content_type_id` = 12 AND `media_mediaattachment`.`object_id` = 20 )

Поэтому, когда я получаю доступ к entry.image, база данных получает удар. Конечно, он должен хранить результаты или что-то?

Ответы [ 2 ]

6 голосов
/ 08 февраля 2011

"или что-то"?

Зачем хранить результаты?Вы явно написали функцию _get_image, чтобы она каждый раз запрашивала базу данных.Если вы хотите, чтобы он сохранял результаты, вы должны указать это сделать.

Вероятно, самый простой способ - просто получить его один раз в шаблоне:

{% with entry.image as images %}
  {% if images %}
  <h2>Current image:</h2>
    {% for m in images %}
      {{ m }}
    {% endfor %}
  {% endif %}
{% endwith %}
3 голосов
/ 08 февраля 2011

Вот как вы пишете свойство кэширования без явного задания для кэша None в методе __init__:

def _get_image(self):
    if not hasattr(self, '_image'):
        self._image = Media.objects.get_for_object(self)
    return self._image

image = property(_get_image)

или в более современном синтаксисе

@property
def image(self):
    if not hasattr(self, '_image'):
        self._image = Media.objects.get_for_object(self)
    return self._image
...