Vue全栈开发旅游网项目(10)-设计用户模型
1.设计用户模型
文件地址:accounts/models.py
1.1 用户详细信息
内容包括:性别 手机号 年龄 生日 真实姓名
创建常量:1-男,0-女;editable=False不许循环
class Profile(models.Model):
SEX_CHOICES={
(1,'男'),
(0,'女')
}
username = models.CharField('用户名',max_length=64, unique=True,editable=False)
user = models.OneToOneField(User,related_name="profile",on_delete=models.CASCADE)
real_name = models.CharField('真实姓名',max_length=32)
email = models.CharField('电子邮件',max_length=128,null=True,blank=True)
is_email_valid = models.BooleanField('电子邮件是否已经被验证',default=False)
phone_no = models.CharField('手机号码',max_length=20,null=True,blank=True)
is_phone_valid = models.BooleanField('电话号码是否已经被验证', default=False)
sex = models.SmallIntegerField('性别',default=1,choices=SEX_CHOICES)
age = models.SmallIntegerField('年龄', default=0)
source = models.CharField('登录的来源',max_length=16,null=True)
version = models.CharField('登录的版本',max_length=32,null=True)
created_at = models.DateTimeField('登录时间',auto_now_add=True)
updated_at = models.DateTimeField('修改时间',auto_now=True)
class Meta:
db_table = "accounts_user_profile"
1.2 用户登录日志
class LoginRecord(models.Model):
user = models.ForeignKey(User,related_name='login_records',on_delete=models.CASCADE)
username = models.CharField('登录的账号',max_length=64)
ip = models.CharField('IP',max_length=32)
address = models.CharField('地址',max_length=32,null=True,blank=True)
source = models.CharField('登录的来源',max_length=16,null=True)
version = models.CharField('登录的版本', max_length=16, null=True)
created_at = models.DateTimeField('登录的时间',auto_now_add=True)
class Meta:
db_table = "accounts_login_record"
2.数据迁移
python manage.py check
python manage.py makemigrations
python manage.py migrate
3.准备Django模板
3.1 创建用户模板文件
3.2 用户登录
文件地址:accounts/templates/user_login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<h3>用户登录</h3>
<form method="post" action=".">
<div>
<!--用户名-->
{{ form.username.label }}<!--用户名文字提示-->
{{ form.username }}<!--用户名文本-->
{{ form.username.errors.as_text }}<!--用户名错误-->
</div>
<div>
<!--密码-->
{{ form.password.label }}<!--密码文字提示-->
{{ form.password }}<!--密码文本-->
{{ form.password.errors.as_text }}<!--密码错误-->
</div>
<div>
{{ form.non_field_errors.as_text }} <!--验证错误提示-->
</div>
<input type="submit" value="登录">
</form>
</body>
</html>
3.3 用户基本信息
文件地址:accounts/templates/user_info.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户的基本信息</title>
</head>
<body>
<p>
当前登录的用户是:{{ user.username }}-{{ user.email }}
</p>
{% if user.is_authenticated %}
<a href="/accounts/user/logout">退出登录</a>
{% endif %}
</body>
</html>
3.4 配置setting
import os
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',👈把它删咯
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR / 'templates')],👈加上os.path.join
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
4.表单验证
新建文件:accounts/forms.py
继承父类 重写子类
import re
from django import forms
from django.contrib.auth import authenticate, login
from django.utils.timezone import now
class LoginForm(forms.Form):
# 登录表单
username = forms.CharField(label='用户名',max_length=100,required=False,help_text='使用帮助',initial='admin')
password = forms.CharField(label='密码',max_length=200,min_length=6,widget=forms.PasswordInput)
#初始化函数,将传入的数据给到父类中处理
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.user = None
#验证用户名的钩子函数
def clean_username(self):
username = self.cleaned_data['username']
pattern = r'^1[0-9]{10}$'
if not re.search(pattern,username):
raise forms.ValidationError('手机号%s输入不正确',code='invalid_phone',params=(username,))
return username
#用户名密码验证
def clean(self):
data = super().clean()
if self.errors:
return
#获取模板中输入的用户名密码
username = data.get('username',None)
password = data.get('password',None)
#验证用户名密码是否正确
user = authenticate(username=username,password=password)
if user is None:
raise forms.ValidationError('用户名或密码不正确')
else:
if not user.is_active:
raise forms.ValidationError('该用户已经被禁用')
self.user = user
return data
#登陆函数
def do_login(self,request):
user = self.user
#调用登录
login(request, user)
#修改登陆时间
user.last_login = now()
user.save()
return user
5.用户登录视图函数
from django.contrib.auth import logout
from django.shortcuts import render, redirect
from accounts.forms import LoginForm
def user_login(request):
#用户登录
if request.method == 'POST':
form = LoginForm(data=request.POST)
if form.is_valid():
form.do_login(request)
print('表单验证通过')
return redirect('/accounts/user/info/')
else:
print(form.errors)
else:
form = LoginForm()
return render(request,'user_login.html',{'form':form})
def user_info(request):
#用户信息
print(request.user)
return render(request, 'user_info.html')
def user_logout(request):
#退出登录
logout(request)
return redirect('/accounts/user/info/')
6.配置路由
新建文件:accounts/urls.py
from django.urls import path
from accounts import views
urlpatterns = [
#用户登录
path('user/login/',views.user_login,name='user_login'),
#用户详细信息
path('user/info/',views.user_info,name='user_info'),
#用户退出登录
path('user/logout/',views.user_logout,name='user_logout')
]
全局urls: