1. 程式人生 > >Django之快取+序列化+訊號+ORM效能優化+驗證碼

Django之快取+序列化+訊號+ORM效能優化+驗證碼

快取

由於Django是動態網站,所有每次請求均會去資料進行相應的操作,當程式訪問量大時,耗時必然會更加

明顯,最簡單解決方式是使用:快取,快取將一個某個views的返回值儲存至記憶體或者memcache中,5分

鍾內再有人來訪問時,則不再去執行view中的操作,而是直接從記憶體或者Redis中之前快取的內容拿到,並

返回。

Django中提供了6種快取方式:

  • 開發除錯

  • 記憶體

  • 檔案

  • 資料庫

  • Memcache快取(python-memcached模組)

  • Memcache快取(pylibmc模組)

  • 配置

    CACHES = {
    'default': {
    'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    'LOCATION': 'unique-snowflake',
    'TIMEOUT': 300, # 快取超時時間(預設300,None表示永不過期,0表示立即過期)
    'OPTIONS': {
    'MAX_ENTRIES': 300, # 最大快取個數(預設300)
    'CULL_FREQUENCY': 3, # 快取到達最大個數之後,剔除快取個數的比例,即1/CULL_FREQUENCY(預設3)
    },
    }
    }

    redis

    django-redis

  • 應用

    應用到檢視上: 粒度適中
    from django.views.decorators.cache import cache_page
    @cache_page(15)
    def user_list(request):
      print('user_list')
      users = models.User.objects.all()
      return render(request, 'user_list.html', {'users': users})
        全站應用: 粒度最大
    MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    # 其他中介軟體...
    'django.middleware.cache.FetchFromCacheMiddleware',
    ]
    區域性檢視:粒度最細

    a. 引入TemplateTag

    {% load cache %}

    b. 使用快取

    {% cache 5000 快取key %}
    快取內容
    {% endcache %}

序列化

 

    json  pickle

- 自定義序列化

class JsonCustomEncoder(json.JSONEncoder):

def default(self, field):

if isinstance(field, datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field, date):
return field.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, field)

print(json.dumps(data,cls=JsonCustomEncoder))

訊號

 

  • 訊號 問題: 資料庫增加一條資料的時候,記錄一條日誌。

    內建訊號    
    Model signals
    pre_init                   # django的model執行其構造方法前,自動觸發
    post_init                   # django的model執行其構造方法後,自動觸發
    pre_save                   # django的model物件儲存前,自動觸發
    post_save                   # django的model物件儲存後,自動觸發
    pre_delete                 # django的model物件刪除前,自動觸發
    post_delete                 # django的model物件刪除後,自動觸發
    m2m_changed                 # django的model中使用m2m欄位操作第三張表(add,remove,clear)前後,自動觸發
    class_prepared             # 程式啟動時,檢測已註冊的app中modal類,對於每一個類,自動觸發
    Management signals
    pre_migrate                 # 執行migrate命令前,自動觸發
    post_migrate               # 執行migrate命令後,自動觸發
    Request/response signals
    request_started             # 請求到來前,自動觸發
    request_finished           # 請求結束後,自動觸發
    got_request_exception       # 請求異常後,自動觸發
    Test signals
    setting_changed             # 使用test測試修改配置檔案時,自動觸發
    template_rendered           # 使用test測試渲染模板時,自動觸發
    Database Wrappers
    connection_created         # 建立資料庫連線時,自動觸發

     

    註冊訊號
    # 方法一
    def callback(sender, **kwargs):
    print("xxoo_callback")
    print(sender, kwargs)
        post_save.connect(callback)
        # 方法二

@receiver(post_save)
def my_callback(sender, **kwargs):
print("xxoo_callback")
print(sender, kwargs)

- ORM效能相關

1. [{} ]
all_users = models.User.objects.all().values('name','age','role__name')

2. [ 物件 ]
all_users = models.User.objects.all()
用的時候注意,只拿自己表中的欄位,別跨表
3. select_related (外來鍵、一對一)
all_users = models.User.objects.all().select_related('role')

4. prefetch_related (role)
all_users = models.User.objects.all().prefetch_related('role')

5. only
all_users = models.User.objects.all().only('name')
用的時候注意,只拿自己指定的欄位
6. defer
all_users = models.User.objects.all().defer('name')

驗證碼

- 驗證碼
from PIL import Image, ImageDraw, ImageFont
import random
    def random_color():
return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    def v_code(request):
img_obj = Image.new('RGB', (250, 35), random_color())

# 在該圖片物件上生成一個畫筆物件
draw_obj = ImageDraw.Draw(img_obj)

font_obj = ImageFont.truetype('static/font/kumo.ttf', 28)

temp = []
for i in range(5):
l = chr(random.randint(97, 122)) # 小寫字母
b = chr(random.randint(65, 90)) # 大寫字母
n = str(random.randint(0, 9))

t = random.choice([l, b, n])
temp.append(t)

draw_obj.text((i * 40 + 35, 0), t, fill=random_color(), font=font_obj)

from io import BytesIO
f1 = BytesIO()
img_obj.save(f1, format="PNG")
img_data = f1.getvalue()

return HttpResponse(img_data, content_type='image/png')