2008-11-23 31 views
47

Tôi muốn thêm một số Ajax -niceness vào trang web được mã hóa Django của tôi.Xác thực Django và Ajax - URL yêu cầu đăng nhập

Trong mã Django của tôi, tôi sử dụng trang trí @login_required từ django.contrib.auth.decorators để đánh dấu chế độ xem nào yêu cầu xác thực. Hành vi mặc định khi người dùng không được xác thực nhấp vào đó là chuyển hướng người đó đến trang đăng nhập và sau đó chuyển trang đích.

Những gì tôi thấy trên một số trang web và thực sự thích là khi người dùng nhấp vào liên kết dẫn đến địa điểm bị hạn chế người dùng chỉ đăng nhập, thay vì được chuyển hướng đến trang đăng nhập, họ sẽ có cửa sổ bật lên (qua JavaScript) yêu cầu họ đăng nhập hoặc đăng ký. Không có phần chuyển hướng, vì vậy không cần người dùng sử dụng phím "quay lại" nếu anh/cô ấy quyết định anh/cô ấy thực sự không thích trang web đủ để lãng phí thời gian đăng ký.

Vì vậy, câu hỏi là: bạn sẽ quản lý nhiệm vụ tự động đánh dấu một số liên kết là "bị hạn chế" để JavaScript có thể xử lý sự kiện onclick và hiển thị cửa sổ bật lên "vui lòng đăng nhập"?

Trả lời

53

I đang phải đối mặt với cùng một vấn đề, và, giống như bạn, tôi muốn một trang trí đơn giản để bọc xung quanh một cái nhìn Django ajax để xử lý xác thực theo cùng một cách mà tôi có quan điểm khác. Một cách tiếp cận có vẻ đầy hứa hẹn đối với tôi là sử dụng trình trang trí như vậy kết hợp với JavaScript tìm kiếm một giá trị nhất định trong phản hồi.

Đây là đầu tiên dự thảo sửa đổi của trang trí:

from functools import wraps 

def ajax_login_required(view_func): 
    @wraps(view_func) 
    def wrapper(request, *args, **kwargs): 
     if request.user.is_authenticated(): 
      return view_func(request, *args, **kwargs) 
     json = simplejson.dumps({ 'not_authenticated': True }) 
     return HttpResponse(json, mimetype='application/json') 
    return wrapper 

Dưới đây là quan điểm:

@ajax_login_required 
def ajax_update_module(request, module_slug, action): 
    # Etc ... 
    return HttpResponse(json, mimetype='application/json') 

Và đây là các hoạt Javascript (jQuery):

$.post('/restricted-url/', data, function(json) { 
    if (json.not_authenticated) { 
     alert('Not authorized.'); // Or something in a message DIV 
     return; 
    } 
    // Etc ... 
}); 

EDIT: Tôi đã cố gắng sử dụng functools.wraps, như được đề xuất. Tôi đã không thực sự sử dụng trang trí này trong mã làm việc, vì vậy hãy cẩn thận của các lỗi có thể.

+6

Có thể đáng để chỉ ra rằng bạn có thể sử dụng trang trí 'functools.wraps' quanh' def wrap' để tránh các bài tập cho 'wrap .__ doc__',' wrap .__ dict__', và 'wrap .__ name__' (không phải đã đề cập trong câu trả lời này nhưng nên được thực hiện). Xem http://docs.python.org/library/functools.html#functools.wraps – quodlibetor

+2

@EricWalker có thể cập nhật bài đăng sau đó? :) –

+0

@Anders: vui lòng tiếp tục và chỉnh sửa phản hồi để kết hợp thay đổi. Tôi đã không làm việc trong Python một thời gian, và tôi không muốn làm hỏng nó. –

5

