博客园之登录

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
models.py配置
AUTH_USER_MODEL = "blog01.UserInfo" #app名称.UserInfo表
settings.py文件设置
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") "username":就相当于input框的name属性 值就变成了("#pwd").val() 用户输入的值 例如: "username": $("#user").val(), 相当于form表单的name属性 "password": $("#pwd").val(), "valid_code": $("#valid").val(), 

相关推荐