参考文献https://blog.csdn.net/wolaiye320/article/details/51942928 https://www.cnblogs.com/chadiandianwenrou/p/7516224.html
使用User对象
- User实例一般从request.user,或是其他下面即将要讨论到的方法取得,它有很多属性和方法。AnonymousUser对象模拟了部分的接口,但不是全部,在把它当成真正的user对象使用前,你得检查一下user.is_authenticated()
User对象属性 属性 描述 username 必填; 少于等于30字符. 只允许字符,数字,下划线 first_name 可选; 少于等于30字符. last_name 可选; 少于等于30字符. email 可选. 邮件地址. password 必填. 密码的摘要hash(Django不会存储原始密码),详见密码章节部分 is_staff 布尔值. 用户是否拥有网站的管理权限. is_active 布尔值. 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录 is_superuser 布尔值. 用户是否拥有所有权限,而无需任何显示的权限分配定义 last_login 用户最后登录的时间,缺省会设置为当前时间 date_joined 创建用户的时间,当用户创建时,缺省的设置为当前的时间 User对象方法 方法 描述 is_authenticated() 如果是真正的 User对象,返回值恒为True。 用于检查用户是否已经通过了认证。通过认证并不意味着 用户拥有任何权限,甚至也不检查该用户是否处于激活状 态,这只是表明用户成功的通过了认证。 is_anonymous() 如果是个 AnonymousUser,返回值为True, 如果是 User对象,返回值为False。一般来 说,is_authenticated()会比这个方法更常用些。 get_full_name() 返回值为: first_name加上last_name,以 空格分隔。 set_password(passwd) 将用户的密码设置为给定的字符串,实际密码已被哈希 处理。这时并不会真正保存 User对象。 check_password(passwd) 如果给定的字符串通过了密码检查,返回 True。 密码比较已进行了哈希处理。 get_group_permissions() 返回用户通过所属组获得的权限列表 get_all_permissions() 返回用户通过所属组和用户自身权限所获得的所有权限 列表。 has_perm(perm) 如果用户拥有给定的权限,返回 True,perm应形如 "package.codename"的格式。如果用户处于 非激活状态,则总是返回False。 has_perms(perm_list) 如果用户拥有所有给定的权限,返回 True。 如果用户处于非激活状态,则总是返回False。 has_module_perms(app_label) 如果用户拥有任何给定 app_label的权限,返回True。如果用户处于非激活状态,则总是返回False get_and_delete_messages() 返回用户的 Message对象列表,并从队列中删除。 email_user(subj, msg) 给用户发送电子邮件,用 DEFAULT_FROM_EMAIL的设 置作为发件人。也可以用第3个参数from_email来 覆盖设置。 get_profile() 返回用户的网站自定义profile,详见Profile章节 - User对象有两个多对多的属性:groups和permissions。User对象可以象使用其他多对多属性的方法一样使用它们
# Set a user's groups: myuser.groups = group_list # Add a user to some groups: myuser.groups.add(group1, group2,...) # Remove a user from some groups: myuser.groups.remove(group1, group2,...) # Remove a user from all groups: myuser.groups.clear() # Permissions work the same way myuser.permissions = permission_list myuser.permissions.add(permission1, permission2, ...) myuser.permissions.remove(permission1, permission2, ...) myuser.permissions.clear()
-
重写User模型
-
Django内置的User模型可能不适合某些项目,我们可能要基于内置的添加一些字段,首先start一个app users用于用户管理
django-admin startapp users
-
编写users app下的models.py
from django.db import models from django.contrib.auth.models import AbstractUser class UserProfile(AbstractUser): nick_name = models.CharField(...) birday = models.DateField(...) gender = models.CharField(...) address = models.CharField(...) mobile = models.CharField(...) image = models.ImageField(upload_to='image/%Y/%m', default='image/default.png', max_length=100) class Meta: verbose_name = "用户信息" verbose_name_plural = "用户信息" def __str__(self): return self.username
-
然后修改settings.py配置文件,覆盖默认的user模型
'''是app的名称,和models里的class名称(表名)''' AUTH_USER_MODEL = "users.UserProfile"
-
登录和登出
- Django 提供内置的视图(view)函数用于处理登录和退出,但在开始前,我们来看看如何手工登录和退出,Django在django.contrib.auth中提供了两个函数来处理这些事情——authenticate()和login()。
authenticate()函数可以用于鉴定用户名和密码是否配对。它接受两个参数,用户标识(通常默认的是username)和密码password,如果密码正确会返回一个User对象;错误则返回None
>>> from django.contrib import auth >>> user = auth.authenticate(username='john', password='secret') >>> if user is not None: ... print("Correct!") ... else: ... print("Oops, that's wrong!")
-
而要登录一个用户,应该使用login(),该函数接受一个HttpRequest对象和一个User对象作为参数并使用Django的会话(session)框架把用户的ID保存在该会话中。下面的例子演示了如何在一个视图中同时使用authenticate()和login()函数
from django.contrib import auth def login(request): username = request.POST['username'] password = request.POST['password'] user = auth.authenticate(username=username, password=password) if user is not None and user.is_active: # Correct password, and the user is marked "active" auth.login(request, user) # Redirect to a success page. return HttpResponseRedirect("/account/loggedin/") else: # Show an error page return HttpResponseRedirect("/account/invalid/")
-
登出,在你的视图中使用django.contrib.auth.logout()。该函数接受一个HttpRequest对象作为参数,没有返回值。
from django.contrib import auth def logout(request): auth.logout(request) # Redirect to a success page. return HttpResponseRedirect("/account/loggedout/")
注意,即使用户没有登录,logout()也不会抛异常。
自定义登录验证
- 如何实现通过email和用户名都能登录呢?就需要重写authenticate方法
from django.shortcuts import render from django.contrib.auth import authenticate, login from django.contrib.auth.backends import ModelBackend from django.db.models import Q from .models import UserProfile # 重写的authenticate登录验证 class CustomBackend(ModelBackend): def authenticate(self, username=None, password=None, **kwargs): try: user = UserProfile.objects.get(Q(username=username) | Q(email=username)) # 检测username和password是否匹配 if user.check_password(password): return user except Exception as e: return None # 登录方法 def acc_login(request): if request.method == 'POST': user_name = request.POST.get('username', '') pass_word = request.POST.get('password', '') user = authenticate(username=user_name, password=pass_word) # 通过settings.py的配置,我们自定义的认证函数会被加入到一个序列中,并通过django.contrib.auth.authenticate 调用 if user is not None: if user.is_active: login(request, user) # 调用django的login return render(request, 'index.html') else: return render(request, 'login.html', {'msg': '用户未激活'}) else: return render(request, 'login.html', {'mgs': '用户名或密码错误'}) elif request.method == 'GET': return render(request, 'login.html')
需要注意的是,覆写的authenticate方法,应该返回一个user对象或None
-
settings.py
AUTHENTICATION_BACKENDS = ('users.views.CustomBackend',)
至此,就支持邮箱和用户名登录了
简单的权限控制
-
限制匿名用户的访问
-
有很多原因需要控制用户访问站点的某部分,一个简单原始的限制方法是检查request.user.is_authenticated(),然后重定向到登陆页面
from django.http import HttpResponseRedirect def my_view(request): if not request.user.is_authenticated(): return HttpResponseRedirect('/login/?next=%s' % request.path) # 或者显示一个出错信息: return render_to_response('myapp/login_error.html')
-
作为一个快捷方式,你可以使用便捷的@login_required装饰器
from django.contrib.auth.decorators import login_required @login_required def my_view(request): # @login_required做下面的事情: # 如果用户没有登录,重定向到登录页面,把当前绝对URL作为next在查询字符串中传递过去,例如:/accounts/login/?next=/polls/3/ # 如果用户已经登录,正常地执行视图函数。
要自动重定向到登录页面,必须在settings.py中设置LOGIN_URL
LOGIN_URL = '/user/login/'
当然,你也可以根据业务需要自定义装饰器
-
-
限制已登录用户的访问
-
可以通过某种权限校验,或某些特定的检查,这些实现方式大致相同。一般的方法是直接在视图函数中的request.user上运行检查。例如,下面视图检查用户登陆并是否有polls.can_vote的权限:
def vote(request): if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')): # vote here else: return HttpResponse("You can't vote in this poll.")
但其实,django提供了一个更优雅的方式来实现以上操作
from django.contrib.auth.decorators import user_passes_test def user_can_vote(user): return user.is_authenticated() and user.has_perm("polls.can_vote") @user_passes_text(user_can_vote, login_url="/login/") def vote(request): # vote here
user_passes_test使用一个必需的参数:一个可调用的方法,它存在User对象并当此用户允许查看该页面时返回True。注意user_passes_test不会自动检查User是否认证,你应该自己做这件事。例子中我们也展示了第二个可选的参数login_url,它让你指定你的登录页面的URL(默认为settings.LOGIN_URL)。
既然检查用户是否有一个特殊权限是相对常见的任务,Django为这种情形提供了一个捷径:@permission_required()装饰器使用这个装饰器,前面的例子可以这样写
from django.contrib.auth.decorators import permission_required @permission_required('polls.can_vote', login_url="/login/") def vote(request): # ..
注意,permission_required()也有一个可选的login_url参数,这个参数默认为settings.LOGIN_URL。
-