ต้องการล็อกอินสำหรับ Django Generic Views ได้อย่างไร?


88

ฉันต้องการ จำกัด การเข้าถึง URL ที่จัดการโดย Django Generic Views

สำหรับมุมมองของฉันฉันรู้ว่าlogin_requiredมัณฑนากรทำงานได้ดี นอกจากนี้การสร้าง / ลบ / อัปเดตมุมมองทั่วไปยังใช้login_requiredอาร์กิวเมนต์ แต่ฉันไม่พบวิธีดำเนินการนี้กับมุมมองทั่วไปอื่น ๆ

คำตอบ:


104

สำหรับ Django <1.5 คุณสามารถเพิ่มมัณฑนากรได้โดยการตัดฟังก์ชันใน URL ของคุณซึ่งจะช่วยให้คุณสามารถรวมมุมมองทั่วไปได้:

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'}),
    )

มุมมองทั่วไปตามฟังก์ชันเลิกใช้แล้วใน Django 1.4 และถูกลบออกใน Django 1.5 แต่ก็ใช้หลักการเดียวกันเพียงห่อฟังก์ชั่นมุมมองของมุมมองตามคลาสด้วยlogin_requiredมัณฑนากร:

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

วิธีระบุlogin_url login_required (TemplateView.as_view (template_name = 'foo_index.html'))
Saisiva A

103

Django> = 1.9 หรือใช้ django-braces

Django 1.9 ได้แนะนำLoginRequiredMixinที่ใช้ดังนี้:

from django.contrib.auth.mixins import LoginRequiredMixin

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

หากคุณใช้ django รุ่นเก่ากว่าคุณสามารถใช้ mixin เดียวกันจากdjango-braces ได้ - เวอร์ชัน Django นั้นใช้เวอร์ชัน django-braces django-braces 1.4.x ยังรองรับ Django 1.4ดังนั้นคุณจึงสามารถใช้กับเวอร์ชันเก่า ๆ ได้

วิธีการที่เก่ากว่า

ฉันพบคำถามนี้ในขณะที่ googling เกี่ยวกับวิธีตกแต่งมุมมองตามชั้นเรียนดังนั้นเพื่อเพิ่มคำตอบสำหรับสิ่งนั้น:

นี้จะครอบคลุมในส่วนเอกสารเกี่ยวกับการตกแต่งมุมมองระดับพื้นฐาน มีurls.pyกระดาษห่อหุ้มหรือคุณสามารถใช้มัณฑนากรกับdispatch()วิธีการ ตัวอย่างจากเอกสารประกอบ:

การตกแต่งใน URL conf

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())),
)

ตกแต่งชั้นเรียน

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)

ดูเอกสารที่ลิงก์ด้านบนสำหรับรายละเอียดเพิ่มเติม


สุดยอด! แต่ฉันสร้างคลาสง่ายๆด้วยdef dispatchเมธอดเท่านั้นที่เป็นคลาสย่อยของView. ตอนนี้ฉันสามารถทำสิ่งนี้ได้:class ProtectedTemplateView(TemplateView, ProtectedView): pass
WBAR

ถ้าฉันไม่ได้ตั้งค่า login_url แต่ตั้งค่านี้ใน settings.py จะเปลี่ยนเส้นทางเป็นค่าเริ่มต้นหรือไม่
Marat Mkhitaryan

38

มุมมองทั่วไปได้เปลี่ยนจากฟังก์ชันเป็นวัตถุด้วย Django เวอร์ชัน 1.3 ดังนั้นจึงมีการเปลี่ยนแปลงเล็กน้อยที่จำเป็นสำหรับคำตอบของ Will McCutchen และ Will Hardy ในการทำงานกับเวอร์ชัน 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'))),
)

นอกจากนี้เอกสารยังอธิบายวิธีการทำเช่นนี้ด้วย


2
โปรดผู้อ่านคำนึงถึงคำตอบนี้เนื่องจากเวลาผ่านไปและซอฟต์แวร์มีการพัฒนา วิธีแก้ปัญหาแรกไม่ได้ผลสำหรับฉัน
n3storm

12

