在使用authenticate
进行验证后,如果验证通过了。那么会返回一个user
对象,拿到user
对象后,可以使用django.contrib.auth.login
进行登录。示例代码如下:
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
注销,或者说退出登录。我们可以通过django.contrib.auth.logout
来实现。他会清理掉这个用户的session
数据。
有时候,某个视图函数是需要经过登录后才能访问的。那么我们可以通过django.contrib.auth.decorators.login_required
装饰器来实现。示例代码如下:
再在settings
中配置好AUTH_USER_MODEL='youapp.User'
models.py
class User(AbstractBaseUser,PermissionsMixin):
telephone = models.CharField(max_length=11,unique=True)
email = models.CharField(max_length=50,unique=True)
username = models.CharField(max_length=100)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'telephone'
objects = UserManager()
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
class UserManager(BaseUserManager):
def _create_user(self,telephone,username,password,**kwargs):
if not telephone:
raise ValueError('必须要传递手机号码!')
if not password:
raise ValueError('必须要传递密码!')
user = self.model(telephone=telephone,username=username,**kwargs)
user.set_password(password)
user.save()
return user
def create_user(self,telephone,username,password,**kwargs):
kwargs['is_superuser'] = False
return self._create_user(telephone=telephone,username=username,password=password,**kwargs)
def create_superuser(self,telephone,username,password,**kwargs):
kwargs['is_superuser'] = True
return self._create_user(telephone=telephone,username=username,password=password,**kwargs)
forms.py
class LoginForm(forms.ModelForm):
remember = forms.IntegerField(required=False)
telephone = forms.CharField(max_length=11)
class Meta:
model = User
fields = ['password']
view.py
def jicheng_view(request):
# user = User.objects.create_superuser(telephone='1888888888',password='123456',username="testxiaoxiao")
# print(user.username) 创建记录
telephone = request.GET.get('telephone')
password = request.GET.get('password')
user = authenticate(request,username=telephone,password=password)
if user:
print("驗證成功 %s" % user.username)
else:
print("失敗")
return HttpResponse("成功")
def my_login(request):
if request.method == 'GET':
return render(request,'login.html')
else:
forms = LoginForm(request.POST)
if forms.is_valid():
telephone = forms.cleaned_data.get("telephone")
password = forms.cleaned_data.get("password")
remember = forms.cleaned_data.get("remember")
user = authenticate(request,username=telephone,password=password)
if user:
login(request,user)
if remember:
request.session.set_expiry(None)
else:
request.session.set_expiry(0)
next_url = request.GET.get('next')#判断后边是否有next
if next_url:
return redirect(next_url) #如果有跳转到next
else:
return HttpResponse("登錄成功")
else:
return HttpResponse("用戶名或者密碼錯誤")
else:
print(forms.errors.get_json_data())
return redirect(reverse('login'))
def my_logout(request):
logout(request) 把请求传给 logout 就是退出登录
return HttpResponse("成功退出登錄")
#这个装饰器为了 想要查看 个人中心 必须先登 #login_url="/login/" 如果你没有登录 先要跳转到登录页面 但是 跳转的登录地址 不是咱们想要的 如果指定登录的地址 必须加上 login_url="/login/
@login_required(login_url="/login/")
def profile(request):
return HttpResponse("登錄成功以後才可以查看的個人中心")
1.使用django 自带的用户系统
2.需要重新定制
3.前后台使用同一个user系统
#自定义user模型
1.单独创建一个应用app 用来存放 用户操作系统 xiaofanzhuoauth
2.全部重写 AbstactBaseUser
3.UserManager 需要重新写
4.在settings.py中设置 AUTH_USER_MODEL = "应用.User"
5.映射到数据库中
6.自增长的id 使用 shortuuid 前提需要 pip install django-shortuuidfield
# 登录逻辑
1.先用我们准备好的那个 登录页面 测试
然后 后期 前后都用一个登录页面
2.因为前后都用一个user系统
前台ajax 提交过来 提交过来 是 json 数据
3.所有的登录逻辑全部写在 xiaofanzhuoauth
如果验证失败了,那么有一些错误信息是我们需要传给前端的。这时候我们可以通过以下属性来获取:
form.errors
:这个属性获取的错误信息是一个包含了html标签的错误信息。
form.errors.get_json_data()
:这个方法获取到的是一个字典类型的错误信息。将某个字段的名字作为key,错误信息作为值的一个字典。
form.as_json(
):这个方法是将form.get_json_data()返回的字典dump成json格式的字符串,方便进行传输。
上述方法获取的字段的错误值,都是一个比较复杂的数据。比如以下:
{'username': [{'message': 'Enter a valid URL.', 'code': 'invalid'}, {'message': 'Ensure this value has at most 4 characters (it has 22).', 'code': 'max_length'}]}
那么如果我只想把错误信息放在一个列表中,而不要再放在一个字典中。这时候我们可以定义一个方法,把这个数据重新整理一份。实例代码如下:
class MyForm(forms.Form):
username = forms.URLField(max_length=4)
def get_errors(self):
errors = self.errors.get_json_data()
new_errors = {}
for key,message_dicts in errors.items():
messages = []
for message in message_dicts:
messages.append(message['message'])
new_errors[key] = messages
return new_errors
这样就可以把某个字段所有的错误信息直接放在这个列表中。
丢给前端一个地址 地址里边是 json数据 前端将json转为 js 然后 显示在页面上
前端通过接口地址 提交数据 给 后台完成数据的增删改查
GET 查
PUT 改
POST 增
DELETE 删除
我们需要判断 用户过来的请求方式 :
Django
中内置了权限的功能。他的权限都是针对表或者说是模型级别的。比如对某个模型上的数据是否可以进行增删改查操作。他不能针对数据级别
的,比如对某个表中的某条数据能否进行增删改查操作(如果要实现数据级别的,考虑使用django-guardian
)。创建完一个模型后,针对这个模型默认就有三种权限,分别是增/删/改/。可以在执行完migrate
命令后,查看数据库中的auth_permission
表中的所有权限。
如何获取settings.py中的 AUTH_USER_MODEL = 'news.User'
其中的codename
表示的是权限的名字。name
表示的是这个权限的作用。
如果我们想要增加新的权限,比如查看某个模型的权限,那么我们可以在定义模型的时候在Meta
中定义好。示例代码如下:
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(get_user_model(),on_delete=models.CASCADE)
class Meta:
permissions = (
('view_article','can view article'),
)
权限都是django.contrib.auth.Permission
的实例。这个模型包含三个字段,name
、codename
以及content_type
,其中的content_type
表示这个permission
是属于哪个app
下的哪个models
。用Permission
模型创建权限的代码如下:
from django.contrib.auth.models import Permission,ContentType
from .models import Article
views.py
def addpermission(request):
content_type = ContentType.objects.get_for_model(Article)
permission = Permission.objects.create(name='可以编辑文章',content_type=content_type,codename='edit_article')
return HttpResponse('添加全选成功')
权限本身只是一个数据,必须和用户进行绑定,才能起到作用。User
模型和权限之间的管理,可以通过以下几种方式来管理:news_user_user_permissions 其实就是这个表的操作
def dopermission(request):
user = User.objects.filter(pk=1).first()
content_type = ContentType.objects.get_for_model(Article)
permissions = Permission.objects.filter(content_type=content_type)
for permission in permissions:
print(permission)
user.user_permissions.set(permissions)
return HttpResponse('用户添加权限成功')
myuser.user_permissions.set(permission_list)
:直接给定一个权限的列表。myuser.user_permissions.add(permission,permission,...)
:一个个添加权限。myuser.user_permissions.remove(permission,permission,...)
:一个个删除权限。myuser.user_permissions.clear()
:清除权限。myuser.has_perm('.')
:判断是否拥有某个权限。权限参数是一个字符串,格式是app_name.codename
。myuser.get_all_permissons()
:获取所有的权限。使用django.contrib.auth.decorators.permission_required
可以非常方便的检查用户是否拥有这个权限,如果拥有,那么就可以进入到指定的视图函数中,如果不拥有,那么就会报一个400
错误。示例代码如下:
def add_article(request):
if request.user.is_authenticated:
print('已经登录')
if request.user.has_perm('news.view_article'):
return HttpResponse('这是添加文章的页面')
else:
return HttpResponse('你没有访问权限',status=403)
else:
return redirect(reverse('login'))
@permission_required(['news.add_article','news.view_article'],login_url="/login/",raise_exception=True)
def add_article(request):
return redirect(reverse('login'))
权限有很多,一个模型就有最少三个权限,如果一些用户拥有相同的权限,那么每次都要重复添加。这时候分组就可以帮我们解决这种问题了,我们可以把一些权限归类,然后添加到某个分组中,之后再把和把需要赋予这些权限的用户添加到这个分组中,就比较好管理了。分组我们使用的是django.contrib.auth.models.Group
模型, 每个用户组拥有id
和name
两个字段,该模型在数据库被映射为auth_group
数据表。
Group.object.create(group_name)
:创建分组。
group.permissions
:某个分组上的权限。多对多的关系。
group.permissions.set
:批量添加权限。
group.permissions.add
:添加权限。group.permissions.remove
:移除权限。group.permissions.clear
:清除所有权限。user.get_group_permissions()
:获取用户所属组的权限。user.groups
:某个用户上的所有分组。多对多的关系。
在settings.TEMPLATES.OPTIONS.context_processors
下,因为添加了django.contrib.auth.context_processors.auth
上下文处理器,因此在模板中可以直接通过perms
来获取用户的所有权限。