Âm thanh như khả năng mẫu trang.

  1. Bạn có thể vượt qua một LINK_VIA (hoặc một cái gì đó) mà bạn cung cấp càng onClick="return popup(this, 'arg')" hoặc None. Mỗi liên kết sẽ là <A HREF="link" {{LINK_VIA}}>some text</a>.

    • Đối với phiên ẩn danh, LINK_VIA có giá trị.
    • Đối đăng nhập phiên, LINK_VIA là Không
  2. Bạn có thể sử dụng một tuyên bố {% if %} xung quanh <A HREF=...> thẻ của bạn. Điều này có vẻ dài dòng.

  3. Bạn có thể viết thẻ tùy chỉnh của riêng mình cho {% link_via %}. Tôi không quen thuộc với điều này, nhưng bạn có thể cung cấp liên kết và văn bản dưới dạng chuỗi và thẻ của bạn có thể tạo một trong hai loại liên kết.

+0

Những gì tôi đang tự hỏi là làm thế nào để xác định từ quan điểm của mẫu nếu chế độ xem mà liên kết dẫn đến được trang trí bằng @login_required hoặc không ... – kender

+0

Mẫu không có liên kết ngẫu nhiên. Nó có các liên kết cụ thể mà bạn thiết kế và mã hóa cụ thể trong mẫu. Tôi đề nghị bạn thay đổi mỗi liên kết bạn đặt cụ thể trong mẫu. –

5

tôi sẽ đồng ý với S.Lott

Hãy kiểm tra trong mẫu, nếu người dùng đang đăng nhập, chỉ cần đặt các liên kết như thường lệ, nếu không muốn nói, đặt một cái gì đó giống như

<a href="{{link}}" onclick="return login_popup()"> 

nơi login_popup sẽ trả về false nếu người dùng nói hủy.

Điều này có thể có thể được thực hiện dễ dàng hơn nhiều trong Jinja2 thông qua macros.

Nếu mẫu không biết url nào yêu cầu người dùng đăng nhập, bạn có thể cần phải xem xét lại thiết kế của mình.

Nếu bạn phải, tôi đoán bạn có thể làm điều tương tự mà trình điều phối url django thực hiện để khám phá chức năng xem.
xem: django.core.urlresolvers

khi bạn đã nắm bắt chức năng chế độ xem, bạn có thể kiểm tra xem trang web có được @login_required hay không.

Điều này có thể được thực hiện trong thẻ tùy chỉnh.
Nếu bạn sử dụng Jinja2, bạn sẽ không cần thẻ, chỉ cần thực hiện chức năng và hiển thị nó cho Môi trường, nó đơn giản nhưng bạn sẽ phải làm một chút đọc trên API của Jinja2)

+0

Tôi cực kỳ muộn với bữa tiệc này, nhưng bất cứ điều gì: Đây không phải là lý tưởng chỉ vì người dùng có thể đã theo một liên kết trực tiếp đến trang được đề cập, trong trường hợp đó, phương pháp popup yêu cầu đăng nhập ở đây sẽ bị hỏng. –

+0

Điều này làm tôi đau mắt. –

1

Dưới đây là đề xuất phiên bản của trang trí với bọc .__ doc__, quấn .__ name__

from functools import wraps 

def ajax_login_required(function): 
    def wrap(request, *args, **kwargs): 
     if request.user.is_authenticated(): 
      return function(request, *args, **kwargs) 
     json = simplejson.dumps({ 'not_authenticated': True }) 
     return HttpResponse(json, mimetype='application/json') 
    wrap.__doc__ = function.__doc__ 
    wrap.__name__ = function.__name__ 
    return wrap 
0

Built tắt của giải pháp Eric Walker's, nhưng đối với Django 2,0

# Standard Imports 
import functools 
import django.http 

def ajax_login_required(view_func): 
    @functools.wraps(view_func) 
    def wrapper(request, *args, **kwargs): 
     if request.user.is_authenticated: 
      return view_func(request, *args, **kwargs) 

     return django.http.JsonResponse('Unauthorized', status=401, safe=False) 

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