天天看點

Django小技巧16: 資料庫通路優化Django小技巧16: 資料庫通路優化

Django小技巧16: 資料庫通路優化

Posted November 05, 2018

Django小技巧16: 資料庫通路優化Django小技巧16: 資料庫通路優化

#錯綜複雜

翻譯整理自: 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()           

複制