2012-06-10 22 views
7

Ứng dụng Django của tôi hiện có URL được bảo vệ bởi các chức năng 'permission_required()'.Tìm các quyền bắt buộc của các URL Django mà không cần gọi chúng?

Chức năng này được gọi theo ba cách khác nhau.

  1. Là trang trí trong views.py, với thông số được mã hóa cứng.
  2. Là một hàm đơn giản, với thông số được tạo tự động, trong Chế độ xem chung dựa trên lớp tùy chỉnh.
  3. Là một hàm gọi chế độ xem trong urls.py, với thông số được mã hóa cứng.

Tôi hiện đang thêm hệ thống menu vào ứng dụng và tôi cần thực hiện các mục menu cho biết người dùng có quyền yêu cầu URL của từng mục nhập trình đơn hay không. (Hoặc bằng cách chuyển sang màu xám hoặc ẩn các mục đã nói.)

Có cách nào để truy vấn các quyền cần thiết cho URL mà không cần yêu cầu URL không?

Giải pháp duy nhất mà tôi đã nghĩ đến cho đến nay là thay thế trang trí bằng một trình trang trí không tham số 'menu_permssion_required()' và mã hóa tất cả các quyền vào cấu trúc Python. Điều này có vẻ giống như một bước lùi, như tùy chỉnh của tôi dựa trên lớp Generic Views đã autogenerate quyền yêu cầu của họ.

Bất kỳ đề xuất nào về cách tạo hệ thống menu phản ánh quyền URL cho người dùng hiện tại?

+0

Tôi luôn mã hóa các menu trong các mẫu, nó đơn giản và cho phép các menu ngữ cảnh với {% extends%}. – jpic

+0

@jplc xin lỗi, tôi không thể hiểu được nhận xét của bạn liên quan đến câu hỏi như thế nào. Điều này đặc biệt về quyền. Quyền được cắt ngang, không được liên kết với tiền tố URL hoặc tương tự. – fadedbee

+0

Bạn có thể kiểm tra các quyền trong mẫu: https://gist.github.com/25c03f286337c66cc860 Đây là tiêu chuẩn khá trong các dự án django từ những gì tôi đã thấy, đây là tài liệu về mô-đun django perms được đề cập: https: // docs.djangoproject.com/en/1.0/topics/auth/#id6 Tuy nhiên, quan điểm của tôi là thời gian làm cho một "hệ thống" cho một menu HTML có thể được chi tiêu tốt hơn cho những thứ khác. – jpic

Trả lời

2

Dưới đây là một ví dụ về cách giải quyết vấn đề của bạn:

Đầu tiên, tạo một wrapper trang trí để sử dụng thay vì permission_required:

from django.contrib.auth.decorators import login_required, permission_required, user_passes_test 
from django.core.exceptions import PermissionDenied 
from functools import wraps 
from django.utils.decorators import available_attrs 

def require_perms(*perms): 
    def decorator(view_func): 
     view_func.permissions = perms 
     @wraps(view_func, assigned=available_attrs(view_func)) 
     def _wrapped_view(request, *args, **kwargs): 
      for perm in perms: 
       return view_func(request, *args, **kwargs) 
      raise PermissionDenied() 
     return _wrapped_view 
    return decorator 

Sau đó, sử dụng nó để trang trí quan điểm của bạn:

@require_perms('my_perm',) 
def home(request): 
..... 

Sau đó, thêm thẻ để sử dụng cho các mục menu của bạn:

from django.core.urlresolvers import resolve 

def check_menu_permissions(menu_path, user): 
    view = resolve(menu_path) 
    if hasattr(view.func, "permissions"): 
     permissions = view.func.permissions 
     for perm in permissions: 
      if user.has_perm(perm): 
       return True # Yep, the user can access this url 
      else: 
       return False # Nope, the user cannot access this url 
    return True # or False - depending on what is the default behavior 

Và cuối cùng, trong các mẫu của bạn, khi xây dựng cây menu:

<button href="{{ some_path }} {% if not check_menu_permissions some_path request.user %}disabled="disabled"{% endif %} /> 

N.B. Tôi đã không thử nghiệm phần cuối cùng với thẻ, nhưng tôi hy vọng bạn có ý tưởng. Điều kỳ diệu ở đây là thêm quyền vào view_func trong trình trang trí, và sau đó bạn có thể truy cập điều này bằng cách sử dụng giải quyết (đường dẫn). Tôi không chắc làm thế nào điều này sẽ hành xử về hiệu suất, nhưng sau khi tất cả đó chỉ là một ý tưởng.

