2010-04-27 30 views
18

Tôi đang sử dụng Khung tin nhắn Django để hiển thị thông báo cho người dùng cũng như trang trí @login_required trên một trong các chế độ xem của tôi. Vì vậy, nếu người dùng cố gắng truy cập một chế độ xem nhất định mà không cần đăng nhập, họ sẽ bị đưa đến trang đăng nhập. Làm thế nào tôi sẽ đi về việc thêm một thông báo lỗi cho trang đăng nhập nói "Để làm ... bạn phải đăng nhập". Tôi không thể thêm nó vào chế độ xem như bình thường vì người dùng không đăng nhập sẽ không bao giờ đến đó.Khung thông báo Django và login_required

Trả lời

13

Không có cách nào rõ ràng. Điều duy nhất cần lưu ý là viết phiên bản trang trí của riêng bạn để đặt một thông báo vào phiên trước khi chuyển hướng, sau đó nhận mẫu đăng nhập để hiển thị thông báo từ phiên.

Bạn sẽ cần phải sử dụng mã trong django.contrib.auth.decorators, đặc biệt là chức năng user_passes_test - bit thêm thông điệp sẽ phải đi trước return HttpResponseRedirect.

13

Tôi đã mất một thời gian để tìm ra một cách thoải mái để làm điều này, nhưng tôi nghĩ Tôi có một triển khai, dựa trên câu trả lời của Daniel Roseman

Điều đầu tiên tôi đã làm là tạo một trình trang trí để đặt thông báo khi người dùng không đăng nhập, giống như login_required.

Vì vậy, tôi đã viết login_required_message:

try: 
    from functools import wraps 
except ImportError: 
    from django.utils.functional import wraps # Python 2.4 fallback. 

from django.utils.decorators import available_attrs 

from django.contrib import messages 

default_message = "Please log in, in order to see the requested page." 

def user_passes_test(test_func, message=default_message): 
    """ 
    Decorator for views that checks that the user passes the given test, 
    setting a message in case of no success. The test should be a callable 
    that takes the user object and returns True if the user passes. 
    """ 
    def decorator(view_func): 
     @wraps(view_func, assigned=available_attrs(view_func)) 
     def _wrapped_view(request, *args, **kwargs): 
      if not test_func(request.user): 
       messages.error(request, message) 
      return view_func(request, *args, **kwargs) 
     return _wrapped_view 
    return decorator 

def login_required_message(function=None, message=default_message): 
    """ 
    Decorator for views that checks that the user is logged in, redirecting 
    to the log-in page if necessary. 
    """ 
    actual_decorator = user_passes_test(
     lambda u: u.is_authenticated(), 
     message=message, 
    ) 
    if function: 
     return actual_decorator(function) 
    return actual_decorator 

Với thi này bây giờ bạn có thể chú thích các phương pháp tầm nhìn của bạn như thế này:

from decorators import login_required_message 
from django.contrib.auth.decorators import login_required 

@login_required_message(message="You should be logged in, in order to see the index!") 
@login_required 
def index(request): 
    pass 

Bây giờ đầu tiên thông báo sẽ được thiết lập, sau đó chuyển hướng sẽ được thực hiện .

Tuy nhiên tôi thực sự không muốn thêm trang trí đăng nhập login_required_message ở mọi nơi. Sẽ đẹp hơn nếu chỉ có một người trang trí. Vì vậy, cho phép chuỗi chúng (chỉ cần thêm video này vào tập tin decorator.py của bạn sau khi login_required_message):

from django.contrib.auth import REDIRECT_FIELD_NAME 
from django.contrib.auth.decorators import login_required 

def login_required_message_and_redirect(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None, message=default_message): 

    if function: 
     return login_required_message(
      login_required(function, redirect_field_name, login_url), 
      message 
     ) 

    return lambda deferred_function: login_required_message_and_redirect(deferred_function, redirect_field_name, login_url, message) 

Tôi đã mất một thời gian để tìm ra dòng cuối cùng này; nhưng lambda để giải cứu!

Bây giờ bạn có thể thay thế hai trang trí chỉ bằng login_required_message_and_redirect: Hầu như ở đó! Vì thực sự tôi muốn sử dụng phương thức login_required_message mới này ở khắp mọi nơi, tôi thêm một miếng vá khỉ cho login_required và nó được sử dụng ở khắp mọi nơi (một lần nữa thêm vào dưới cùng của tệp decorators.py)!

from django.contrib.auth import decorators 
setattr(decorators, 'login_required', login_required_message_and_redirect) 

cho phép tôi gọi:

# a message will appear, since login_required is monkey patched 
@login_required 
def logout(request): 
    pass 

# or customize the message per view 
@login_required(message="You should be logged in message! Available after monkey patch") 
def index(request): 
    pass 
Các vấn đề liên quan