Làm thế nào để yêu cầu đăng nhập cho Django Generic Views?


87

Tôi muốn hạn chế quyền truy cập vào các URL do Django Generic Views xử lý.

Đối với Chế độ xem của tôi, tôi biết rằng login_requiredngười trang trí thực hiện công việc. Ngoài ra Tạo / Xóa / Cập nhật Chế độ xem Chung cũng lấy login_requiredđối số, nhưng tôi không thể tìm cách thực hiện việc này cho các Chế độ xem Chung khác.

Câu trả lời:


104

Đối với Django <1,5, bạn có thể thêm trình trang trí bằng cách gói hàm trong các url của mình, điều này cho phép bạn bọc các chế độ xem chung:

from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
    )

Các chế độ xem chung dựa trên chức năng không được chấp nhận trong Django 1.4 và đã bị xóa trong Django 1.5. Nhưng nguyên tắc tương tự cũng được áp dụng, chỉ cần bọc hàm xem của chế độ xem dựa trên lớp với trình login_requiredtrang trí:

login_required(TemplateView.as_view(template_name='foo_index.html'))

Đây là cách chỉ định login_url login_required (TemplateView.as_view (template_name = 'foo_index.html'))
Saisiva A

101

Django 1.9 hoặc sử dụng dấu ngoặc nhọn django

Django 1.9 đã giới thiệu một LoginRequiredMixin được sử dụng như vậy:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Nếu bạn đang sử dụng phiên bản django cũ hơn, bạn có thể sử dụng khá nhiều bản mixin tương tự từ django-niềng - phiên bản Django dựa trên phiên bản django-niềng. django -ces 1.4.x vẫn hỗ trợ Django 1.4 nên các bạn có thể sử dụng với các phiên bản khá cũ.

Phương pháp cũ hơn

Tôi đã tìm thấy câu hỏi này khi tìm kiếm trên Google về cách trang trí các khung nhìn dựa trên lớp học, vì vậy, để thêm câu trả lời cho điều đó:

Điều này được đề cập trong phần tài liệu về cách trang trí các khung nhìn dựa trên lớp . Có urls.pytrình bao bọc, hoặc bạn có thể áp dụng trình trang trí cho dispatch()phương thức. Ví dụ từ tài liệu:

Trang trí trong conf URL

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = patterns('',
    (r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
    (r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)

Trang trí lớp học

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(ProtectedView, self).dispatch(*args, **kwargs)

Xem tài liệu được liên kết ở trên để biết thêm chi tiết.


TUYỆT VỜI! nhưng tôi đã tạo một lớp đơn giản chỉ với def dispatchphương thức là lớp con của View. Bây giờ tôi chỉ có thể làm một cái gì đó như thế này:class ProtectedTemplateView(TemplateView, ProtectedView): pass
WBAR

nếu tôi không đặt login_url nhưng đặt cái này trên settings.py thì nó có chuyển hướng đến cái này theo mặc định không?
Marat Mkitaryan

38

Các chế độ xem chung đã thay đổi từ chức năng thành đối tượng với phiên bản 1.3 của Django. Do đó, cần có một chút thay đổi để câu trả lời của Will McCutchen và Will Hardy hoạt động với phiên bản 1.3:

from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

urlpatterns = patterns('',
    (r'^foo/$', login_required(TemplateView.as_view(template_name='foo_index.html'))),
)

Ngoài ra, tài liệu cũng mô tả cách thực hiện điều này.


2
Xin độc giả lưu ý câu trả lời này vì thời gian trôi qua và phần mềm phát triển. Giải pháp đầu tiên không hiệu quả với tôi.
n3storm

12

Nếu bạn không muốn viết trình bao bọc mỏng của riêng mình xung quanh các chế độ xem chung được đề cập (như Aamir đã đề xuất), bạn cũng có thể làm điều gì đó như sau trong urls.pytệp của mình :

from django.conf.urls.defaults import *

# Directly import whatever generic views you're using and the login_required
# decorator
from django.views.generic.simple import direct_to_template
from django.contrib.auth.decorators import login_required

# In your urlpatterns, wrap the generic view with the decorator
urlpatterns = patterns('',
    (r'', login_required(direct_to_template), {'template': 'index.html'}),
    # etc
)

8

Đối với django 1.11, Bạn có thể sử dụng LoginRequiredMixin cho Chế độ xem dựa trên lớp

trong tệp cài đặt, bạn nên thêm

LOGIN_URL="/login/"

trong views của bạn.py

from django.contrib.auth.mixins import LoginRequiredMixin

class RestaurantLocationCreateView(LoginRequiredMixin,CreateView):
    ....

8

Một cách khác để đạt được điều này là bên dưới, tôi thích rằng nó khá giống với cách nó được thực hiện với các khung nhìn dựa trên chức năng và không yêu cầu sửa đổi urls.pyhoặc ghi đè dispatch:

@method_decorator(login_required, name='dispatch')
class YourGenericViewSubclass(TemplateView):
    #
    # View methods
    #

3

Tôi muốn một cách có thể sử dụng lại để yêu cầu xác thực trên nhiều chế độ xem bắt nguồn từ các chế độ xem chung. Tôi đã tạo một hàm điều phối thay thế mà tôi có thể thêm vào lớp xem của mình theo cách giống như các khai báo khác.

class Index(generic.ListView):
    model = models.HomePage
    dispatch = auth.dispatch

auth.dispatch là nơi chúng tôi thực hiện công việc:

def dispatch(self, request, *args, **kw):
    """Mix-in for generic views"""
    if userSession(request):
        return  super(self.__class__, self).dispatch(request, *args, **kw)

    # auth failed, return login screen
    response = user(request)
    response.set_cookie('afterauth', value=request.path_info)
    return response


1

Sử dụng như sau:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here

5
Dựa trên ngày của câu hỏi, tôi giả sử OP đang yêu cầu một giải pháp cho các khung nhìn chung dựa trên lớp của django ... không phải các khung nhìn dựa trên hàm.
Dolph

0

Sau đây có thể giải quyết vấn đề này.

// in views.py:
class LoginAuthenAJAX(View):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            jsonr = json.dumps({'authenticated': True})
        else:
            jsonr = json.dumps({'authenticated': False})
        return HttpResponse(jsonr, content_type='application/json')

// in urls.py
    path('login_auth', views.LoginAuthenAJAX.as_view(), name="user_verify"),

//in xxx.html
<script src = “{% static “xxx/script.js” %}” 
var login_auth_link = “{%  url ‘user_verify’ %}”
</script>

// in script.js
        $.get(login_auth_link, {
            'csrfmiddlewaretoken' : csrf_token,
            },
            function(ret){
                if (ret.authenticated == false) {
                    window.location.pathname="/accounts/login/"
                }
                $("#message").html(ret.result);
            }
        )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.