数据库设计

from django.db import models
from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    """
    用户信息,继承auth_user表
    """
    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='avatar/', default="/avatar/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 HomeCategory(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')

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='创建时间', auto_now_add=True)

    homeCategory = models.ForeignKey(to='HomeCategory', 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 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'),
        ]

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'),
        ]

models.py

验证码登录

先打个样儿:

part1:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/css/login.css">

<body>

<div class="container ">
    <div class="row ">
        <form action="" class="form-horizontal col-md-6 col-md-offset-3">
            <div class="form-group">
                <label for="username">用户名</label>
                <input type="text" class="form-control" id="username">
            </div>

            <div class="form-group">
                <label for="password">密码</label>
                <input type="password" class="form-control" id="password">
            </div>

            <div class="form-group">
                <label for="valid_code">验证码</label>
                <div class="row">
                    <div class="col-md-6">
                        <input type="text" class="form-control" id="valid_code">
                    </div>
                    <div class="col-md-6">
                        <img width="230" height="35" src="https://pic.cnblogs.com/avatar/1054809/20171214142056.png"
                             alt="">
                    </div>
                </div>

            </div>
            <div class="form-group">
                <input type="button" value="登录" class="btn btn-primary form-control" id="login-btn">

            </div>

        </form>
    </div>
</div>

<script src="/static/js/jquery-3.2.1.min.js"></script>
<script src="/static/plugins/bootstrap/js/bootstrap.min.js"></script>
</body>
</html> 

login.html

.container{
    margin-top: 100px;
}

login.css

看先效果:

导入 PIL模块,random模块。生成随机颜色的验证图。(PIL需要安装pillow模块:pip install pillow)

login.html
 <img src="/get_valid_img/" alt="" width="230" height="35" id="valid_img">
from django.shortcuts import render, redirect, HttpResponse
import random
from PIL import Image

def log_in(request):
    return render(request, 'login.html')

def get_valid_img(request):
    import random
    from PIL import Image
    def get_random_color():
        # 生成随机色
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    # 生成图片(画布,默认是白色)
    image = Image.new(mode="RGB", size=(230, 35), color=get_random_color())
    f = open('a.png', 'wb')
    image.save(f, 'png')
    # 读取图片数据
    with open('a.png', 'rb') as f_read:
        data = f_read.read()
    return HttpResponse(data)

views.py

我们当然不能用图片来当验证码,而且还有一个问题是,图片也不能保存在硬盘上。

还需要导入下面的模块

from PIL import ImageDraw,ImageFont (画笔和字体)
from io import BytesIO(用于将图片暂存在内存)

字体文件:http://oyh98v0ft.bkt.clouddn.com/kumo.ttf

from django.shortcuts import render, redirect, HttpResponse
import random
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from PIL import Image

def log_in(request):
    return render(request, 'login.html')

def get_valid_img(request):
    def get_random_color():
        # 生成随机色
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    def get_random_char():
        # 生成随机字符
        random_num = str(random.randint(0, 9))  # 随机数字
        random_upper_alph = chr(random.randint(65, 90))  # 随机大写字母
        random_lowwer_alph = chr(random.randint(79, 122))  # 随机小写字母
        random_char = random.choice([random_num, random_lowwer_alph, random_upper_alph])
        return random_char  # 返回随机字符

    # 生成画布图片
    image = Image.new(mode="RGB", size=(230, 35), color=get_random_color())
    # 生成画笔
    draw = ImageDraw.Draw(image, mode="RGB")
    # 指定字体
    font = ImageFont.truetype("blog/static/font/kumo.ttf", 32)
    # 写入6个随机字符(数字,字母)
    for i in range(1, 6):
        char = get_random_char()
        draw.text([i * 40, 5], char, get_random_color(), font=font)
    width = 230
    height = 35
    # 生成80个点
    for i in range(80):
        draw.point((random.randint(0, width), random.randint(0, height)), fill=get_random_color())
    # 生成两根干扰线
    for i in range(2):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=get_random_color())
    # 暂存内存
    f = BytesIO()
    image.save(f, "png")
    # 从内存中取
    data = f.getvalue()
    return HttpResponse(data)

views.py

给img添加点击局部刷新的功能:

