2009-03-29 17 views
5

Giả sử rằng tôi có một hệ thống có một số trang công khai (cả người dùng không được xác thực và người dùng đã đăng nhập đều có thể xem) và những người khác chỉ người dùng đã đăng nhập mới có thể xem.Mẫu django có thể biết liệu chế độ xem mà nó được gọi ra có trình trang trí @login_required không?

Tôi muốn mẫu hiển thị nội dung hơi khác nhau cho mỗi một trong hai lớp trang này. Trình trang trí chế độ xem @login_required luôn được sử dụng trên các chế độ xem mà chỉ người dùng đã đăng nhập mới có thể xem. Tuy nhiên, mẫu của tôi sẽ cần biết liệu trình trang trí này có được sử dụng trên chế độ xem mà từ đó mẫu được gọi ra hay không.

Hãy nhớ rằng tôi không quan tâm liệu người dùng có đăng nhập hay không cho các trang công khai. Những gì tôi quan tâm là liệu một trang có thể được xem bởi công chúng hay không, và sự vắng mặt của một trang trí @login_required sẽ cho tôi biết điều đó.

Có ai có thể ném cho tôi một gợi ý về cách mẫu sẽ biết liệu một trang trí cụ thể có đang được sử dụng trên chế độ xem mà từ đó mẫu được gọi ra không?

Trả lời

5

Có, có thể, nhưng không quá đơn giản. Yếu tố phức tạp là thiết kế trang trí login_required của Django thực sự đi qua 2 cấp độ không xác định (một hàm động và một trang trí khác), để kết thúc tại django.contrib.auth.decorators._CheckLogin, là một lớp với phương thức __call__.

Hãy nói rằng bạn có một tổ chức phi django, vườn nhiều chức năng trang trí trông như thế này:

def my_decorator(func): 
    def inner(): 
     return func() 
    return inner 

@my_decorator 
def foo(): 
    print foo.func_name 

# results in: inner 

Kiểm tra để xem nếu chức năng foo đã được bọc có thể đơn giản như kiểm tra tên đối tượng chức năng của . Bạn có thể làm điều này bên trong hàm. Tên sẽ thực sự là tên của hàm wrapper cuối cùng. Đối với các trường hợp phức tạp hơn, bạn có thể sử dụng mô-đun inspect để đi bộ lên các khung bên ngoài từ khung hiện tại nếu bạn đang tìm kiếm một thứ gì đó cụ thể.

Trong trường hợp của Django, tuy nhiên, thực tế là trang trí thực sự là một thể hiện của lớp _CheckLogin có nghĩa là chức năng không phải là thực sự là một chức năng, và do đó không có func_name tài sản: cố gắng đoạn mã trên sẽ nâng cao một ngoại lệ .

Nhìn vào mã nguồn cho django.contrib.auth.decorators._CheckLogin, tuy nhiên, cho thấy trường hợp _CheckLogin sẽ có thuộc tính login_url.Đây là một điều khá đơn giản để kiểm tra:

@login_required 
def my_view(request): 
    is_private = hasattr(my_view, 'login_url') 

_CheckLogin cũng được sử dụng để thực hiện trang trí auth khác, phương pháp này cũng sẽ làm việc cho permission_required, vv Tôi đã không bao giờ thực sự có nhu cầu sử dụng này Tuy nhiên, tôi thực sự không thể bình luận về những gì bạn nên tìm kiếm nếu bạn có nhiều trang trí xung quanh một cái nhìn duy nhất ... một bài tập còn lại cho người đọc, tôi đoán (kiểm tra ngăn xếp khung?).

Như lời khuyên biên tập không được kiểm tra, tuy nhiên, tôi sẽ nói kiểm tra chức năng để xem liệu nó có được bọc như thế này đánh tôi một chút không. Bạn có thể tưởng tượng tất cả các loại hành vi không thể đoán trước đang chờ xảy ra khi một nhà phát triển mới đến dự án như tát trên một số trang trí khác. Trong thực tế, bạn cũng tiếp xúc với những thay đổi trong khuôn khổ django chính nó ... một nguy cơ bảo mật chờ đợi để xảy ra.

Tôi muốn giới thiệu phương pháp tiếp cận của Van Gale vì lý do đó là điều gì đó rõ ràng và do đó triển khai mạnh mẽ hơn nhiều.

+0

Khối mã đầu tiên của bạn sẽ không hoạt động như văn bản. my_decorator hủy bỏ chức năng được truyền cho nó, vì vậy việc đặt một lệnh in trong foo là vô ích. –

+0

Cảm ơn David, bạn nói đúng ... Tôi đã lướt qua khối đầu tiên để đến điểm chính mà không cần đọc kỹ những gì tôi đã gõ. Đánh giá cao bản chỉnh sửa. –

+0

Cảm ơn bạn đã trả lời sâu. Kết luận của bạn là những gì tôi đã làm, mặc dù tôi nghĩ rằng có thể có thêm một số "pythonic;" Tôi nghĩ rằng trong trường hợp của tôi làm điều này "đúng" cách là quá phức tạp và không phải là rất mạnh mẽ. –

3

Tôi sẽ chuyển một biến ngữ cảnh bổ sung vào mẫu.

Vì vậy, quan điểm cho rằng đã @login_required sẽ vượt qua một biến như private: True và các quan điểm khác sẽ vượt qua private: False

+0

Tôi đã kết thúc việc này trong thời gian ngắn. Hiệu quả hoàn hảo, nhưng không hoàn toàn là pythonic vì tôi có thể lấy được giá trị này từ sự vắng mặt của trang trí @login_required. –

1

Tại sao mẫu của bạn cần phải biết điều này? Nếu trình trang trí @login_required được sử dụng, chính chế độ xem sẽ ngăn những người không đăng nhập từ bao giờ truy cập trang và do đó không bao giờ thấy mẫu bắt đầu.

+0

Có lẽ mẫu được nhắc đến từ nhiều nơi, một số điểm vào có @login_required và một số không có. –

+0

Vâng, đó là những gì tôi giả định. –

+0

Blaird là chính xác. Mẫu là mẫu base.html của tôi, là mẫu gốc của tất cả các mẫu khác trên trang web của tôi. –

0

Mẫu có phân cấp vì vậy tại sao không có phiên bản @login_required và phiên bản "no @login_required", cả hai đều được kế thừa từ cùng một cấp độ gốc?

Điều này sẽ giữ cho các mẫu trở nên sạch hơn và dễ bảo trì hơn.

+0

Có một điểm khác biệt nhỏ. với những gì tôi muốn làm. Tôi wnat để kiểm tra xem của tôi cho dù một mẫu cụ thể được sử dụng, không thực hiện các hành vi mẫu đối diện. –

Các vấn đề liên quan