我有一個跟蹤出版物的Django應用程序。出版物與作者有着M2M的關係。使用MySQL。Django:減少ListView模板上的查詢
簡單。
class Publication(models.Model):
slug = models.SlugField(unique=True, max_length=128)
author = models.ManyToManyField(Author, blank=True, null=True, through='Authorship')
title = models.CharField(max_length=128)
def __unicode__(self):
return unicode(self.title)
我有一個ListView
向他們展示:
class PubList(ListView):
model = Publication
大部分是研究論文,有幾個作家。在我的模板上,我想顯示一個作者列表。所以我做了這樣的事情:
{% for obj in publication_list %}
<tr>
<td><a href="{{ obj.get_absolute_url }}">{{ obj.title }}</a></td>
<td>
{% for a in obj.authorship_set.all %}
{{ a.author.last_name }}, {{ a.author.first_name }}
{% if not forloop.last %}; {% endif %}
{% endfor %}
</td>
</tr>
{% endfor %}
那麼,你可能會猜測我的問題是什麼。隨着Publications
的數量增加,數據庫調用起飛。有超過500個查詢需要119份出版物
我解決了它,像這樣: 在我PubList(ListView)
我重寫get_context_data
這個函數的輸出設置爲背景[「作家」]:
def get_authors_by_pub():
from django.db import connection
sql = """SELECT p.id,
(
SELECT GROUP_CONCAT(CONCAT(a.last_name, ', ', a.first_name) SEPARATOR '; ')
FROM publication_authorship ap
LEFT JOIN publication_author a ON a.id = ap.author_id
WHERE ap.publication_id = p.id
)
FROM publication_publication p"""
cursor = connection.cursor()
cursor.execute(sql)
rows = cursor.fetchall() or()
authors = {}
for r in rows:
if r[1]:
authors[r[0]] = r[1]
return authors
現在我有一個作家詞典,如: {1: 'Tesla, Nikola; Clarke, Aurthur; Hooper, Grace', 2: 'Hopper, Grace; Simpson, Marge'}
然後,在模板,因爲我不能鍵訪問的字典,我遍歷authors
找到有鑰匙的那些是publication.id
:
<td>
{% for key, value in authors.items %}
{% if key == obj.id %}
{{ value }}
{% endif %}
{% endfor %}
</td>
This Works,just 2 queries。即使作者查詢是殘酷的,嵌套的SELECTs,它的速度比以前快了幾個數量級。
但我想知道是否有更好的方法。對於模板上的每個出版物,我都覺得有點棘手。我希望能夠在模板上使用authors[obj.id]
。
您認爲如何?
因爲我是啞巴?謝謝!! –
沒有人是個笨拙的伴侶,我們都在學習:)只需要更多的文檔閱讀;) – petkostas
您可以將'.all()'截斷 - 不是必需的。 – meshy