img标签很特别,不需要ajax,如下。

<script>
         $("#valid_img").click(function () {
         $(this)[0].src+="?"
     });
</script>

  

验证码初步完成,下面完成登录验证功能。

因为要验证验证码是否输入正确,我需要找一个容器存验证码,到后台去对比,这个容器就是session!

下面,看我操作

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^blog/', include('blog.urls')),
    url(r'^', include('blog.urls')),
]

mysit.urls.py

from django.conf.urls import url, include
from . import views

urlpatterns = [

    # 登录
    url(r'^login/$', views.log_in),
    # 验证码
    url(r'^get_valid_img/$', views.get_valid_img, name='get_valid_img'),
    # 主页
    url(r'^index/$', views.index, name='index'),

]

blog.urls.py

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/css/login.css">

<body>

<div class="container ">
    <div class="row ">
        <form action="" class="form-horizontal col-md-6 col-md-offset-3">
            {% csrf_token %}
            <div class="form-group">
                <label for="username">用户名</label>
                <input type="text" class="form-control" id="username">
            </div>

            <div class="form-group">
                <label for="password">密码</label>
                <input type="password" class="form-control" id="password">
            </div>

            <div class="form-group">
                <label for="valid_code">验证码</label>
                <div class="row">
                    <div class="col-md-6">
                        <input type="text" class="form-control" id="valid_code">
                    </div>
                    <div class="col-md-6">
                        <img src="/get_valid_img/" alt="" width="230" height="35" id="valid_img">
                    </div>
                </div>

            </div>
            <div class="form-group">
                <input type="button" value="登录" class="btn btn-primary form-control" id="loginBtn">

            </div>

        </form>
        <span id="error_msg"></span>
    </div>
</div>

<script src="/static/js/jquery-3.2.1.min.js"></script>
<script src="/static/plugins/bootstrap/js/bootstrap.min.js"></script>

<script>
    // 局部刷新验证码
    $("#valid_img").click(function () {
        $(this)[0].src += "?"
    });
    //ajax 登录
    $("#loginBtn").click(function () {
        $.ajax({
            url: '/login/',
            type: 'POST',
            data: {
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                username: $("#username").val(),
                password: $("#password").val(),
                valid_code: $("#valid_code").val()

            },
            success: function (data) {
                // 验证通过,进入主页
                if (data.user) {
                    location.href = '/index/'

                }
                // 验证不通过,就提示错误信息
                else {
                    $("#error_msg").text(data.error_msg).css("color", "red")
                    // 定时清除错误信息,8秒钟
                    setTimeout(function () {
                        $("#error_msg").text("")
                    }, 8000)
                }
            }

        })
    });
</script>
</body>
</html> 

views.py

from django.shortcuts import render, redirect, HttpResponse
import random
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from PIL import Image
from django.contrib import auth
from django.http import JsonResponse

def get_valid_img(request):
    def get_random_color():
        # 生成随机色
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    def get_random_char():
        # 生成随机字符
        random_num = str(random.randint(0, 9))  # 随机数字
        random_upper_alph = chr(random.randint(65, 90))  # 随机大写字母
        random_lowwer_alph = chr(random.randint(79, 122))  # 随机小写字母
        random_char = random.choice([random_num, random_lowwer_alph, random_upper_alph])
        return random_char  # 返回随机字符

    # 生成画布图片
    image = Image.new(mode="RGB", size=(230, 35), color=get_random_color())
    # 生成画笔
    draw = ImageDraw.Draw(image, mode="RGB")
    # 指定字体
    font = ImageFont.truetype("blog/static/font/kumo.ttf", 32)
    valid_code_str = ""  # 用来拼接验证码
    # 写入6个随机字符(数字,字母)
    for i in range(1, 6):
        char = get_random_char()
        valid_code_str += char  # 拼接验证码
        draw.text([i * 40, 5], char, get_random_color(), font=font)
    width = 230
    height = 35
    # 生成80个点
    for i in range(80):
        draw.point((random.randint(0, width), random.randint(0, height)), fill=get_random_color())
    # 生成两根干扰线
    for i in range(2):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=get_random_color())
    # 暂存内存
    f = BytesIO()
    image.save(f, "png")
    # 从内存中取
    data = f.getvalue()
    # 将验证码保存在session
    request.session["valid_code_str"] = valid_code_str
    return HttpResponse(data)

def log_in(request):
    if request.is_ajax():
        user = request.POST.get('username')
        pwd = request.POST.get('pwd')
        valid_code = request.POST.get('valid_code')
        # 获取session里面的验证码
        valid_code_str = request.session.get("valid_code_str")
        # 也可以这样写:valid_code_str=request.session["valid_code_str"]
        loginResponse = {"user": None, "error_msg": ''}
        # 先对验证码进行校验(不区分大小写)
        if valid_code_str.upper() == valid_code.upper():
            # 验证码通过,再对用户名密码进行校验(要导入auth)
            user = auth.authenticate(username=user, password=pwd)
            if user:
                auth.login(request, user)  # 设置session
                loginResponse["user"] = user.username
            else:
                loginResponse["error_msg"] = "username or password is wrong!"
        else:
            # 验证码不通过,不再进行下面的验证,直接返回提示错误信息
            loginResponse["error_msg"] = " valid code is wrong!"
            # JsonResponse可完成json数据的转换工作,简便!
        return JsonResponse(loginResponse)

    return render(request, 'login.html')

def index(request):
    return render(request, 'index.html')

效果:

验证码错误时:

验证码正确时(密码也错误)

美化版:

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css">
    <style>
        body {
            background-color: #eeeeee;
            margin-top: 100px;
        }
    </style>
<body>

<div class="container ">
    <div class="row ">
        <div class=" col-sm-6 col-sm-offset-3">
            <form action="" class="form-horizontal">
                {% csrf_token %}
                <div class="form-group">
                    <label for="username" class="col-sm-2 control-label">用户名</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="username" placeholder="Username">
                    </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" placeholder="Password">
                    </div>

                </div>

                <div class="form-group">
                    <label for="valid_code" class="col-sm-2 control-label">验证码</label>
                    <div class="col-sm-5">
                        <input type="text" class="form-control" id="valid_code" placeholder="Validcode">
                    </div>
                    <div class="col-sm-5">
                        <img style="margin-left: -17px" src="/get_valid_img/" alt="" width="230" height="33"
                             id="valid_img">
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <input type="button" value="登录" class="btn btn-primary form-control" id="loginBtn">
                    </div>
                </div>
                <div class="col-sm-offset-2 col-sm-10">
                    <div class="reg" style="margin-left: -10px">还没账号?<a href="/register/">立即注册</a></div>
                </div>

            </form>
        </div>
        <span id="error_msg"></span>
    </div>
</div>

<script src="/static/js/jquery-3.2.1.min.js"></script>
<script src="/static/plugins/bootstrap/js/bootstrap.min.js"></script>

<script>
    // 局部刷新验证码
    $("#valid_img").click(function () {
        $(this)[0].src += "?"
    });
    //ajax 登录
    $("#loginBtn").click(function () {
        $.ajax({
            url: '/login/',
            type: 'POST',
            data: {
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                username: $("#username").val(),
                password: $("#password").val(),
                valid_code: $("#valid_code").val()

            },
            success: function (data) {
                // 验证通过,进入主页
                if (data.user) {
                    location.href = '/index/'

                }
                // 验证不通过,就提示错误信息
                else {
                    $("#error_msg").text(data.error_msg).css("color", "red")
                    // 定时清除错误信息,8秒钟
                    setTimeout(function () {
                        $("#error_msg").text("")
                    }, 8000)
                }
            }

        })
    });
</script>
</body>
</html> 

login.html

Django 博客项目01 数据库设计与验证码校验+Ajax登录的更多相关文章

  1. django博客项目8:文章详情页

    首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按钮,应该跳转到文章的详情页面来阅读文章的详细内容.现在让我们来开发博客的详情页面,有了前面的基础,开发流程都是一样 ...

  2. django博客项目3:创建 Django 博客的数据库模型

    设计博客的数据库表结构 博客最主要的功能就是展示我们写的文章,它需要从某个地方获取博客文章数据才能把文章展示出来,通常来说这个地方就是数据库.我们把写好的文章永久地保存在数据库里,当用户访问我们的博客 ...

  3. Django——博客项目

    博客项目 目前的目标是构建一个基于Django的前后端完整的博客系统,首先对项目流程整理如下: 1. 分析需求 1.1. 基于用户认证组件和Ajax实现登录验证 图形验证码核心代码: 模板: < ...

  4. django博客项目5:博客首页视图(2)

    真正的 Django 博客首页视图 在此之前我们已经编写了 Blog 的首页视图,并且配置了 URL 和模板,让 Django 能够正确地处理 HTTP 请求并返回合适的 HTTP 响应.不过我们仅仅 ...

  5. 9.28 Django博客项目(一)

    2018-9-28 17:37:18 今天把博客项目 实现了注册和添加图片的功能! 放在了自己的github上面 源码! https://github.com/TrueNewBee/bbs_demo ...

  6. django博客项目6:Django Admin 后台发布文章

    在此之前我们完成了 Django 博客首页视图的编写,我们希望首页展示发布的博客文章列表,但是它却抱怨:暂时还没有发布的文章!如它所言,我们确实还没有发布任何文章,本节我们将使用 Django 自带的 ...

  7. django博客项目2.建立 Django 博客应用

    建立博客应用 我们已经建立了 Django 博客的项目工程,并且成功地运行了它.不过到目前为止这一切都还只是 Django 为我们创建的项目初始内容,Django 不可能为我们初始化生成博客代码,这些 ...

  8. django博客项目1.环境搭建

    安装 Python Windows 下安装 Python 非常简单,去 Python 官方网站找到 Python 3 的下载地址,根据你的系统选择 32 位或者 64 位的安装包,下载好后双击安装即可 ...

  9. <Django>博客项目

    0.项目的通用流程 项目立项 需求分析 原型 前端 页面设计 UI及交互实现 后端 架构设计 数据库设计 代码模板实现 单元测试 网站整合 功能及集成测试 网站发布 1.BBS项目需求分析 需要哪些表 ...

随机推荐

  1. duilib CEditUI 禁止输入中文字符,禁止复制粘贴

    1.CEditUI 禁止使用中文输入法 在 CEditUI::DoEvent 函数中,添加代码: if(m_bOnlyEnglishChar && m_pWindow &&am ...

  2. SGU 110. Dungeon 计算几何 难度:3

    110. Dungeon time limit per test: 0.25 sec. memory limit per test: 4096 KB The mission of space expl ...

  3. Android JNI作用及其详解

    Android JNI作用及其详解 Java Native Interface (JNI)标准是Java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 J ...

  4. Cetus

    转自:https://github.com/Lede-Inc/cetus Cetus 简介 Cetus是由C语言开发的关系型数据库MySQL的中间件,主要提供了一个全面的数据库访问代理功能.Cetus ...

  5. apscheduler -定时任务

    https://apscheduler.readthedocs.io/en/latest/userguide.html 简单的使用方式为: from apscheduler.schedulers.bl ...

  6. iOS多线程编程:线程同步总结

    1:原子操作 - OSAtomic系列函数 iOS平台下的原子操作函数都以OSAtomic开头,使用时需要包含头文件<libkern/OSBase.h>.不同线程如果通过原子操作函数对同一 ...

  7. L207

    The leaders of the two countries are planning their summit meeting with a (pledge) to maintain and d ...

  8. kbmMW TkbmMWHashSHA256与Delphi 10.2 THashSHA2算出相同的结果

    procedure TForm2.Button3Click(Sender: TObject); var hashed:string; begin hashed:=TkbmMWHashSHA256.Ha ...

  9. Android Mms专题之:Mms源码结构

    从软件的功能角度来讲,Mms分为对话列表,消息列表,短信编辑,彩信编辑,短信显示,彩信显示和配置. 从实现的角度来看,它分为GUI展示层,发送/接收,彩信解析,彩信附件,信息数据等,这些分类对应着源码 ...

  10. python3:xlrd、xlwt、xlutils处理excel文件

    1.xlrd读取excel 请参考上篇博客https://www.cnblogs.com/shapeL/p/9075843.html 2.xlwt生成excel 安装下载:pip install xl ...