(工作小總結)Django REST Framework 效能優化,簡單實現預載入功能
阿新 • • 發佈:2019-01-25
緣由: Django 的 ORM 是惰性的每個使用者訪問網站時候,都要進行一次資料互動
在最初開發的時候,需要考慮到使用者量大的時候,
又由於 Django 的 ORM 是惰性的,它只取出當前查詢所需響應最小的資料。它不知道你是否有成百上千的相同或相似的資料也需要取出來。因此訪問網站時這勢必會對資料庫造成巨大壓力!
有句話說的是:只要你在序列化中使用巢狀關係,你就在拿你的效能開玩笑那麼怎麼解決他呢?
解決的方法是使用者訪問時候進行預載入功能,即將資料提前載入到使用者本地中。如何預載入呢?其實django已經提供了方法,在這裡我將工作中常用的載入方式貼出來:
很簡單!在你訪問量大的檢視新增:
queryset = queryset.prefetch_related('你的序列化器名')
具體列子如下:
class CustomerSerializer(serializers.ModelSerializer):
orders = OrderSerializer(many=True, read_only=True)
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('orders' )
return queryset
呼叫例子:
customer_qs = Customers.objects.all()
customer_qs = CustomerSerializer.setup_eager_loading(customer_qs) # Set up eager loading to avoid N+1 selects
post_data = CustomerSerializer(customer_qs, many=True).data
以上是簡單實現預載入的原理,我想各位閱讀預載入這塊,程式碼經驗應該還是有的吧??那我就直接貼出比較具體的程式碼塊了,實現預載入功能!
- 首先建立一個簡單的資料模型類:
from django.contrib.auth.models import User
class Event:
""" A single occasion that has many `attendees` from a number of organizations."""
creator = models.ForeignKey(User)
name = models.TextField()
event_date = models.DateTimeField()
class Attendee:
""" A party-goer who (usually) represents an `organization`, who may attend many `events`."""
events = models.ManyToManyField(Event, related_name='attendees')
organization = models.ForeignKey(Organization, null=True)
class Organization:
name = models.TextField()
2.預載入程式碼如下:
class EventSerializer(serializers.ModelSerializer):
creator = serializers.StringRelatedField()
attendees = AttendeeSerializer(many=True)
unaffiliated_attendees = AttendeeSerializer(many=True)
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
# select_related for "to-one" relationships
queryset = queryset.select_related('creator')
# prefetch_related for "to-many" relationships
queryset = queryset.prefetch_related(
'attendees',
'attendees__organization')
# Prefetch for subsets of relationships
queryset = queryset.prefetch_related(
Prefetch('unaffiliated_attendees',
queryset=Attendee.objects.filter(organization__isnull=True))
)
return queryset