- 创建用户:
python manage.py startapp users
- 注册子应用:在 blog 文件夹的 settings.py 的 INSTALLED_APPS 中添加:
'users.apps.UsersConfig',
- 准备模板目录并设置模板路径:在 blog 同级文件夹中新建 templates 文件夹,在 blog 文件夹的 settings.py 的 TEMPLATES 中添加:
'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 将 static 文件夹中的 register.html 拖入 templates 文件夹中,在 users 文件夹的 views.py 中加入:
from django.views import View class RegisterView(View): """用户注册""" def get(self, request): """ 提供注册界面 :param request: 请求对象 :return: 注册界面 """ return render(request, 'register.html')
- 定义子路由:在 users 文件夹中创建 urls.py 文件,并加入:
from django.urls import path from users.views import RegisterView urlpatterns = [ # 参数1:路由 # 参数2:视图函数 # 参数3:路由名,方便通过reverse来获取路由 path('register/', RegisterView.as_view(), name='register'), ]
- 添加子应用路由引导:在 blog 文件夹的 urls.py 文件中,替换和添加:
from django.urls import path, include path('', include(('users.urls', 'users'), namespace='users')),
- 在 templates 文件夹的 register.html 文件中修改静态文件加载方式(相对加载路径),以下代码是 html 的 header 处修改:
以下代码是 <!--图片验证码--> 处修改:{% load static %} // 在django3.x后不再使用load staticfiles <!-- 引入bootstrap的css文件 --> <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}"> <!-- 引入vuejs --> <script type="text/javascript" src="{% static 'js/vue-2.5.16.js' %}"></script> <script type="text/javascript" src="{% static 'js/axios-0.18.0.min.js' %}"></script>
以下代码是 html 的 footer 处修改:<img src="{% static 'img/image_code.png'%}" @click="generate_image_code" alt="" style="width: 110px;height: 40px;">
<!-- 引入js --> <script type="text/javascript" src="{% static 'js/host.js' %}"></script> <script type="text/javascript" src="{% static 'js/common.js' %}"></script> <script type="text/javascript" src="{% static 'js/register.js' %}"></script>
- 在网页中输入:127.0.0.1:8000/register/ 出现登录界面
-
定义用户模型类
- User对象基本属性:
创建用户必选 username、password 创建用户可选 email、first_name、last_name、last_login、date_joined、is_active、is_staff、is_superuse 判断用户是否通过认证 is_authenticated 修改用户名认证字段 USERNAME_FIELD 创建用户的方法 user = User.objects.create_user(username, password, **extra_fields) 用户认证的方法 from django.contrib.auth import authenticate
user = authenticate(username=username, password=password, **kwargs)
设置密码 set_password(raw_password) 校验密码 check_password(raw_password) - 自定义用户模型类:在 users 文件夹的 models.py 文件中添加:
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): # 用户信息 mobile = models.CharField(max_length=20, unique=True,blank=True) # 电话号码字段 avatar = models.ImageField(upload_to='avatar/%Y%m%d/', blank=True) # 头像 user_desc = models.TextField(max_length=500, blank=True) # 个人简介 USERNAME_FIELD = 'mobile' # 修改认证的字段 REQUIRED_FIELDS = ['username','email'] #创建超级管理员的需要必须输入的字段 class Meta: # 内部类 class Meta 用于给 model 定义元数据 db_table='tb_user' #修改默认的表名 verbose_name='用户信息' # Admin后台显示 verbose_name_plural=verbose_name # Admin后台显示 def __str__(self): return self.mobile
- 指定用户模型类:配置规则为 AUTH_USER_MODEL = '应用名.模型类名',在 blog 文件夹的 settings.py 的最后添加:
AUTH_USER_MODEL = 'users.User'
- 迁移用户模型类:
若出现以下报错,则先注释掉 blog 文件夹的 settings.py 中 INSTALLED_APPS 的 'django.contrib.admin', 和 urls.py 中 urlpatterns 的 path('admin/', admin.site.urls),python manage.py makemigrations python manage.py migrate
5. cmd 进入 MySQL,Ctrl+C 可退出当前界面,输入 use blog(blog文件夹的 settings.py 中的数据库名字),再输入 show databases; 和 desc tb_user;
-
图形验证码接口设计和定义
- 在 blog 文件夹的同级目录中新建 libs 文件夹,放入 captcha 文件夹和 _init_.py 文件
- 安装图片处理库(大于10的版本会报错):
pip install Pillow==9.5.0
- 请求方式:GET,请求地址:imagecode?uuid=xxxxx-xxxx-xxxxxx,参数名:uuid,类型:string,是否必传:是,说明:唯一编号
- 添加图形验证码视图:在 users 文件夹的 views.py 的最后添加:
from django.http import HttpResponseBadRequest,HttpResponse from libs.captcha.captcha import captcha from django_redis import get_redis_connection class ImageCodeView(View): def get(self,request): uuid=request.GET.get('uuid') #获取前端传递过来的参数 if uuid is None: #判断参数是否为None return HttpResponseBadRequest('请求参数错误') text, image = captcha.generate_captcha() # 获取验证码内容和图片二进制数据 redis_conn = get_redis_connection('default') # 将图片验内容保存到redis中,并设置过期时间 redis_conn.setex('img:%s' % uuid, 300, text) return HttpResponse(image, content_type='image/jpeg') # 返回响应,将生成的图片以content_type为image/jpeg的形式返回给请求
- 设置子路由:在 users 文件夹的 urls.py 中添加:
from django.urls import path from users.views import ImageCodeView urlpatterns = [ path('imagecode/', ImageCodeView.as_view(),name='imagecode'), ]
- 在 templates 文件夹的 register.html 文件中,修改模板中图片验证码 HTML 代码:
<img :src="image_code_url" @click="generate_image_code" alt="" style="width: 110px;height: 40px;">
- 如果运行网页出现下列错误:
则需要安装 cryptography,如清华大学源:
pip3 install cryptography -i https://pypi.tuna.tsinghua.edu.cn/simple
-
短信验证码
- 在 libs 文件夹中,拖入 yuntongxin 文件夹,并新建 __init__.py 文件;在 utils 文件夹中,加入 response_code.py 文件
- 容联云短信平台官网链接:https://www.yuntongxun.com/,免费开发测试模板 ID 为 1,形式为:【云通讯】您使用的是云通讯短信模板,您的验证码是 {1},请于 {2} 分钟内正确输入。根据控制台信息修改 yuntongxin 文件夹中的 sms.py 文件:
_accountSid = '2c94811c8b1e335b018c4d288d9744ae' # ACCOUNT SID _accountToken = '190c870643c94ba78238005a4139f4dd' # AUTH TOKEN _appId = '2c94811c8b1e335b018c4d288f1744b5' # APPID
- 在 users 文件夹的 views.py 中加入:
from django.http import JsonResponse from utils.response_code import RETCODE from random import randint from libs.yuntongxun.sms import CCP import logging logger=logging.getLogger('django') class SmsCodeView(View): def get(self,request): image_code_client = request.GET.get('image_code') # 接收参数 uuid = request.GET.get('uuid') mobile=request.GET.get('mobile') if not all([image_code_client, uuid,mobile]): # 校验参数 return JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必传参数'}) redis_conn = get_redis_connection('default') # 创建连接到redis的对象 image_code_server = redis_conn.get('img:%s' % uuid) # 提取图形验证码 if image_code_server is None: return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码失效'}) # 图形验证码过期或者不存在 try: # 删除图形验证码,避免恶意测试图形验证码 redis_conn.delete('img:%s' % uuid) except Exception as e: logger.error(e) image_code_server = image_code_server.decode() # bytes转字符串 if image_code_client.lower() != image_code_server.lower(): # 转小写后比较 return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '输入图形验证码有误'}) sms_code = '%06d' % randint(0, 999999) # 生成短信验证码:生成6位数验证码 logger.info(sms_code) # 将验证码输出在控制台,以方便调试 redis_conn.setex('sms:%s' % mobile, 300, sms_code) # 保存短信验证码到redis中,并设置有效期 CCP().send_template_sms(mobile, [sms_code, 5],1) # 发送短信验证码 return JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信成功'}) # 响应结果
- 运行后获取的验证码显示在 vscode 工作区窗口中
-
用户注册实现
- 注册视图:
import re from users.models import User from django.db import DatabaseError class RegisterView(View): def post(self,request): mobile = request.POST.get('mobile') #接收参数 password = request.POST.get('password') password2 = request.POST.get('password2') smscode=request.POST.get('sms_code') if not all([mobile, password, password2, smscode]): # 判断参数是否齐全 return HttpResponseBadRequest('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): # 判断手机号是否合法 return HttpResponseBadRequest('请输入正确的手机号码') if not re.match(r'^[0-9A-Za-z]{8,20}$', password): # 判断密码是否是8-20个数字 return HttpResponseBadRequest('请输入8-20位的密码') if password != password2: # 判断两次密码是否一致 return HttpResponseBadRequest('两次输入的密码不一致') redis_conn = get_redis_connection('default') #验证短信验证码 sms_code_server = redis_conn.get('sms:%s' % mobile) if sms_code_server is None: return HttpResponseBadRequest('短信验证码已过期') if smscode != sms_code_server.decode(): return HttpResponseBadRequest('短信验证码错误') try: # 保存注册数据 user=User.objects.create_user(username=mobile,mobile=mobile, password=password) except DatabaseError: return HttpResponseBadRequest('注册失败') return HttpResponse('注册成功,重定向到首页') # 响应注册结果
- 在 templates 文件夹的 register.html 中添加:
{% csrf_token %}
-
展示首页
- 创建首页子应用:
python manage.py startapp home
- 定义首页视图:在 home 文件夹的 views.py 中添加:
from django.views import View class IndexView(View): def get(self, request): """首页广告""" return render(request, 'index.html') """提供首页广告界面"""
- 在 home 子应用中创建 urls.py 文件,并定义子路由:
from django.urls import path from home.views import IndexView urlpatterns = [ path('', IndexView.as_view(),name='index'), ]
- 在 blog 文件夹的 urls.py 总路由中添加子应用路由引导:
path('', include(('home.urls','home'),namespace='home')),
- 需将 index.html 加入templates文件夹下
-
状态保持
- 设置首页所需的用户名信息和登录状态:修改 users 文件夹的 views.py 文件
from django.contrib.auth import login login(request, user) response = redirect(reverse('home:index')) # 跳转到首页 response.set_cookie('is_login',True) # 设置cookie,登录状态,会话结束后自动过期 response.set_cookie('username',user.username,max_age=30*24*3600) # 设置用户有效期 return response
- 查看 cookie 数据:先在链接 http://127.0.0.1:8000/register/ 中注册账号,再进入链接 http://127.0.0.1:8000/ 点击左上方带圈 (i) 进行查看
- cmd 中输入 redis-cli,进入后输入 keys * 查看,再输入 select 1 和 keys * 查看
学习介绍链接:https://blog.csdn.net/castlegirl/article/details/135075747?spm=1001.2014.3001.5501
项目链接:GitHub - haifengyuhui/project_blogweb: Project: A website for haifengyuhui's blog