from django.db import models from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): ''' 用户表 ''' nid =models.AutoField(primary_key=True) phone =models.CharField(max_length=11,null=True,unique=True) avatar = models.FileField(upload_to='avatars/',default='avatars/default.png',verbose_name='头像') create_time =models.DateTimeField(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(max_length=64) site =models.CharField(max_length=32,unique=True) theme =models.CharField(max_length=32) def __str__(self): return self.title class Category(models.Model): ''' 个人博客文章分类 ''' nid =models.AutoField(primary_key=True) title =models.CharField(max_length=32)#分类标题 blog = models.ForeignKey(to ='Blog',to_field='nid')#外键关联博客,一个博客站点可以有多个分类 def __str__(self): return self.title class Tag(models.Model): '''' 标签 ''' nid =models.AutoField(primary_key=True) title =models.CharField(max_length=32) blog =models.ForeignKey(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) #文章标题描述 desc =models.CharField(max_length=255) #文章描述 create_time =models.DateTimeField()#创建时间 category = models.ForeignKey(to ='Category',to_field='nid',null=True) user = models.ForeignKey(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 Article2Tag(models.Model): ''' 文章和标签的多对多关系表 ''' nid =models.AutoField(primary_key=True) article =models.ForeignKey(to='Article',to_field='nid') tag =models.ForeignKey(to ='Tag',to_field='nid') class Meta: unique_together = (('article','tag'),) class ArticleUpDown(models.Model): ''' 点赞 ''' nid= models.AutoField(primary_key=True) user =models.ForeignKey(to ='UserInfo',null=True) artcle = models.BooleanField(default=True) class Meta: unique_together = (('article','user'),) class Comment(models.Model): ''' 评论表 ''' nid = models.AutoField(primary_key=True) article =models.ForeignKey(to ='Article',to_field='nid') user =models.ForeignKey(to ='UserInfo',to_field='nid') content =models.CharField(max_length=255)#评论内容 create_time =models.DateTimeField(auto_now_add=True) parent_comment =models.ForeignKey('self',null=True) def __str__(self): return self.content
settings 里配置
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static')
]
# 告诉Djanog 项目用哪张表做认证
AUTH_USER_MODEL='app01.UserInfo'
# Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # }, 'default':{ 'ENGINE':'django.db.backends.mysql', 'NAME':'day77', 'USER':'root', 'PASSWORD':'123456', 'HOST':'127.0.0.1', 'PORT':3306, } }
init配置文件
import pymysql pymysql.install_as_MySQLdb()
登录配置
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/',views.login)
]
login登陆页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>欢迎登陆</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/mystyle.css"> #导入bootstrap </head> <body> <div class="container"> <div class="row"> <form class="form-horizontal col-md-6 col-md-offset-3 login-form" > {% csrf_token %} 登陆界面的csrf token校验 <div class="form-group" > <label for="inputEmail3" class="col-sm-2 control-label">用户名:</label> <div class="col-sm-10"> <input type="text" class="form-control" id="username" name="username" placeholder="用户名"> </div> </div> <div class="form-group"> <label for="password" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="password" class="form-control" id="password" name="password" placeholder="密码"> </div> </div> {# <div class="form-group">#} {# <div class="col-sm-offset-2 col-sm-10">#} {# <div class="checkbox">#} {# <label>#} {# <input type="checkbox"> 记住密码#} {# </label>#} {# </div>#} {# </div>#} {# </div>#} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type='button' class="btn btn-default" id="login-button">登陆</button> <span class="login-error"></span> </div> </div> </form> </div> </div> <script src="/static/jquery-3.3.1.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> <script> $('#login-button').click(function(){ // 1.取到用户填写的用户名和密码:-->取input框的值 var username = $('#username').val(); var password =$('#password').val(); //2. 用AJAX 发送到服务器端. $.ajax({ url:'/login/', type:'post', data:{ 'username':username, 'password': password , 'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val() }, success:function (data) { console.log(data); if (data.status){ //有错误,在页面中提示 $(".login-error").text(data.msg) }else { //登陆成功 location.href = data.msg } } }) })
})
//当input框获取焦点时将之前的错误信息清空
$("#username,#password") .focus(function () {
//将之前的内容清空
$('.login-error').text('');
})
</script>
</body>
</html>
views文件
from django.shortcuts import render,redirect,HttpResponse from django.http import JsonResponse from django.contrib import auth # Create your views here. def login(request): # if request.is_ajax(): if request.method =='POST': print(request.POST) #初始化一个给ajax返回的数据 ret ={'status':0,'msg':''} #从提交过来的数据中取到用户名和密码 username =request.POST.get('username') pwd =request.POST.get('password') #利用auth模块进行验证 导入auth模块 user = auth.authenticate(username=username, password =pwd) if user: #用户名密码正确 ,登陆成功. #给用户做登陆 auth.login(request,user) ret['msg']='/index/' return JsonResponse(ret) #跳转到index 界面 else: #用户名密码错误, ret['status'] =1 ret['msg']='用户名或密码错误' return JsonResponse(ret) return render(request,'login.html' ) def index(request): return HttpResponse('ok')
二、生成验证码图片
验证码:
1. 验证码要随机生成
1.如何自己生成一个图片
2. PIL Pillow
views 文件配置
#获取验证码图片的视图
def get_valid_img(request):
with open( 'valid_code.png','rb') as f :
data =f.read()
#自己生成一个图片
from PIL import Image,ImageDraw,ImageFont
import random
#获取随机颜色的函数
def get_random_color():
return random.randint(0,255),
random.randint(0, 255),
random.randint(0, 255),
#生成一个图片对象
img_obj = Image.new(
'RGB',
(220,35),
get_random_color()
)
#在生成的图片上写字符
#生成一个画笔对象
draw_obj =ImageDraw.Draw(img_obj)
#加载字体文件,得到一个字体对象
font_obj = ImageFont.truetype("static/font/kumo.ttf",28)
#循环五次添加随机字符
valid_code_tmp =[]
for i in range(5):
n =str(random.randint(0,9))
l=chr(random.randint(97,122))
u=chr(random.randint(65,90))
tmp = random.choice([n,l,u])
valid_code_tmp.append(tmp)
draw_obj.text((20+40*i,0),tmp,fill=get_random_color(),font =font_obj)
#将生成的图片保存在磁盘上.
# with open( 's10.png','wb') as f :
# img_obj.save(f,"png")
# #把刚才生成的图片返回给页面
# with open('s10.png','rb')as f :
# data =f.read()
#不需要在硬盘上保存文件,直接在内存中加载就可以
from io import BytesIO
io_obj =BytesIO()
#将生成的图片数据保存在io对象中
img_obj.save(io_obj,'png')
#从io对象里面取上一步保存的数据
data =io_obj.getvalue()
return HttpResponse(data)
Login登陆页面配置
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">验证码</label>
<div class="col-sm-10">
<input type="text" name="valid_code" >
<img class="valid-img" src="/get_valid_img/" alt="">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type='button' class="btn btn-default" id="login-button">登陆</button>
<span class="login-error"></span>
</div>
</div>
老师写的登录view文件
from django.shortcuts import render, redirect, HttpResponse from django.http import JsonResponse from django.contrib import auth # Create your views here. # VALID_CODE = "" def login(request): # if request.is_ajax(): # 如果是AJAX请求 if request.method == "POST": # 初始化一个给AJAX返回的数据 ret = {"status": 0, "msg": ""} # 从提交过来的数据中 取到用户名和密码 username = request.POST.get("username") pwd = request.POST.get("password") valid_code = request.POST.get("valid_code") # 获取用户填写的验证码 print(valid_code) print("用户输入的验证码".center(120, "=")) if valid_code and valid_code.upper() == request.session.get("valid_code", "").upper(): # 验证码正确 # 利用auth模块做用户名和密码的校验 user = auth.authenticate(username=username, password=pwd) if user: # 用户名密码正确 # 给用户做登录 auth.login(request, user) ret["msg"] = "/index/" else: # 用户名密码错误 ret["status"] = 1 ret["msg"] = "用户名或密码错误!" else: ret["status"] = 1 ret["msg"] = "验证码错误" return JsonResponse(ret) return render(request, "login.html") def index(request): return render(request, "index.html") # 获取验证码图片的视图 def get_valid_img(request): # with open("valid_code.png", "rb") as f: # data = f.read() # 自己生成一个图片 from PIL import Image, ImageDraw, ImageFont import random # 获取随机颜色的函数 def get_random_color(): return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) # 生成一个图片对象 img_obj = Image.new( 'RGB', (220, 35), get_random_color() ) # 在生成的图片上写字符 # 生成一个图片画笔对象 draw_obj = ImageDraw.Draw(img_obj) # 加载字体文件, 得到一个字体对象 font_obj = ImageFont.truetype("static/font/kumo.ttf", 28) # 开始生成随机字符串并且写到图片上 tmp_list = [] for i in range(5): u = chr(random.randint(65, 90)) # 生成大写字母 l = chr(random.randint(97, 122)) # 生成小写字母 n = str(random.randint(0, 9)) # 生成数字,注意要转换成字符串类型 tmp = random.choice([u, l, n]) tmp_list.append(tmp) draw_obj.text((20+40*i, 0), tmp, fill=get_random_color(), font=font_obj) print("".join(tmp_list)) print("生成的验证码".center(120, "=")) # 不能保存到全局变量 # global VALID_CODE # VALID_CODE = "".join(tmp_list) # 保存到session request.session["valid_code"] = "".join(tmp_list) # 加干扰线 # width = 220 # 图片宽度(防止越界) # height = 35 # for i in range(5): # x1 = random.randint(0, width) # x2 = random.randint(0, width) # y1 = random.randint(0, height) # y2 = random.randint(0, height) # draw_obj.line((x1, y1, x2, y2), fill=get_random_color()) # # # 加干扰点 # for i in range(40): # draw_obj.point((random.randint(0, width), random.randint(0, height)), fill=get_random_color()) # x = random.randint(0, width) # y = random.randint(0, height) # draw_obj.arc((x, y, x+4, y+4), 0, 90, fill=get_random_color()) # 将生成的图片保存在磁盘上 # with open("s10.png", "wb") as f: # img_obj.save(f, "png") # # 把刚才生成的图片返回给页面 # with open("s10.png", "rb") as f: # data = f.read() # 不需要在硬盘上保存文件,直接在内存中加载就可以 from io import BytesIO io_obj = BytesIO() # 将生成的图片数据保存在io对象中 img_obj.save(io_obj, "png") # 从io对象里面取上一步保存的数据 data = io_obj.getvalue() return HttpResponse(data)
自己写的整个登录界面
from django.shortcuts import render,redirect,HttpResponse from django.http import JsonResponse from django.contrib import auth # Create your views here. VALID_CODE='' def login(request): # if request.is_ajax(): if request.method =='POST': print(request.POST) #初始化一个给ajax返回的数据 ret ={'status':0,'msg':''} #从提交过来的数据中取到用户名和密码 username =request.POST.get('username') pwd =request.POST.get('password') valid_code = request.POST.get('valid_code')#获取用户填写的验证码 print(valid_code) print('用户输入的验证码'.center(120,'=')) if valid_code.upper() ==request.session["valid_code"].upper(): #利用auth模块进行验证 导入auth模块 user = auth.authenticate(username=username, password =pwd) if user: #用户名密码正确 ,登陆成功. #给用户做登陆 auth.login(request,user) ret['msg']='/index/' return JsonResponse(ret) #跳转到index 界面 else: #用户名密码错误, ret['status'] =1 ret['msg']='用户名或密码错误' return JsonResponse(ret) return render(request,'login.html' ) def index(request): return HttpResponse('ok') #获取验证码图片的视图 def get_valid_img(request): with open( 'valid_code.png','rb') as f : data =f.read() #自己生成一个图片 from PIL import Image,ImageDraw,ImageFont import random #获取随机颜色的函数 def get_random_color(): return random.randint(0,255), random.randint(0, 255), random.randint(0, 255), #生成一个图片对象 img_obj = Image.new ( 'RGB', (220,35), get_random_color() ) #在生成的图片上写字符 #生成一个画笔对象 draw_obj =ImageDraw.Draw(img_obj) #加载字体文件,得到一个字体对象 font_obj = ImageFont.truetype("static/font/kumo.ttf",28) #循环五次添加随机字符 valid_code_tmp =[] for i in range(5): n =str(random.randint(0,9)) l=chr(random.randint(97,122)) u=chr(random.randint(65,90)) tmp = random.choice([n,l,u]) valid_code_tmp.append(tmp) draw_obj.text((20+40*i,0),tmp,fill=get_random_color(),font =font_obj) print("".join(valid_code_tmp)) print("生成的验证码".center(120, "=")) # 不能保存到全局变量 # global VALID_CODE # VALID_CODE = "".join(tmp_list) # 保存到session request.session["valid_code"] = "".join(valid_code_tmp) #将生成的图片保存在磁盘上. # with open( 's10.png','wb') as f : # img_obj.save(f,"png") # #把刚才生成的图片返回给页面 # with open('s10.png','rb')as f : # data =f.read() #不需要在硬盘上保存文件,直接在内存中加载就可以 from io import BytesIO io_obj =BytesIO() #将生成的图片数据保存在io对象中 img_obj.save(io_obj,'png') #从io对象里面取上一步保存的数据 data =io_obj.getvalue() return HttpResponse(data)
前端登录
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>欢迎登陆</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/mystyle.css"> #导入bootstrap </head> <body> <div class="container"> <div class="row"> <form class="form-horizontal col-md-6 col-md-offset-3 login-form" > {% csrf_token %} <div class="form-group" > <label for="inputEmail3" class="col-sm-2 control-label">用户名:</label> <div class="col-sm-10"> <input type="text" class="form-control" id="username" name="username" placeholder="用户名"> </div> </div> <div class="form-group"> <label for="password" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="password" class="form-control" id="password" name="password" placeholder="密码"> </div> </div> <div class="form-group"> <label for="password" class="col-sm-2 control-label">验证码</label> <div class="col-sm-10"> <input type="text" name="valid_code" id="valid_code" > <img class="valid-img" src="/get_valid_img/" alt=""> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type='button' class="btn btn-default" id="login-button">登陆</button> <span class="login-error"></span> </div> </div> </form> </div> </div> <script src="/static/jquery-3.3.1.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> <script> $('#login-button').click(function(){ // 1.取到用户填写的用户名和密码:-->取input框的值 var username = $('#username').val(); var password =$('#password').val(); var valid_code=$('#valid_code').val(); //2. 用AJAX 发送到服务器端. $.ajax({ url:'/login/', type:'post', data:{ 'username':username, 'password': password , 'valid_code':valid_code, 'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val() }, success:function (data) { console.log(data); if (data.status){ //有错误,在页面中提示 $(".login-error").text(data.msg) }else { //登陆成功 location.href = data.msg } } }) }) //当input框获取焦点时将之前的错误信息清空 $("#username,#password") .focus(function () { //将之前的内容清空 $('.login-error').text(''); }) </script> </body> </html>