数据库设计

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. 标准库中 vector list等排序

    1.list自带有排序函数sort():可以定义自己的排序规则,如: struct stTest { int count; wstring str; }; bool SortByNum(const s ...

  2. PHP:第一章——PHP中逻辑运算符的使用方法

    //逻辑运算符 $a=;$b=;$c=;$d=; //逻辑与(and 和 &&)他们两个的逻辑是一样的,如果两个值都为true,结果才为true,否则是false. //var_dum ...

  3. 利用express.js连接mongodb数据库

    var MongoClient = require('mongodb').MongoClient; var DB_CONN_STR = "mongodb://localhost:27017/ ...

  4. EhLib TitleButton SVisibleColumnsEh = '错误的列';

    unit EhLibConsts; interface resourcestring SClearSelectedCellsEh = '清除选择的单元?'; SInvalidTextFormatEh ...

  5. Java——File类概述

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

  6. hdu 1556 Color the ball (线段树+代码详解)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  7. 解压Ubuntu的initrd.img的方法

    Ubuntu的initrd.img可以在/boot中找到,通常文件名后面还跟有很长的一串版本号. 为了保险起见,不直接操作原文件,而是把它复制到自己的家目(home)录中.如果你是用root帐号登录的 ...

  8. OC基础知识总结 分类: ios学习 OC 2015-06-26 17:58 58人阅读 评论(0) 收藏

    //OC: Objective-C, 面向对象的C语言 //OC与C的区别 //1.OC是C的超集, C语言的所有语法都可以在OC中使用 //2.OC是面向对象 //3.OC是一门运行时语言 //4. ...

  9. App Transfer:苹果允许iOS App从一个开发者帐号转至另一个开发者账号

    App Transfer:苹果允许iOS App从一个开发者帐号转至另一个开发者账号 苹果在WWDC上宣布超过30万的开发者为iOS平台开发超过90万的应用,你可能会想到有人想出售或者购买app. 现 ...

  10. iOS被开发者遗忘在角落的NSException-其实它很强大

    NSException是什么? 最熟悉的陌生人,这是我对NSException的概述,为什么这么说呢?其实很多开发者接触到NSException的频率非常频繁,但很多人都不知道什么是NSExcepti ...