2011-12-19 23 views
8

Trong mỗi giao diện ứng dụng của tôi, tôi cần phải có menu điều hướng. Vì vậy, ngay bây giờ trong mỗi chế độ xem, tôi thực hiện truy vấn phức tạp và lưu trữ menu trong từ điển được chuyển tới mẫu. Trong các mẫu biến mà trong đó tôi có dữ liệu được bao quanh với "cache", vì vậy mặc dù các truy vấn khá tốn kém, nó không làm phiền tôi."Tải trọng" dữ liệu từ bộ xử lý ngữ cảnh

Nhưng tôi không muốn lặp lại chính mình trong mọi chế độ xem. Tôi đoán rằng nơi tốt nhất để chuẩn bị thực đơn là trong bộ xử lý ngữ cảnh của riêng tôi. Và vì vậy tôi đã viết một, nhưng tôi nhận thấy rằng ngay cả khi tôi không sử dụng dữ liệu từ bộ xử lý ngữ cảnh, các truy vấn được sử dụng để chuẩn bị menu được thực hiện. Có cách nào để "lười biếng tải" dữ liệu như vậy từ CP hoặc làm tôi phải sử dụng bộ nhớ cache "cấp thấp" trong CP? Hoặc có thể có một giải pháp tốt hơn cho vấn đề của tôi?

+0

thế nào về một nếu: khối khác trong bộ xử lý ngữ cảnh của bạn để kiểm tra xem dữ liệu là cần thiết hay không? –

+0

bạn có thể viết thẻ tùy chỉnh, chỉ được tính khi được sử dụng – kosii

Trả lời

18

Django có SimpleLazyObject. Trong Django 1.3, điều này được sử dụng bởi auth context processor (source code). Điều này làm cho user khả dụng trong ngữ cảnh mẫu cho mọi truy vấn, nhưng người dùng chỉ được truy cập khi mẫu chứa {{ user }}.

Bạn sẽ có thể làm điều gì đó tương tự trong bộ xử lý ngữ cảnh của mình.

from django.utils.functional import SimpleLazyObject 
def my_context_processor(request): 
    def complicated_query(): 
     do_stuff() 
     return result 

    return { 
     'result': SimpleLazyObject(complicated_query) 
3

Nếu bạn chuyển đối tượng có thể gọi vào ngữ cảnh mẫu, Django sẽ đánh giá đối tượng đó khi được sử dụng trong mẫu. Điều này cung cấp một cách đơn giản để làm lười biếng - chỉ cần vượt qua trong callables:

def my_context_processor(request): 
    def complicated_query(): 
     do_stuff() 
     return result      
    return {'result': complicated_query} 

Vấn đề ở đây là nó không memoize cuộc gọi - nếu bạn sử dụng nó nhiều lần, complicated_query được gọi nhiều lần.

Việc sửa chữa là sử dụng cái gì đó như SimpleLazyObject như trong câu trả lời khác, hoặc sử dụng một cái gì đó giống như memoize này trang trí:

def memoize_nullary(f): 
    """ 
    Memoizes a function that takes no arguments. 
    """ 
    def func(): 
     if not hasattr(func, 'retval'): 
      func.retval = f() 
     return func.retval 
    return func 

def my_context_processor(request): 
    @memoize_nullary 
    def complicated_query(): 
     do_stuff() 
     return result      
    return {'result': complicated_query} 

Hoặc, nếu chức năng đã tồn tại, bạn sẽ làm điều đó như thế này:

from somewhere import complicated_query 

def my_context_processor(request):   
    return {'result': memoize_nullary(complicated_query)} 

Tôi muốn phương pháp này hơn SimpleLazyObject vì sau này có thể sản xuất một số strange bugs sometimes.

(Tôi là một trong những người ban đầu thực hiện LazyObjectSimpleLazyObject, và khám phá cho bản thân mình rằng có lời nguyền trên bất kỳ mã vật phẩm dán nhãn simple.)