Django - 为什么这会两次击中数据库

时间:2011-02-08 11:30:56

标签: python django django-models

我的模型中有一个属性:

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 个答案:

答案 0 :(得分:6)

“或某事”?

为什么要存储结果?您已明确编写_get_image函数,以便每次都查询数据库。如果您希望它存储结果,您需要告诉它执行此操作。

可能最简单的方法就是在模板中获取一次:

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

答案 1 :(得分:3)

以下是编写缓存属性的方法,而无需在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