EDIT: Chỉ cần cố định một lỗi trong ví dụ ..

+0

Cảm ơn, tôi thích ý tưởng chung. Tôi sẽ cho bạn biết làm thế nào nó hoạt động trong thực tế trước khi kết thúc tháng (thời hạn dự án). – fadedbee

2

Có cách nào truy vấn các quyền cần thiết cho URL mà không yêu cầu URL không?

User.has_perm()User.has_module_perms()

Bất kỳ đề xuất về cách để thực hiện một hệ thống menu mà phản ánh quyền URL cho người dùng hiện tại?

Tôi thực sự thích câu hỏi này, bởi vì nó liên quan đến bất kỳ ai tạo trang web với django, vì vậy tôi thấy nó thực sự có liên quan. Tôi đã trải qua điều đó và thậm chí là coded a menu "system" trong dự án django đầu tiên của tôi vào năm 2008. Nhưng kể từ đó tôi đã thử Pinax, và một trong những thứ (rất nhiều) tôi học được từ các dự án mẫu của họ là nó hoàn toàn không cần thiết.

Vì vậy, tôi không có đề xuất nào tôi sẽ hỗ trợ về cách tạo menu "hệ thống" tôn trọng quyền yêu cầu của người dùng.

Tôi có đề xuất về cách tạo một menu đơn giản tôn trọng quyền yêu cầu của người dùng để có thể không hoàn toàn không liên quan.

  1. Chỉ cần chắc menu của bạn dưới dạng HTML đồng bằng, nó không giống như nó sẽ thay đổi như vậy thường là nó phải được tạo ra. Điều đó cũng sẽ giữ mã Python của bạn đơn giản hơn.

  2. Thêm vào settings.TEMPLATE_CONTEXT_PROCESSORS: 'django.core.context_processors.PermWrapper'

  3. Sử dụng {{ perms }} proxy để User.has_perms.

Ví dụ:

{% if perms.auth %} 
    <li class="divider"></li> 

    {% if perms.auth.change_user %} 
    <li> 
     <a href="{% url admin:auth_user_changelist %}">{% trans 'Users' %}</a> 
    </li> 
    {% endif %} 

    {% if perms.auth.change_group %} 
    <li> 
     <a href="{% url admin:auth_group_changelist %}">{% trans 'User groups' %}</a> 
    </li> 
    {% endif %} 

{% endif %} 
{# etc, etC#} 

Đó là cách tôi tiếp tục chuyển hướng đơn giản, ngu ngốcra khỏi con đường. Nhưng tôi cũng luôn luôn bao gồm an autocomplete không xa các menu để cho phép người dùng điều hướng đến bất kỳ trang chi tiết nào một cách dễ dàng. Vì vậy, đó là tất cả những gì tôi biết về điều hướng trong các dự án django, tôi mong muốn đọc các câu trả lời khác!

1

Tôi đã có một vấn đề tương tự, nhưng nó đã đi sâu hơn một chút. Thay vì chỉ cho phép, tôi cũng muốn các thử nghiệm khác dựa trên người dùng đã đăng ký (ví dụ: is_staff hoặc user.units.count() > 1). Sao chép những thứ này trong chế độ xem và mẫu có vẻ dễ bị lỗi.

Bạn có thể quan sát đối tượng xem và xem tất cả các trang trí bao quanh nó và tìm ra nếu chúng là séc (trong trường hợp của tôi: đối số đầu tiên tôi muốn u hoặc user). Nếu tất cả đều trôi qua, thì hãy cho phép hiển thị liên kết.

Get all decorators wrapping a function mô tả kỹ thuật chi tiết hơn một chút. Bạn có thể tìm thấy ứng dụng kết thúc tốt đẹp việc này thành một sự thay thế tiện dụng cho {% url %} tại Django-menus.

+0

Cảm ơn, tôi sẽ có một cái nhìn tại Django-menu và xem nếu nó làm những gì tôi yêu cầu. Nếu cuối cùng tôi phải tự viết mã này (khi tôi sử dụng trang trí tùy chỉnh của mình), tôi sẽ đi với câu trả lời của Tisho, vì nó ít đáng kể hơn 'ma thuật'. – fadedbee

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