博客园之登录

from django.db import models from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用户信息 """ nid = models.AutoField(primary_key=True) nickname = models.CharField(verbose_name='昵称', max_length=32) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to = 'avatars/',default="/avatars/default.png") create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid',null=True) def __str__(self): return self.username class Blog(models.Model): """ 博客信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='个人博客标题', max_length=64) site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self): return self.title class Category(models.Model): """ 博主个人文章分类表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分类标题', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid') def __str__(self): return self.title class Tag(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='标签名称', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid') def __str__(self): return self.title class Article(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章标题') desc = models.CharField(max_length=255, verbose_name='文章描述') comment_count= models.IntegerField(default=0) up_count = models.IntegerField(default=0) down_count = models.IntegerField(default=0) create_time = models.DateTimeField(verbose_name='创建时间') homeCategory = models.ForeignKey(to='Category', to_field='nid', null=True) #siteDetaiCategory = models.ForeignKey(to='SiteCategory', to_field='nid', null=True) user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid') tags = models.ManyToManyField( to="Tag", through='Article2Tag', through_fields=('article', 'tag'), ) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章详细表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid') class Comment(models.Model): """ 评论表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid') user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid') content = models.CharField(verbose_name='评论内容', max_length=255) create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) parent_comment = models.ForeignKey('self', null=True) def __str__(self): return self.content class ArticleUpDown(models.Model): """ 点赞表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey('UserInfo', null=True) article = models.ForeignKey("Article", null=True) is_up=models.BooleanField(default=True) class Meta: unique_together = [ ('article', 'user'), ] class Article2Tag(models.Model): nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid') tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid') class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v=self.article.title+"----"+self.tag.title return v

AUTH_USER_MODEL = "blog01.UserInfo" #app名称.UserInfo表
urls.py:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^get_valid_img/', views.get_valid_img),
url(r'^index/', views.index),
]
views.py:
from django.shortcuts import render,HttpResponse,redirect from django.contrib import auth from django.http import JsonResponse from django import forms from django.forms import widgets from .models import * def login(request): if request.method=="POST": user=request.POST.get("username") pwd=request.POST.get("password") input_valid_codes=request.POST.get("valid_code") # 校验验证码 session_valid_codes=request.session.get("insert_valid") print(session_valid_codes,'222') ''' request.COOKIE['sessionId'] #取出随机字符串 in session表中 models.session.object.filter(sessionid=取出随机字符串).values ''' login_response={"user":None,"error_msg":""} #定义一个第三方变量存储用于判断 if session_valid_codes.upper()==input_valid_codes.upper(): #用户在浏览器输入大小写混合、大写、小写 均转为大写进行判断。(忽略大小写) user=auth.authenticate(username=user,password=pwd)#再判断输入的用户名、密码与数据库存储的是否相同 if user: #用户名密码如果为真 auth.login(request,user) #验证登录 login_response["user"]=user.username #用户名赋给login_response的 'user' print(user.username) else: login_response["error_msg"] = "username or password error!" #否则赋值给错误 else: login_response["error_msg"]="valid_code error!" #输入的验证码与输入的不一致则返回error提示 import json return HttpResponse(json.dumps(login_response)) else: return render(request,"login.html") # Create your views here. # 方式1:(仅仅实现了渲染本地静态图片当做验证码的功能) # from cnblog项目实战 import settings # import os # path=os.path.join(settings.BASE_DIR,"static","img","linhaifeng.jpg") # with open(path,"rb") as f: # data=f.read() #方式二要实现图片自动实现生成一张图片(缺点是保存到本地了) # from PIL import Image # img=Image.new(mode='RGB',size=(120,30),color=(0,110,168)) #生成一张图片长宽120,30,颜色是三基色(RGB)因子调色而成 # img.save( open('whq.png','wb') ) #以二进制方式读写保存这张图片 # with open('whq.png', 'rb') as f: #以二进制方式读图片 # data = f.read() #读出的结果保存赋值给data # return HttpResponse(data)#交给浏览器渲染数据 # 方法三实现把图片保存到内存 # from io import BytesIO #该模块实现了把文件保存到内存中 # f=BytesIO() # from PIL import Image # img=Image.new(mode='RGB',size=(90,30),color=(0,19,168)) #生成一张图片长宽120,30,颜色是三基色(RGB)因子调色而成 # img.save( f,'png') #保存这个文件的句柄+png后缀 # data=f.getvalue() # return HttpResponse(data)#交给浏览器渲染数据 import random def get_randon_color(): return (random.randint(123,234),random.randint(123,234),random.randint(123,234)) def get_valid_img(request): from PIL import Image, ImageDraw, ImageFont from io import BytesIO # 生成图片 image = Image.new("RGB", (280, 40), get_randon_color()) #280, 40图片大小 # # #生成一枝画笔 draw = ImageDraw.Draw(image) # font = ImageFont.truetype("static/font/kumo.ttf/", size=35)#指定字体,以及大小 #生成随机数 keep_valid_codes = "" for i in range(5): random_num = str(random.randint(0, 9))#生成0,9数字转换字符串 random_lower_alf = chr(random.randint(97, 122))#生成大写字母 random_upper_alf = chr(random.randint(65, 90))#生成小写字母 random_char = random.choices([random_num, random_lower_alf, random_upper_alf])[0]#任意选一个 print(random_char, "===") draw.text((20 + i * 50, 0), random_char, fill=get_randon_color()) keep_valid_codes += random_char f = BytesIO() #实例化一个内存IO对象 image.save(f, "png")#保存成png格式 data = f.getvalue() #取图片+随机数的图片 print(keep_valid_codes,keep_valid_codes.upper()) s=''.join(keep_valid_codes) request.session['insert_valid']=s ''' Django:做的事件 1:浏览器中 Set_cookie('sessionId','随机字符串') 2:Django的中Django_session 表中 sessionKey字段 sessiondata '随机字符串' {insert_valid:keep_valid_codes} ''' return HttpResponse(data) #返回带随机数的图片 def index(request): return render(request,'index.html')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"> <script src="/static/js/jquery-3.1.1.js"></script>{# jquery是js的扩展包所以用script #} </head> <body> <div class="container"> <div class="row"> <div class="col-md-4 col-md-offset-3"> <form> <div class="form-group"> <label for="user">用户名</label> <input type="text" class="form-control" id="user" placeholder="输入用户名"> </div> <div class="form-group"> <label for="pwd">密码</label> <input type="password" class="form-control" id="pwd" placeholder="输入密码"> </div> <div class="form-group"> <label for="valid">验证码</label> <div class="row"> <div class="col-md-3"> <input type="text" class="form-control" id="valid" placeholder="输入验证码"> </div> <div> <div class="col-md-3"> <img id="valid_img" width="220" height="40" src="/get_valid_img/" alt=""> </div> </div> </div> </div> <input type="button" class="btn btn-primary" value="submit" id="submit_btn" > <span class="error"></span> </form> </div> </div> </div> <script> // 验证码刷新 $("#valid_img").click(function () { $(this)[0].src += "?" }); // ajax请求验证 $("#submit_btn").click(function () { $.ajax({ url: "/login/", type: "post", data: { "username": $("#user").val(), "password": $("#pwd").val(), "valid_code": $("#valid").val(), "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val() }, success: function (data) { // {"user":"","error_meg":""} console.log(data); var data = JSON.parse(data); if (data.user) { // 登录成功 location.href = "/index/" } else { $(".error").html(data.error_msg).css('color', "red") setTimeout(function () { $(".error").html("") }, 1000) } } }) }) </script> </body> </html>
index.html(登录 后跳转的页面):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"> <script src="/static/js/jquery-3.1.1.js"></script> </head> <body> <h3>index</h3> </body> </html>
执行顺序:

输入http://127.0.0.1:8000/login执行过程分析 urls.py配置 1:导入from app01 import views 是指能调用views模块功能 2:配置浏览器路径部分:login路径指向实际执行功能的函数 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), ] 3:编写实现login功能函数 3.1:导入auth模块使之支持auth验证(数据长度等) from django.contrib import auth 3.2:get请求执行else分支执行 return render(request,"login.html") 3.3:进入html页面: 3.3.1:<div class="container"> bootstrap整个盒子是居中效果 1: <div class="row"> container子盒子里的元素在一行显示 1.1:<div class="col-md-6 col-md-offset-3"> 盒子占六个栅格,向右移动三个栅格 1:定制form表单盒子 1.1:<div class="form-group">boostrap样式的盒子 1: <label for="user">用户名</label>:label标签使之能点击用户名时光标进入框 2:type="text" :类型为输入文本的框 3:class="form-control" :bootstrap样式 4:id="user" :设置唯一的标签用于查找,与label标签 for属性相同 5:placeholder="输入用户名":用于输入框中悬浮是显示的效果 1.2:1.1:<div class="form-group">boostrap样式的盒子 1: <label for="pwd">密码</label>:label标签使之能点击用户名时光标进入框 2:type="password" :类型为输入以点'.'加密的框 3:class="form-control" :bootstrap样式 4:id="pwd" :设置唯一的标签用于查找,与label标签 for属性相同 5:placeholder="输入密码":用于输入框中悬浮是显示的效果 1.3:1.1:<div class="form-group">boostrap样式的盒子 1: <label for="valid">密码</label>:label标签使之能点击用户名时光标进入框 2:type="text" :类型为输入文本的框 3:class="form-control" :bootstrap样式 4:id="valid" :设置唯一的标签用于查找,与label标签 for属性相同 5:placeholder="输入验证码":用于输入框中悬浮是显示的效果 1.4: 1: {% csrf_token %}:设置中间件csrf验证 2:input type="button":设置一个可以自定义事件的提交按钮 3:class="btn btn-primary":boostrap蓝色控件样式 4:value="submit":button控件显示值为‘submit’字段 5:id="submit_btn":设置唯一性的标识,利于查找 3.4:填写form表单: 1:用户名:whq518518 2:密码:ehfeoflenfol 3:验证码:session_valid_codes 生成的随机字符串 4:点击submit控件 5:执行submit执行的事件 5.1:$("#login_btn").click(function () 把id=login_btn控件变成jquery属性,执行点击事件 5.2:执行ajax请求体 url:"/login/":执行login路径匹配 urls.py 的login---->执行views.py里的login函数 type:"post":提交给服务器数据的方式post data:{ "user":$("#user").val(),#找到id=user的控件,并取输入框的值(val()) "pwd":$("#pwd").val(),#找到id=pwd的控件,并取输入框的值(val()) "valid_code":$("#valid").val(),#找到id=valid的控件,并取输入框的值(val()) "csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val() #设置中间件 }, 6:匹配urls.py文件,指向views文件的login函数 urlpatterns = [ url(r'^login/', views.login), ] 4 views.py文件login函数 7:request.method 与type:"post"相对比执行 user=request.POST.get("username") : 1:get("username") 与"username":$("#user").val()的"username"匹配 2:$("#user").val()的$("#user")查找form表单id=user的控件 3:("#user").val():取出form表单id="user"输入框的值 pwd=request.POST.get("password") 1:get("password") 与"password":$("#pwd").val()的"pwd"匹配 2:$("#pwd").val()的$("#pwd")查找form表单id=pwd的控件 3:("#pwd").val():取出form表单id="pwd"输入框的值 pwd=request.POST.get("valid_code") 1:get("valid_code") 与"valid_code":$("#valid").val()的"valid_code"匹配 2:$("#valid").val()的$("#valid")查找form表单id=valid的控件 3:("#valid").val():取出form表单id="valid"输入框的值 # 校验验证码 session_valid_codes=request.session.get("insert_valid")#读取session,找到insert_valid为key的一条字段 session读取过程: ''' request.COOKIE['sessionId'] #取出随机字符串 in session表中 models.session.object.filter(sessionid=取出随机字符串).values ''' login_response={"user":None,"error_msg":""} #定义一个第三方变量存储用于判断 if session_valid_codes.upper()==input_valid_codes.upper(): #判断验证码与输入的是否一致(此处必须转换成大写 或小写,不知为什么) user=auth.authenticate(username=user,password=pwd)#再判断输入的用户名、密码与数据库存储的是否相同 if user: #用户名密码如果为真 auth.login(request,user) #验证登录 login_response["user"]=user.username #用户名赋给login_response的 'user’ else: login_response["error_msg"] = "username or password error!" #否则赋值给错误 else: login_response["error_msg"]="valid_code error!" #输入的验证码与输入的不一致则返回error提示 import json return HttpResponse(json.dumps(login_response)) #login_response 是个字典 ,需要把结果传递给前端,前端是html、js、语言。 # 这就涉及到不同语言之间传递数据的问题了 #解决方案:1先序列化到硬盘上json.dumps(login_response) # 2 用HttpResponse把序列化到硬盘上的数据传递给前端。 # 3请求的数据体:data: {} #4: success: function(data) 返回的数据 # var data = JSON.parse(data); 把data数据:login_response={"user":None,"error_msg":""}解析成JavaScript对象 # if (data.user) { 判断字典user是否为真 # // 登录成功 # location.href = "/index/"为真则登录index页面 # # } # else { 为假则找到button按钮的后的 span标签 class=error, # 渲染data.error_msg字段,标红显示。 # $(".error").html(data.error_msg).css('color', "red") # # setTimeout(function () {1秒后超时,找到button按钮的后的 span标签 class=error 消失 # $(".error").html("") # }, 1000) # } # } else: return render(request,"login.html") 创建get_randon_color()函数:(RGB颜色以随机数方式生成) import random def get_randon_color(): return (random.randint(123,234),random.randint(123,234),random.randint(123,234)) ------------------------------------------------------------------------------------------ 创建get_valid_img()函数:(实现图片随机验证码) def get_valid_img(request): from PIL import Image, ImageDraw, ImageFont from io import BytesIO # 生成图片 image = Image.new("RGB", (280, 40), get_randon_color()) #长宽280, 40图片大小 # # #生成一枝画笔 draw = ImageDraw.Draw(image) # font = ImageFont.truetype("static/font/kumo.ttf/", size=35)#指定字体,以及大小 #生成随机数 keep_valid_codes = "" for i in range(5): random_num = str(random.randint(0, 9))#生成0,9数字转换字符串 random_lower_alf = chr(random.randint(97, 122))#生成大写字母 random_upper_alf = chr(random.randint(65, 90))#生成小写字母 random_char = random.choices([random_num, random_lower_alf, random_upper_alf])[0]#,不以切片方式话,结果是列表类型 print(random_char, "===") draw.text((20 + i * 50, 0), random_char, fill=get_randon_color()) #在图片20像素处,每增加一个元素字符占50像素,y轴处于0坐标 keep_valid_codes += random_char #生成5位的字符串 f = BytesIO() #实例化一个内存IO对象 image.save(f, "png")#保存成png格式 data = f.getvalue() #取图片+随机数=的图片 request.session['insert_valid']=keep_valid_codes #把生成的随机字符串插入session表中( 解决方案:1 保存在内存中:B链接来了会重置验证码,导致A客户端在填写form表单时就重置了其他导致验证码错误 2:保存在本地:不可取,保存在客户端的某地不方便 3:保存到session表中:登录时直接从数据库查询读取 ) ''' Django:做的事件 1:浏览器中 Set_cookie('sessionId','随机字符串') 2:Django的中Django_session 表中 sessionKey字段 sessiondata '随机字符串' {insert_valid:keep_valid_codes} ''' return HttpResponse(data) #返回带随机数的图片 ---------------------------------------------------------------------------------- def index(request): return render(request,'index.html')
开发者自己写input标签时 用键(name):值(value) +submit表单形式提交给服务器,换做ajax后就改成" username": ("#user").val(), 相当于form表单的name属性 "password": ("#valid").val(),
撸起袖子加油干!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通