หากคุณไม่ต้องการเขียนกระดาษห่อบาง ๆ ของคุณเองรอบ ๆ มุมมองทั่วไปที่เป็นปัญหา (ตามที่ Aamir แนะนำ) คุณสามารถทำสิ่งนี้ในurls.pyไฟล์ของคุณได้:

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

สำหรับ django 1.11 คุณสามารถใช้ LoginRequiredMixin สำหรับมุมมองตามคลาส

ในไฟล์การตั้งค่าคุณควรเพิ่ม

LOGIN_URL="/login/"

ใน views.py ของคุณ

from django.contrib.auth.mixins import LoginRequiredMixin

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

8

อีกวิธีหนึ่งในการบรรลุสิ่งนี้คือด้านล่างฉันชอบที่มันค่อนข้างคล้ายกับการทำด้วยมุมมองตามฟังก์ชันและไม่จำเป็นต้องแก้ไขurls.pyหรือลบล้างdispatch:

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

3

ฉันต้องการวิธีที่ใช้ซ้ำได้ในการกำหนดให้มีการตรวจสอบสิทธิ์ในหลาย ๆ มุมมองที่มาจากมุมมองทั่วไป ฉันสร้างฟังก์ชันการจัดส่งทดแทนซึ่งฉันสามารถเพิ่มลงในคลาสมุมมองของฉันในลักษณะเดียวกับการประกาศอื่น ๆ

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

auth.dispatch คือที่ที่เราทำงาน:

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

3

ใน Django => 3.0 มันค่อนข้างง่าย:

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

@method_decorator(login_required(login_url='/login/'), name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

สำหรับการอ้างอิง: https://docs.djangoproject.com/en/3.0/topics/class-based-views/intro/#decorating-the-class


1

ใช้สิ่งต่อไปนี้:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here

5
จากวันที่ของคำถามฉันคิดว่า OP กำลังขอวิธีแก้ปัญหาสำหรับมุมมองทั่วไปตามคลาสของ django ... ไม่ใช่มุมมองตามฟังก์ชัน
Dolph

0

สิ่งต่อไปนี้สามารถแก้ปัญหานี้ได้

// 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);
            }
        )

0

ฉันพยายามหาคำตอบมานานจนพบวิธีแก้ปัญหานี้

ใน models.py do: จากโมเดลการนำเข้า django.db

class YourLoginModel:
      fullname = models.CharField(max_length=255, default='your_name', unique=True)
      email  = models.EmailField(max_length=255, unique=True)
      username = models.CharField(max_length=255, unique=True)
      password = models.CharField(max_length=255) #using werkzeug's 
                                                  #generate_password_hash on plaintext password before committing to database model

ใน form.py ทำ:

from django import forms
from .models import YourLoginModel

class LoginForm(forms.ModelForm):
      class Meta:
            model = YourLoginModel
            fields = ('username', 'password')

ในตรรกะการเข้าสู่ระบบ views.py:

def login(request):
    #login logic here
     # init empty form
    form = LoginForm()

    if request.method == 'POST':

        try:
            # peforms a Select query in db and gets user with log in username
            user_logging_in = User.objects.get(username=request.POST['username'])

            # assign user hash to var
            hash = user_logging_in.password

            # assign form str passs word to var
            password = request.POST['password']

        # if the user does not exist
        except ObjectDoesNotExist:
            html_response = 'User does not exists'
            return HttpResponse(html_response)

        # peform password and hash check
        if check_password_hash(hash, password):
 
            #using sessions cookies to know who we're interacting with
            request.session['username'] = request.POST['username']

            #set expiry date of the session
            request.session.set_expiry(0) # 0 means when the browser is closed

            return redirect('yourapp:home')
        else:
            return HttpResponse('password was incorrect')

    html = 'Login'
    return render(request, 'login.html', {'form': form})

ในมุมมองแอปคุณต้องการดำเนินการ login_required ใน do

from django.views.generic import TemplateView

class yourTemplateView(TemplateView):
      template_name = 'your_template.html'
      def dispatch(self, request, *args, **kwrags):
           if not request.session.has_key('username'):
              #return HttpResponse('not logged in')
              return redirect('yourapp:login.html')
           else:
              return render(request, 'your_view.html')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.