Django小技巧16: 資料庫通路優化
Posted November 05, 2018
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2PnVGcq5SN2lmbzFTd3ITevwFN1AjNxQTMtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.jpeg)
#錯綜複雜
翻譯整理自: simpleisbetterthancomplex.com
本篇分享資料庫通路優化相關, 讀完這些并不是讓你立即去優化代碼, 更多的時候對于現有代碼的優化, 需要借助Django Debug Toolbar來分析後, 再去相應的優化代碼, 但今天要說的是一些簡單的技巧, 用于你在編寫代碼的時候就所有規避不好用法, 使用推薦的用法.
通路外鍵值
如果你隻需外鍵的ID
Python
Do
post.author_id
複制
Python
Don't
post.author.id
複制
如果你的博文中有一個 author 的外鍵,Django 會自動将主鍵存儲在屬性author_id中, 而在author屬性則是一個惰性的資料庫引用。如果你如果使用author來通路 ID, 資料則會多出一個額外的查詢,就會産生開銷。
批量插入Many to Many字段
Python
Do
user.groups.add(administrators, managers)
複制
Python
Don't
user.groups.add(administrators)
user.groups.add(managers)
複制
Count QuerySets
如果你隻需擷取 QuerySet count
Python
Do
users = User.objects.all()
users.count()
# Or in template...
{{ users.count }}
複制
Python
Don't
users = User.objects.all()
len(users)
# Or in template...
{{ users|length }}
複制
Empty QuerySets
如果你隻想知道 QuerySets 是否為空.
Python
Do
groups = Group.objects.all()
if groups.exists():
# Do something...
複制
Python
Don't
groups = Group.objects.all()
if groups:
# Do something...
複制
減少不必要的查詢次數
就是之前講過的 select_related
Python
Do
review = Review.objects.select_related('author').first() # Select the Review and the Author in a single query
name = review.author.first_name
複制
Python
Don't
review = Review.objects.first() # Select the Review
name = review.author.first_name # Additional query to select the Author
複制
隻檢索需要的字段
假設模型Invoice有50個字段,你想要建立一個表格隻顯示摘要資訊,包含number、date和value.
Python
Do
# views.py
# If you don't need the model instance, go for:
invoices = Invoice.objects.values('number', 'date', 'value') # Returns a dict
# If you still need to access some instance methods, go for:
invoices = Invoice.objects.only('number', 'date', 'value') # Returns a queryset
# invoices.html
<table>
{% for invoice in invoices %}
<tr>
<td>{{ invoice.number }}</td>
<td>{{ invoice.date }}</td>
<td>{{ invoice.value }}</td>
</tr>
{% endfor %}
</table>
複制
Python
Don't
# views.py
invoices = Invoice.objects.all()
# invoices.html
<table>
{% for invoice in invoices %}
<tr>
<td>{{ invoice.number }}</td>
<td>{{ invoice.date }}</td>
<td>{{ invoice.value }}</td>
</tr>
{% endfor %}
</table>
複制
批量更新
使用
F()
批量更新.
Python
Do
from django.db.models import F
Product.objects.update(price=F('price') * 1.2)
複制
Python
Don't
products = Product.objects.all()
for product in products:
product.price *= 1.2
product.save()
複制