На некоторых страницах мы не хотим, чтобы анонимные пользователи могли получить доступ, например, к личным страницам и т. д. Доступ к такого рода страницам разрешен только зарегистрированным пользователям.В django у нас также есть больше способов добиться этого. .
Самый простой, мы оцениваем пользователя is_authenticated в viewz, но этот метод относительно неуклюж, в идеале мы, конечно, не хотим, чтобы этот запрос попадал в наше представление, и мы можем вернуть соответствующий ответ до этого, и Django фактически инкапсулировал связанные функции и занятия для нас.
декоратор login_required на основе режима fbv
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME,
login_url=None):
# 实际上这个方法也是调用is_authenticated去判断
pass
Способ применения также очень прост:
# fbv模式
from django.contrib.auth.decorators import login_required
@login_required
def user_info_view(request):
# 用户个人界面
pass
Затем мы надеемся, что если анонимный пользователь может быть перенаправлен на интерфейс входа в систему после доступа к этому интерфейсу, мы можем установить соответствующие параметры.Декоратор login_required будет читать settings.LOGIN_URL по умолчанию и перенаправлять на эту страницу.Если вы хотите быть более гибким , Затем мы также можем передать соответствующие параметры декоратору.
# fbv模式
@login_required(login_url='/login/', redirect_field_name='next')
def user_info_view(request):
# 用户个人界面
pass
login_url — это URL-адрес, перенаправляемый после доступа анонимного пользователя, обычно это страница входа.
redirect_field_name — это параметр запроса на получение
Предположим, что текущая страница будет /user/info/
Тогда URL-адрес перенаправления: /login/?next=/user/info/
Этот параметр можно использовать для возврата на эту страницу сразу после входа в систему, что будет подробно описано позже!
Класс LoginRequiredMixin на основе cbv
Блоггеры обычно используют режим cbv, в этом режиме мы перепишем методы get и post, теоретически для оформления этих двух методов можно использовать декоратор login_required.
# cbv模式
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
class UserInfoView(View):
@method_decorator(login_required(login_url='/login/', redirect_field_name='next'))
def get(self, request):
# 获取用户个人界面
pass
login_required — это декоратор функции, а method_decorator может преобразовать декоратор функции в декоратор метода. Если здесь еще есть пост-запрос, то нам придется писать такой код снова, что немного избыточно, поскольку мы используем классы для реализации, конечно, мы можем добиться этого за счет преимуществ классов! Наследовать LoginRequiredMixin!
from django.contrib.auth.mixins import LoginRequiredMixin
class UserInfoView(LoginRequiredMixin, View):
def get(self, request):
# 获取用户个人界面
pass
Итак, как реализован LoginRequiredMixin? посмотрите на исходный код
class LoginRequiredMixin(AccessMixin):
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated():
return self.handle_no_permission()
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
По сути, он переписывает метод диспетчеризации, потому что мы также наследуем представление. Фактически он переписывает функцию диспетчеризации в представлении. Если вы знаете логику представления, вы поймете, почему его можно реализовать именно так!
Когда мы вызываем ваш класс представления в URL-адресе, например, метод UserInfoView.as_view(), он вызывает dispatch(), который действует как диспетчер. Если запрос на получение сделан, то он вызывает метод get. Если Is почтовый запрос, затем вызовите метод post. Затем в диспетчере, чтобы определить, вошел ли пользователь в систему, конечно, может играть эту роль.
Затем, поскольку мы просто переписываем диспетчеризацию, мы также можем реализовать ее сами!
# 自定义LoginRequiredMixin
class LoginRequiredMixin(object):
@method_decorator(login_required(login_url='/login/', redirect_field_name='next'))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
Конечно, нужно ли реализовывать это самостоятельно, зависит от ваших собственных потребностей~
перенаправить и прыгать
(login_url='/login/', redirect_field_name='next')
Эти два параметра предоставляют нам URL-адрес перенаправления и перехода. Когда анонимный пользователь входит на страницу, на которой необходимо войти, он переходит на login_url. Этот запрос на получение также содержит параметр redirect_field_name со значением «далее». Если он посещает личную страницу, то переходите к
http://127.0.0.1/login/?next=/user/info/
Мы можем использовать этот параметр, чтобы сразу перейти на личную страницу после входа в систему.
class LoginView(View):
"""
用户登录逻辑
"""
def get(self, request):
# 获取到next参数,渲染到template中,在form表单添加一个hidden类型的元素
next = request.GET.get('next', '')
return render(request, "login.html", {'next': next})
def post(self, request):
login_form = LoginForm(request.POST)
if login_form.is_valid():
user_name = request.POST.get("username", "")
pass_word = request.POST.get("password", "")
next = request.POST.get('next', '')
user = authenticate(username=user_name, password=pass_word)
if user is not None:
if user.is_active:
login(request, user)
if next:
# 如果next存在,直接跳转到指定页面
return HttpResponseRedirect(next)
# 不存在跳转到index界面
return HttpResponseRedirect(reverse('index'))
else:
return render(request, "login.html", {"msg": "用户未激活"})
else:
return render(request, "login.html", {"msg": "用户名或密码错误"})
else:
return render(request, "login.html", {"login_form": login_form})
# login.html template form中添加
<input name="next" type="hidden" value="{{ next }}"/>
Распространенная проблема с переходом на страницу входа
Если обычная страница также хочет вернуться на исходную страницу после входа в систему, это очень просто.В запросе есть параметр пути, который представляет текущую страницу.Нам нужно только привести этот параметр при переходе к интерфейсу входа .
# template
<a class="loginbtn" href="/login/?next={{ request.path }}">登录</a>
<a class='logoutbtn' href="/logout/?next={{ request.path }}"退出</a>
<a class='registerbtn' href="/register/?next={{ request.path }}"注册</a>
Логика реализации входа такая же, как описано выше, фактически логика реализации интерфейса входа и регистрации одинакова.
# logout
class LogoutView(View):
def get(self, request):
next = request.GET.get('next', '')
logout(request)
try:
return HttpResponseRedirect(next)
except:
return HttpResponseRedirect(reverse('index'))
послесловие
В этой статье основное внимание уделяется использованию декоратора @login_required, а также использованию и настройке класса LoginReqiredMixin и, наконец, реализации перенаправления и перехода входа!