• Authentication of Django


    Django Authentication 用户认证系统


    一、 Django的认证系统

    Django自带一个用户认证系统,用于处理用户账户、群组、许可和基于cookie的用户会话。

    1.1 概览

    Django的认证系统包含了身份验证和权限管理两部分。简单地说,身份验证用于核实某个用户是否是合法用户,权限管理则是决定一个合法用户具有哪些权限。这里,“身份验证”这个词同时代指上面两部分的含义。

    系统主要包括:

    • 用户
    • 许可
    • 可配置的密码哈希系统
    • 用于用户登录或者限制访问的表单和视图工具
    • 可插拔的后端

    类似下面的问题,请使用第三方包:

    • 密码强度检查
    • 登录请求限制
    • 第三方认证

    1.2 安装

    默认情况下,使用django-admin startproject命令后,认证相关的模块已经自动添加到settings文件内了,如果没有的话,请手动添加。

    在 INSTALLED_APPS配置项中:

    1. 'django.contrib.auth': 包含认证框架的核心以及默认模型
    2. 'django.contrib.contenttypes':内容类型系统,用于给模型关联许可

    在MIDDLEWARE配置项中:

    1. SessionMiddleware:通过请求管理会话
    2. AuthenticationMiddleware:将会话和用户关联

    当配置正确后,运行manage.py migrate命令,创建用户认证系统相关的数据库表以及分配预定义的权限。

    二、 使用Django的认证系统

    2.1 用户对象

    默认的用户包含下面的属性:

    • username
    • password
    • email
    • first_name
    • last_name

    2.1.1 创建用户

    最直接的办法是使用 create_user()功能:

    >>> from django.contrib.auth.models import User
    >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
    # 这时,user是一个User类的实例,已经保存在了数据库内,你可以随时修改它的属性,例如:
    >>> user.last_name = 'Lennon'
    >>> user.save()
    

    如果你已经启用了Django的admin站点,你也可以在web页面上创建用户。

    2.1.2 创建超级用户

    使用createsuperuser命令

    $ python manage.py createsuperuser --username=joe --email=joe@example.com
    

    根据提示输入名字、密码和邮箱地址。

    2.1.3 修改密码

    Django默认会对密码进行加密,因此,不要企图对密码进行直接操作。这也是为什么要使用一个帮助函数来创建用户的原因。

    要修改密码,有两个办法:

    1. 使用命令行: manage.py changepassword username。如果不提供用户名,则会尝试修改当前系统用户的密码。
    2. 使用set_password()方法:
    from django.contrib.auth.models import User
    u = User.objects.get(username='john')
    u.set_password('new password')
    u.save()
    

    同样可以在admin中修改密码。
    Django提供了views和forms,方便用户自己修改密码。
    修改密码后,用户的所有当前会话将被注销。

    2.1.4 用户验证

    authenticate(**credentials)[source]:

    通常接收username与password作为参数进行认证。在认证后端中,有一项通过则返回一个User类对象,一项都没通过或者抛出了PermissionDenied异常,则返回一个None。例如:

    from django.contrib.auth import authenticate
    user = authenticate(username='john', password='secret')
    if user is not None:
        # A backend authenticated the credentials
    else:
        # No backend authenticated the credentials
    

    2.2 权限与授权

    Django提供了一个权限系统用于它的admin站点,当然你也可以在你的代码中使用。
    使用方法:

    • 必须有“add”授权的用户才可以访问add页面
    • 必须有“change”授权的用户才可以访问change list页面
    • 必须有“delete”授权的用户才可以删除对象

    ModelAdmin类提供了 has_add_permission(),has_change_permission()和has_delete_permission()三个方法。User表的对象有两个多对多的字段,groups和user_permissions,可以像普通的model一样访问他们。

    myuser.groups.set([group_list])
    myuser.groups.add(group, group, ...)
    myuser.groups.remove(group, group, ...)
    myuser.groups.clear()
    myuser.user_permissions.set([permission_list])
    myuser.user_permissions.add(permission, permission, ...)
    myuser.user_permissions.remove(permission, permission, ...)
    myuser.user_permissions.clear()
    

    2.2.1 默认权限

    默认情况下,使用manage.py migrate命令时,Django会给每个已经存在的model添加默认的权限。
    假设你现在有个app叫做foo,有个model叫做bar,使用下面的方式可以测试默认权限:

    add: user.has_perm('foo.add_bar')
    change: user.has_perm('foo.change_bar')
    delete: user.has_perm('foo.delete_bar')
    

    2.2.2 组

    Django提供了一个django.contrib.auth.models.Group模型,该model可用于给用户分组,实现批量管理。用户和组属于多对多的关系。用户自动具有所属组的所有权限。

    2.2.3 在代码中创建权限

    例如,你可以为myapp中的BlogPost模型添加一个can_publish权限。

    from myapp.models import BlogPost
    from django.contrib.auth.models import Permission
    from django.contrib.contenttypes.models import ContentType
    
    content_type = ContentType.objects.get_for_model(BlogPost)
    permission = Permission.objects.create(
        codename='can_publish',
        name='Can Publish Posts',
        content_type=content_type,
    )
    

    然后,你可以通过User模型的user_permissions属性或者Group模型的permissions属性为用户添加该权限。

    2.2.4 权限缓存

    权限检查后,会被缓存在用户对象中。参考下面的例子:

    from django.contrib.auth.models import Permission, User
    from django.shortcuts import get_object_or_404
    
    def user_gains_perms(request, user_id):
        user = get_object_or_404(User, pk=user_id)
        # any permission check will cache the current set of permissions
        user.has_perm('myapp.change_bar')
    
        permission = Permission.objects.get(codename='change_bar')
        user.user_permissions.add(permission)
    
        # Checking the cached permission set
        user.has_perm('myapp.change_bar')  # False
    
        # Request new instance of User
        # Be aware that user.refresh_from_db() won't clear the cache.
        user = get_object_or_404(User, pk=user_id)
    
        # Permission cache is repopulated from the database
        user.has_perm('myapp.change_bar')  # True
    
        ...
    

    2.3 在Web请求中的认证

    Django使用session和中间件在请求对象中钩住认证系统。

    每一次请求中都包含一个request.user属性。如果该用户未登陆,该属性的值是AnonymousUser,如果已经登录,该属性就是一个User模型的实例。

    可以使用is_authenticated方法进行判断,如下:

    if request.user.is_authenticated:
    # Do something for authenticated users.
    ...
    else:
        # Do something for anonymous users.
        ...
    

    2.3.1 如何登录用户

    login(request, user, backend=None)[source]:

    在视图中,使用login()方法登录用户。它接收一个HttpRequest参数和一个User对象参数。该方法会把用户的ID保存在Django的session中。下面是一个认证和登陆的例子:

    from django.contrib.auth import authenticate, login
    
    def my_view(request):
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            # 跳转到成功页面
            ...
        else:
            # 返回一个非法登录的错误页面
            ...
    

    2.3.2 如何注销用户

    logout(request)[source]:

    from django.contrib.auth import logout
    
    def logout_view(request):
        logout(request)
        # Redirect to a success page.
    

    注意,被logout的用户如何没登录,不会抛出错误。
    一旦logout,当前请求中的session数据都会被清空。

    2.3.3 登陆用户访问限制

    原始的办法

    在request.user.is_authenticated中重定向到登录页面,如下所示:

    from django.conf import settings
    from django.shortcuts import redirect
    
    def my_view(request):
        if not request.user.is_authenticated:
            return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
        # ...
    

    或者显示一个错误信息:

    from django.shortcuts import render
    
    def my_view(request):
        if not request.user.is_authenticated:
            return render(request, 'myapp/login_error.html')
        # ...
    

    使用装饰器

    login_required(redirect_field_name='next', login_url=None)[source]

    from django.contrib.auth.decorators import login_required
    
    @login_required
    def my_view(request):
        ...
    

    该装饰器工作机制:

    • 如果用户未登陆,重定向到settings.LOGIN_URL,传递当前绝对路径作为url字符串的参数,例如:/accounts/login/?next=/polls/3/
    • 如果用户已经登录,执行正常的视图

    此时,默认的url中使用的参数是“next”,如果你想使用自定义的参数,请修改login_required()的redirect_field_name参数,如下所示:

    from django.contrib.auth.decorators import login_required
    
    @login_required(redirect_field_name='my_redirect_field')
    def my_view(request):
        ...
    

    如果你这么做了,你还需要重新定制登录模板,因为它引用了redirect_field_name变量。

    login_required()方法还有一个可选的longin_url参数。例如:

    from django.contrib.auth.decorators import login_required
    
    @login_required(login_url='/accounts/login/')
    def my_view(request):
        ...
    

    注意:如果不指定login_url参数,请确保你的settings.LOGIN_URL和登陆视图保持正确的关联。例如:

    from django.contrib.auth import views as auth_views
    url(r'^accounts/login/$', auth_views.login),
    

    使用LoginRequired mixin

    通过继承LoginRequiredMixin类的方式。
    在多继承时,该类必须是最左边的父类。
    class LoginRequiredMixin(New in Django 1.9.)

    根据raise_exception参数的不同,对于未登陆的用户请求,响应不同的结果。

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
        login_url = '/login/'
        redirect_field_name = 'redirect_to'
    

    进行测试,根据结果决定动作

    你也可以直接在视图中进行过滤:

    from django.shortcuts import redirect
    
    def my_view(request):
        if not request.user.email.endswith('@example.com'):
            return redirect('/login/?next=%s' % request.path)
        # ...
    
    • user_passes_test(test_func,login_url=None,redirect_field_name='next')[source]
      该装饰器当调用的返回值是Fasle的时候重定向。
    from django.contrib.auth.decorators import user_passes_test
    
    def email_check(user):
        return user.email.endswith('@example.com')
    
    @user_passes_test(email_check)
    def my_view(request):
        ...
    

    对于上面的例子,email_check接收一个User对象作为参数,当其返回值是True时,允许执行下面的my_view视图,否则不允许。

    user_passes_test()有两个可选的参数:login_url和redirect_field_name。前者是跳转的url后者是url参数字符串。例如:

    @user_passes_test(email_check, login_url='/login/')
    def my_view(request):
        ...
    
    • class UserPassesTestMixin

    继承该类,重写test_func()方法:

    from django.contrib.auth.mixins import UserPassesTestMixin
    
    class MyView(UserPassesTestMixin, View):
    
        def test_func(self):
            return self.request.user.email.endswith('@example.com')
    

    也可以重写get_test_func()方法,指定自定义的名称用于替代默认的test_func。

    权限需求装饰器

    permission_required(perm, login_url=None, raise_exception=False)[source]

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('polls.can_vote')
    def my_view(request):
        ...
    

    类似has_perm()方法。权限的格式是<app label>.<permission codename>

    可选的longin_url参数:

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('polls.can_vote', login_url='/loginpage/')
    def my_view(request):
        ...
    

    raise_exception参数如果给予,装饰器会抛出PermissionDenied异常,并且用403页面代替重定向的登陆页面。例如:

    from django.contrib.auth.decorators import login_required, permission_required
    
    @login_required
    @permission_required('polls.can_vote', raise_exception=True)
    def my_view(request):
        ...
    

    PermissionRequiredMixin类

    同上面的loginrequiredmixin类似。

    from django.contrib.auth.mixins import PermissionRequiredMixin
    
    class MyView(PermissionRequiredMixin, View):
        permission_required = 'polls.can_vote'
        # Or multiple of permissions:
        permission_required = ('polls.can_open', 'polls.can_edit')
    

    可以自定义重写get_permission_required()和has_permission()方法

    2.3.4 在基于类的视图中重定向未授权的请求

    class AccessMixin:

    • login_url
      get_login_url()方法的默认回调函数。

    • permission_denied_message
      拒绝访问的提示信息。默认是空字符串。

    • redirect_field_name
      get_redirect_field_name()的返回值. 默认是"next".

    • raise_exception
      抛出异常。默认为False。

    • get_login_url()

    • get_permission_denied_message()

    • get_redirect_field_name()

    • handle_no_permission()¶

    2.3.5 认证视图

    Django没有为认证视图提供默认的模板,你需要自己创建。

    使用视图

    有很多种办法实现这些视图,最简单的是使用Django提供的django.contrib.auth.urls,将它添加到URLconf文件中:

    urlpatterns = [
    url('^', include('django.contrib.auth.urls')),
    ]
    

    这就相当于添加了下面的URL模式:

    ^login/$ [name='login']
    ^logout/$ [name='logout']
    ^password_change/$ [name='password_change']
    ^password_change/done/$ [name='password_change_done']
    ^password_reset/$ [name='password_reset']
    ^password_reset/done/$ [name='password_reset_done']
    ^reset/(?P<uidb64>[0-9A-Za-z_-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$ [name='password_reset_confirm']
    ^reset/done/$ [name='password_reset_complete']
    

    其中,方括号里的是url的别名。
    当然,也可以使用自定义的URL,例如:

    from django.contrib.auth import views as auth_views

    urlpatterns = [
    url('^change-password/$', auth_views.password_change),
    ]

    这些views有一些可选的参数。例如template_name,用于指定视图需要使用的html模板,看下面的例子:

    urlpatterns = [
        url(
            '^change-password/$', auth_views.password_change,
            {'template_name': 'change-password.html'}
        ),
    ]
    

    所有的这类views都返回一个TemplateResponse实例,对于自定义views可以将Django提供的view封装起来使用,例如:

    from django.contrib.auth import views
    
    def change_password(request):
        template_response = views.password_change(request)
        # Do something with `template_response`
        return template_response
    

    所有的认证视图

    下面是django.contrib.auth模块包含的所有视图:

    login(request, template_name=registration/login.html, redirect_field_name='next', authentication_form=AuthenticationForm, current_app=None, extra_context=None, redirect_authenticated_user=False)

    登录视图

    URL name:login (该视图对应的访问地址,下同)

    可选参数:

    template_name: 登录页面html文件名。默认为registration/login.html。

    redirect_field_name: 用于登录URL路径的参数关键字,默认是“next”。

    authentication_form:用于认证的调用,默认是AuthenticationForm。

    current_app: 2.0版本中将被移除,用request.current_app代替。

    extra_context: 额外的数据字典

    redirect_authenticated_user:一个布尔值,用于控制已登陆用户是否可以访问登录页面。默认是False。

    django.contrib.auth.views.login视图的工作机制是:
    使用GET请求时,显示一个登陆表单,用户可以输入登录信息。
    使用POST请求时,携带用户提供的登陆信息,进行用户验证。如果验证成功,重定向到next参数指定的url地址(如果未指定next参数,则使用settings.LOGIN_REDIRECT_URL中配置的地址,该地址默认为/accounts/profile/),如果不成功,继续显示表单页面。

    Django不提供registration/login.html模板文件,需要自己编写。该模板有4个环境变量:

    1. form:一个表示AuthenticationForm的Form对象
    2. next:登录成功后重定向的url地址
    3. site:当前的Site,根据SITE_ID设置。如果没有安装site框架,则被设置为一个RequestSite的实例,它将从HttpRequest中导出site名和域名。
    4. site_name:site.name的别名。如果没安装site框架,它将被设置为request.META['SERVER_NAME']的值。

    也可以不使用默认的registration/login.html模板,而是指定别的模板,使用template_name参数,如下:

    url(r'^accounts/login/$', auth_views.login, {'template_name': 'myapp/login.html'}),
    

    这里有一个registration/login.html模板的简单例子(假定你已经有了base.html文件)。

    {% extends "base.html" %}
    
    {% block content %}
    
    {% if form.errors %}
    <p>Your username and password didn't match. Please try again.</p>
    {% endif %}
    
    {% if next %}
        {% if user.is_authenticated %}
        <p>Your account doesn't have access to this page. To proceed,
        please login with an account that has access.</p>
        {% else %}
        <p>Please login to see this page.</p>
        {% endif %}
    {% endif %}
    
    <form method="post" action="{% url 'login' %}">
    {% csrf_token %}
    <table>
    <tr>
        <td>{{ form.username.label_tag }}</td>
        <td>{{ form.username }}</td>
    </tr>
    <tr>
        <td>{{ form.password.label_tag }}</td>
        <td>{{ form.password }}</td>
    </tr>
    </table>
    
    <input type="submit" value="login" />
    <input type="hidden" name="next" value="{{ next }}" />
    </form>
    
    {# Assumes you setup the password_reset view in your URLconf #}
    <p><a href="{% url 'password_reset' %}">Lost password?</a></p>
    
    {% endblock %}
    

    如果使用自定义认证系统,可以通过authentication_form参数,指定你自定义的认证form显示在登录页面中。这个form必须接受一个request关键字参数在它的__init__方法中,并且提供一个get_user()方法用于返回通过认证的user对象。

    logout(request, next_page=None, template_name='registration/logged_out.html', redirect_field_name='next', current_app=None, extra_context=None)

    注销视图

    URL name: logout
    可选参数:

    • next_page: 注销后跳转的页面。默认是settings.LOGOUT_REDIRECT_URL。
    • template_name: 注销后跳转的页面html文件.默认是registration/logged_out.html
    • redirect_field_name: 同上
    • current_app: 同上
    • extra_context:同上

    模板变量:

    • title:字符串“Logged out”
    • site:同上
    • site_name:同上
    logout_then_login(request, login_url=None, current_app=None, extra_context=None)

    注销用户,并返回登录页面。

    URL name:未设置

    可选参数:

    • login_url:同上
    • current_app: 同上
    • extra_context:同上
    password_change(request, template_name='registration/password_change_form.html', post_change_redirect=None, password_change_form=PasswordChangeForm, current_app=None, extra_context=None)¶

    用户修改密码的页面

    URL name:password_change

    可选参数:

    • template_name:用于显示修改密码表单的页面文件。默认是registration/password_change_form.html。
    • post_change_redirect:成功修改后跳转的url
    • password_change_form:自定义的“change password”表单,它必须接收一个user关键字参数。默认为PasswordChangeForm。
    • current_app: 同上
    • extra_context:同上

    模板变量:

    • form:修改密码的表单
    password_change_done(request, template_name='registration/password_change_done.html', current_app=None, extra_context=None)

    用户修改完密码后的页面。

    URL name: password_change_done

    可选参数:

    • template_name:用于显示修改密码表单的页面文件。默认是registration/password_change_form.html。
    • current_app: 同上
    • extra_context:同上
    password_reset(request, template_name='registration/password_reset_form.html', email_template_name='registration/password_reset_email.html', subject_template_name='registration/password_reset_subject.txt', password_reset_form=PasswordResetForm, token_generator=default_token_generator, post_reset_redirect=None, from_email=None, current_app=None, extra_context=None, html_email_template_name=None, extra_email_context=None)¶

    生成一个一次性的连接,并将该连接发送到用户注册的邮箱地址,用户通过改地址重置他的密码。

    为了防止潜在的攻击,如果提供的邮件地址在系统中不存在,视图不会发送邮件,用户也不会受到任何的错误信息提示。如果想要提供错误信息的话,继承PasswordResetForm类,并使用password_reset_form参数。

    URL name: password_reset

    可选参数:

    • template_name: 同上。默认是registration/password_reset_form.html。
    • email_template_name:发送携带重置密码连接的邮件的页面。默认是registration/password_reset_email.html。
    • subject_template_name:邮件的主题,默认是registration/password_reset_subject.txt。
    • password_reset_form: 同上
    • token_generator:检查一次性连接的类的实例。默认是default_token_generator,它是django.contrib.auth.tokens.PasswordResetTokenGenerator的一个实例。
    • post_reset_redirect: 同上
    • from_email: 发件人地址。默认是DEFAULT_FROM_EMAIL。
    • current_app: 同上
    • extra_context:同上
    • html_email_template_name: 默认情况下HTML email不发送。
    • extra_email_context: email模板中额外的数据字典。

    模板变量:

    • form:同上

    email模板变量:

    • email:user.email的别名
    • user:当前user。只有有效的用户才可以重置他们的密码(User.is_active is True)。
    • site_name:同上
    • domain:site.domain的别名。如果没有安装site框架,则为request.get_host()。
    • protocol: http或者https协议
    • uid: 用户的主键,基于64位。
    • token: 用于检查重置连接合法性的令牌

    一个简单的registration/password_reset_email.html文件范例:

    Someone asked for password reset for email {{ email }}. Follow the link below:
    {{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
    
    password_reset_done(request, template_name='registration/password_reset_done.html', current_app=None, extra_context=None)

    密码重置后的跳转页面
    URL name: password_reset_done

    可选参数:

    • template_name: 同上。默认是registration/password_reset_done.html。
    • current_app: 同上
    • extra_context:同上
    password_reset_confirm(request, uidb64=None, token=None, template_name='registration/password_reset_confirm.html', token_generator=default_token_generator, set_password_form=SetPasswordForm, post_reset_redirect=None, current_app=None, extra_context=None)

    显示一个输入新密码的表单

    URL name: password_reset_confirm

    可选参数:

    • uidb64: 同上,默认为None。
    • token: 检查密码是否合法的令牌,默认为None.
    • template_name: 同上,默认为registration/password_reset_confirm.html.
    • token_generator: 同上
    • set_password_form: 用于设置密码的表单。默认为SetPasswordForm。
    • post_reset_redirect: 同上,默认为None。
    • current_app: 同上
    • extra_context: 同上

    模板变量:

    • form: 同上
    • validlink: 布尔值。链接合法则为True。
    password_reset_complete(request, template_name='registration/password_reset_complete.html', current_app=None, extra_context=None)

    提示用户密码已经成功修改

    URL name: password_reset_complete

    可选参数:

    • template_name: 同上,默认为registration/password_reset_confirm.html.
    • current_app: 同上
    • extra_context: 同上

    2.3.6 有用的函数

    redirect_to_login(next, login_url=None, redirect_field_name='next')

    重定向到登录页面,登录成功后跳转到指定的url。

    必须参数:next,登录成功后跳转的url
    可选参数:longin_url和redirect_field_name

    2.3.7 内置表单

    如果你不想使用内置的视图,但又不想编写表单,认证系统提供了内置的表单供你直接使用,它们位于django.contrib.auth.forms。

    class AdminPasswordChangeForm

    admin中用于修改用户密码的表单。user是它的第一位置参数。

    class AuthenticationForm

    登录表单,request是它的第一位置参数。

    confirm_login_allowed(user):默认情况下,它拒绝is_active标识为False的用户。要修改这个规则,你需要继承AuthenticationForm类,并重写confirm_login_allowed()方法。如果给予的用户没有登录,它应该抛出一个ValidationError异常。

    例如,允许所有用户登录,不管它是否active:

    from django.contrib.auth.forms import AuthenticationForm
    
    class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
        def confirm_login_allowed(self, user):
            pass
    

    或者只允许某些状态的用户登录:

    class PickyAuthenticationForm(AuthenticationForm):
        def confirm_login_allowed(self, user):
            if not user.is_active:
                raise forms.ValidationError(
                    _("This account is inactive."),
                    code='inactive',
                )
            if user.username.startswith('b'):
                raise forms.ValidationError(
                    _("Sorry, accounts starting with 'b' aren't welcome here."),
                    code='no_b_users',
                )
    

    class PasswordChangeForm

    用户修改自己密码的表单

    class PasswordResetForm

    一个表单,用于生成和发送带有一次性连接的邮件,帮助用户重置密码。

    send_email(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None)

    发送邮件的方法。
    参数:

    • subject_template_name – 主题模板
    • email_template_name – 邮件主题模板
    • context – 传递给subject_template, email_template和html_email_template 的数据
    • from_email – 发件人
    • to_email – 收件人
    • html_email_template_name

    class SetPasswordForm

    设置密码的表单

    class UserChangeForm

    admin中修改用户信息和权限的表单

    class UserCreationForm

    创建新用户的ModelForm。它有3个字段,username、password1和password2.

    2.3.8 模板中的认证数据

    用户

    渲染一个RequestContext模板时,当前已登陆的用户,或者一个User实例,或者一个 AnonymousUser实例,都被保存在模板的变量{{ user }}中。例如:

    {% if user.is_authenticated %}
        <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
    {% else %}
        <p>Welcome, new user. Please log in.</p>
    {% endif %}
    

    如果不是使用的RequestContext,这些变量将不可用。

    权限

    当前登陆用户的权限保存在模板变量 {{ perms }}中。它是一个django.contrib.auth.context_processors.PermWrapper的实例。

    对于{{ perms }}对象,单级属性查询相当于User.has_module_perms的功能。例如:
    {{ perms.foo }},如果登陆用户有任何foo的权限,该变量就等于True。

    双级属性查询相当于User.has_perm。例如:{{ perms.foo.can_vote }}

    因此,你可以在if语句中使用它们,如下面的例子所示:

    {% if perms.foo %}
        <p>You have permission to do something in the foo app.</p>
        {% if perms.foo.can_vote %}
            <p>You can vote!</p>
        {% endif %}
        {% if perms.foo.can_drive %}
            <p>You can drive!</p>
        {% endif %}
    {% else %}
        <p>You don't have permission to do anything in the foo app.</p>
    {% endif %}
    

    还可以使用关键字“in”,进行范围判断:

    {% if 'foo' in perms %}
        {% if 'foo.can_vote' in perms %}
            <p>In lookup works, too.</p>
        {% endif %}
    {% endif %}
    

    2.4 在admin站点中管理用户

    当django.contrib.admin与django.contrib.auth都被安装时,可以在admin站点中方便的对用户、组和权限进行管理。

  • 相关阅读:
    JGrouseDoc使用(原创)
    MVP*2
    《天气与生活》修正近日总是显示数据有误的问题
    [Vista Gadget] 《农历小助手》和《天气与生活》发布新版
    Vista Sidebar gadget development(dropping)
    微软要干掉ADOBE?
    [JS]根据格式字符串分析日期(MM与自动匹配两位的09和一位的9),货币分析成浮点数
    Vista问题二则
    腾讯公司内部信息平台部门招聘.net资深开发工程师和项目经理
    ClientSortableTableExtender Ajax toolkit Extender(源码以后再发布和讲解)
  • 原文地址:https://www.cnblogs.com/feixuelove1009/p/6253553.html
Copyright © 2020-2023  润新知