博客系统

 博客系统项目整理:

 一:创建表:

models代码:

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

class UserInfo(AbstractUser):
    '''用户信息表'''
    nid = models.AutoField(primary_key=True)
    nickname = models.CharField(max_length=32,verbose_name="昵称",unique=True,null=True,blank=True)
    tel = models.CharField(max_length=11,  verbose_name='电话',unique=True, null=True,blank=True)
    avatar = models.FileField(verbose_name="头像",upload_to="avatar",default="/avatar/default.png")
    create_time = models.DateTimeField(verbose_name="创建时间",auto_now_add=True)
    class Meta:
        verbose_name_plural = "用户信息表"
    def __str__(self):
        return self.username

class Article(models.Model):
    '''
    文章表
    '''
    title = models.CharField(max_length=64,verbose_name="文章标题")
    summary = models.CharField(max_length=244, verbose_name="文章概要")
    create_time = models.DateTimeField(verbose_name="创建时间",auto_now_add=True)
    update_time = models.DateTimeField(verbose_name="修改时间",auto_now=True)
    poll_count = models.IntegerField(verbose_name="点赞数",default=0)
    comment_count = models.IntegerField(verbose_name="评论数",default=0)
    read_count = models.IntegerField(verbose_name="阅读数",default=0)
    # is_essence = models.BooleanField(verbose_name="是否精华",default=0)
    # is_top = models.BooleanField(verbose_name="是否置顶",default=0)

    user = models.ForeignKey(to="UserInfo",verbose_name="所属作者",null=True,blank=True)
    classify = models.ForeignKey(to="Classfication",verbose_name="所属类别",null=True,blank=True)
    tags = models.ManyToManyField(to="Tag",through="Article2tag",through_fields=('article', 'tag'),verbose_name="所属标签")
    site_article_category = models.ForeignKey(to="SiteArticleCategory", null=True,verbose_name="文章分类")
    class Meta:
        verbose_name_plural = "文章表"
    def __str__(self):
        return self.title

class Article_detail(models.Model):
    '''文章细节表'''
    article = models.OneToOneField(to="Article",verbose_name="所属文章")
    content = models.TextField(verbose_name="文章内容")

    class Meta:
        verbose_name_plural = "文章细节表"

class Tag(models.Model):
    '''标签表'''
    name = models.CharField(max_length=32,verbose_name="标签名")
    blog = models.ForeignKey(to="Blog",verbose_name="所属博客")
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural = "标签表"

class Article2tag(models.Model):
    article = models.ForeignKey(verbose_name="文章",to="Article")
    tag = models.ForeignKey(verbose_name="标签",to="Tag")
    class Meta:
        '''联合唯一'''
        unique_together = [
            ("article","tag")
        ]

class Comment(models.Model):
    '''评论表'''
    time = models.DateTimeField(verbose_name="评论时间",auto_now_add=True)
    content = models.CharField(max_length=265,verbose_name="评论内容")
    up_count = models.IntegerField(default=0)
    user = models.ForeignKey(to="UserInfo",verbose_name="评论人",null=True,blank=True)
    article = models.ForeignKey(to="Article",verbose_name="评论文章",null=True,blank=True)
    farther_comment = models.ForeignKey(to="Comment",verbose_name="父级评论",null=True,blank=True)
    # farther_comment = models.ForeignKey("self",verbose_name="父级评论",null=True,blank=True)

    class Meta:
        verbose_name_plural = "评论表"

class Article_poll(models.Model):
    '''文章点赞表'''
    time = models.DateTimeField(verbose_name="点赞时间",auto_now_add=True)
    article = models.ForeignKey(to="Article",verbose_name="点赞文章",null=True,blank=True)   #一个文章可以有多个赞
    user = models.ForeignKey(to="UserInfo",verbose_name="点赞人",null=True,blank=True)
    # is_positive = models.BooleanField(default=1,verbose_name="点赞或踩")

    class Meta:
        '''联合唯一'''
        unique_together = ("user", "article",)
        verbose_name_plural = "文章点赞表"

class Comment_poll(models.Model):
    '''评论点赞表'''
    time=models.DateTimeField(verbose_name="点赞时间",auto_now_add=True)
    # is_positive = models.BooleanField(verbose_name="点赞或踩",default=1)
    user = models.ForeignKey(to="UserInfo",verbose_name="点赞用户",null=True,blank=True)
    comment = models.ForeignKey(to="Comment",verbose_name="点赞所属评论",null=True,blank=True)   #一个评论可以有多个赞

    class Meta:
        '''联合唯一'''
        unique_together = ("user","comment",)
        verbose_name_plural = "评论点赞表"

class Blog(models.Model):
    '''个人站点表'''
    title = models.CharField(max_length=32,verbose_name="个人博客标题")
    url = models.CharField(max_length=64,verbose_name="路径",unique=True)
    theme = models.CharField(max_length=32,verbose_name="博客主题")
    user = models.OneToOneField(to="UserInfo", verbose_name="所属用户")
    class Meta:
        verbose_name_plural = "个人站点表Blog"
    def __str__(self):
        return self.title

class Classfication(models.Model):
    '''博主个人文章分类表'''
    title = models.CharField(max_length=32, verbose_name="分类标题")
    blog = models.ForeignKey(to="Blog",verbose_name="所属博客")
    def __str__(self):
        return self.title
    class Meta:
        verbose_name_plural = "分类表"

#与文章表关联,属于博客全局的分类
class SiteCategory(models.Model):
    """
    博客主页分类,父
    """
    name=models.CharField(max_length=32)
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural = "博客主页分类,父"

class SiteArticleCategory(models.Model):
    """
    博客主页分类,子
    """
    name=models.CharField(max_length=32)
    site_category=models.ForeignKey("SiteCategory")
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural = "博客主页分类,子"
View Code

admin:

from django.contrib import admin
# Register your models here.
from . import models
admin.site.register(models.UserInfo)
admin.site.register(models.Article)
admin.site.register(models.Article_detail)
admin.site.register(models.Tag)
admin.site.register(models.Article2tag)
admin.site.register(models.Comment)
admin.site.register(models.Article_poll)
admin.site.register(models.Comment_poll)
admin.site.register(models.Blog)
admin.site.register(models.Classfication)
admin.site.register(models.SiteCategory)
admin.site.register(models.SiteArticleCategory)
View Code

配置---引用:

#配置 settings:   AUTH_USER_MODEL = "app01.UserInfo"
#引用from django.contrib.auth.models import AbstractUser

from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser
View Code

表关系:

博客系统表关系整理;
                1:创建用户信息表(UserInfo):-----------继承了AbstractUser(配置 settings:   AUTH_USER_MODEL = "app01.UserInfo")
                                    ----------(from django.contrib.auth.models import AbstractUser)
                        主键(ID)
                        昵称(nickname)
                        电话(tel)
                        邮箱(email)
                        头像(avatar)
                        创建时间(create_time)
                2:创建文章表(Acticle)
                        文章标题(title)
                        文章概要(summary)
                        创建时间(create_time)
                        修改时间(updata_time)
                        点赞数(poll_count)
                        评论数(comment_count)
                        阅读数(read_count)
                        作者(user)-------------------------------与信息表(Userinfo)是一对多的关系
                        所属类别(classify)-----------------------与分类表(Classify)是一对多的关系
                        标签(tag)--------------------------------与标签表(Tag)是多对多的关系,过滤关系,一篇文章只能有一层与标签的关系,不可重复。 
                        博客的类,固定字段只有选择的权限(type_choices)
                3文章详细表(Article_detail)
                        所属文章(article)------------------------与文章表是(Article)是一对一的关系
                        文章内容(content)
                4标签表(Tag)
                        标签名(name)
                        所属博客(blog)----------------------------与博客表是一对多的关系
                5博客和标签的关系表(Article2tag)--------------自己创建方便后面添加字段
                        文章(article)-----------------------------与文章表(Article)是多对一的关系
                        标签(tag)---------------------------------与标签表(Tag)是多对一的关系
                6:评论表
                        评论时间(time)
                        评论内容(content)
                        评论人(user)------------------------------与用户信息表(UserInfo)是多对一的关系
                        评论文章(article)-------------------------与文章表(Acticle)是多对一的关系
                        父级评论(father_comment)------------------自关联(可以评论别人的评论)
                7:文章点赞表(Article_poll)
                        点赞时间(time)
                        点赞文章(article)-------------------------与文章表(Acticle)是多对一的关系
                        点赞人(user)------------------------------与用户表(UserInfo)是多对一的关系
                8:评论点赞表(Comment_poll)
                        点赞时间(time)
                        点赞用户(user)----------------------------与用户信息表(UserInfo)是多对一的关系
                        点赞所属评论(comment)---------------------与评论表(Comment)是多对一的关系
                9:博客表(Blog)
                        个人博客标题(title)
                        路径(url)
                        theme(博客主题)
                        user(所属用户)----------------------------与用户信息表是(UserInfo)是一对一的关系
                10:博主个人文章分类表(Classfication)
                        分类标题(title)
                        所属博客(blog)----------------------------与博客表是(Blog)是多对一的关系
View Code

二:登录:

 界面显示

      

<!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">
    <title>博客系统首页</title>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <style>
        .hides{ display: none; }
    </style>
</head>
<body>
<nav class="navbar navbar-inverse primary">
    <div class="container">
            <a class="navbar-brand" href="#">博客园</a>
        <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse">
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                    <li><a href="">{{request.userinfo.uaername}}<span class="glyphicon glyphicon-user"></span></a></li>
                    <li><a href="/log_out/">注销</a></li>
                    <li><a href="/#/">修改密码</a></li>
                {% else %}
                    <li><a href="/login/">登录</a></li>
                    <li><a href="/register/">注册</a></li>
                {% endif %}
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="搜索">
            </form>
        </div>
    </div>
</nav>
<div class="container">
        <div class="row col-md-3">
            <div class="panel panel-primary">
                <div class="panel-body">
                    网站分类
                </div>
                <div class="panel-footer">
                    {% for site in site_list %}
                        <div class="panel panel-primary">
                            <div class="panel-heading cate_title">{{site.name}}</div>
                            <div class="panel-body hides">
                                {% for sitearticlecategory in site.sitearticlecategory_set.all %}
                                    <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p>
                                {% endfor %}
                            </div>
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
        <div class="col-md-6">
            <div class=" article_list">
                {% for article in article_list %}
                    <div><a href="">{{article.title}}</a></div>
                    <div class="row">
                        <div class="avatar col-md-2">
                            <a href="{% url 'aaa'  article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a>
                        </div>
                        <div class="summary col-md-10" >
                            <p>{{article.summary}}</p>
                        </div>
                    </div>
                    <div class="article_info row">
                        &nbsp&nbsp<a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a> &nbsp&nbsp发布与:{{article.create_time|date:"Y-m-d H:i"}}
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-comment"></span>评论({{article.comment_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{article.poll_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-share-alt"></span>阅读({{article.read_count}})</a>
                    </div>
                    <hr>
                {% endfor %}
            </div>
        </div>
        <div class="col-md-3">
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
        </div>
    </div>
<script>
     $(".cate_title").mouseover(function () {
        $(this).next().slideDown(300)
    }).parent().mouseleave(function () {
         $(this).children(".panel-footer").slideUp(300)
     });
{#    $(".cate_title").mouseenter(function () {#}
{#        $(this).next().slideDown(300)#}
{#    });#}
{#    $(".panel-footer").mouseleave(function () {#}
{#        $(this).next().slideUp(300)#}
{#    });#}
</script>
</b

导入:

 url

url(r'^get_authCode_img/', views.get_authCode_img),
    url(r'^login/$',views.login),

前端页面的实现:

<!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">
    <title>博客系统首页</title>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <style>
        .hides{ display: none; }
    </style>
</head>
<body>
<nav class="navbar navbar-inverse primary">
    <div class="container">
            <a class="navbar-brand" href="#">博客园</a>
        <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse">
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                    <li><a href="">{{request.userinfo.uaername}}<span class="glyphicon glyphicon-user"></span></a></li>
                    <li><a href="/log_out/">注销</a></li>
                    <li><a href="/#/">修改密码</a></li>
                {% else %}
                    <li><a href="/login/">登录</a></li>
                    <li><a href="/register/">注册</a></li>
                {% endif %}
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="搜索">
            </form>
        </div>
    </div>
</nav>
<div class="container">
        <div class="row col-md-3">
            <div class="panel panel-primary">
                <div class="panel-body">
                    网站分类
                </div>
                <div class="panel-footer">
                    {% for site in site_list %}
                        <div class="panel panel-primary">
                            <div class="panel-heading cate_title">{{site.name}}</div>
                            <div class="panel-body hides">
                                {% for sitearticlecategory in site.sitearticlecategory_set.all %}
                                    <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p>
                                {% endfor %}
                            </div>
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
        <div class="col-md-6">
            <div class=" article_list">
                {% for article in article_list %}
                    <div><a href="">{{article.title}}</a></div>
                    <div class="row">
                        <div class="avatar col-md-2">
                            <a href="{% url 'aaa'  article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a>
                        </div>
                        <div class="summary col-md-10" >
                            <p>{{article.summary}}</p>
                        </div>
                    </div>
                    <div class="article_info row">
                        &nbsp&nbsp<a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a> &nbsp&nbsp发布与:{{article.create_time|date:"Y-m-d H:i"}}
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-comment"></span>评论({{article.comment_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{article.poll_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-share-alt"></span>阅读({{article.read_count}})</a>
                    </div>
                    <hr>
                {% endfor %}
            </div>
        </div>
        <div class="col-md-3">
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
        </div>
    </div>
<script>
     $(".cate_title").mouseover(function () {
        $(this).next().slideDown(300)
    }).parent().mouseleave(function () {
         $(this).children(".panel-footer").slideUp(300)
     });
{#    $(".cate_title").mouseenter(function () {#}
{#        $(this).next().slideDown(300)#}
{#    });#}
{#    $(".panel-footer").mouseleave(function () {#}
{#        $(this).next().slideUp(300)#}
{#    });#}
</script>
</body>
</
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>用户登录页面</title>
    <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="/static/css/login.css">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row col-md-4 col-lg-offset-4 container">
        <form method=post>
                {% csrf_token %}
                <h1 class="form-signin-heading col-lg-offset-4 text-primary"><b>请登录:</b></h1>
                 <hr>
                <div>
                    <label for="username">用户名:</label>
                    <p class="username"><input id="username" class="form-control" placeholder="用户名"  type="text" name="username"></p>
                </div>
                <div>
                    <label for="password">密码:</label>
                    <p class="password"><input id="password" class="form-control" placeholder="密码"  type="password" name="password"></p>
                </div>
                <div>
                    <label for="auth_code">验证码:</label>
                    <p class="auth_code"><input id="auth_code" class="form-control" placeholder="验证码"  type="text" name="auth_code"></p>
                </div>
                <div>
                    <img class="auth_code_img" src="/get_authCode_img/" style="200px;height:50px">
{#                    <a class="refresh">看不清</a>#}
                </div>
            <hr>
            <input type="button" value="登录" class="btn btn-lg btn-primary pull-left" id="subBtn"><span class="error"></span>
            <a href="/register/"> <input type="button" value="注册" class="btn btn-lg btn-primary pull-right" id=""></a>
        </form>
    </div>
</div>
<script>
    //登录
   $("#subBtn").click(function () {
       $.ajax({
           url:"/login/",
           type:"POST",
           data:{
               "username":$("#username").val(),
               "password":$("#password").val(),
               "auth_code":$("#auth_code").val(),
               "csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()
           },
           success:function (data) {
               console.log(data);
               var response=JSON.parse(data);
               if (response["is_login"]){
                   location.href="/index/"
               }
               else {
                    $(".error").html(response["error_msg"]).css("color","red")
               }
           }
       })
   });
    // 验证码刷新
    $(".auth_code_img").click(function () {
        $(this)[0].src+="?"
    })
</script>
</body>
</html>
View Code

后端代码:

 登录
def login(request):
    if request.is_ajax():
        login_response = {"is_login": False, "error_msg": None}  # 定义一个字典
        username = request.POST.get("username")  # 取到用户名
        password = request.POST.get("password")  # 取到密码
        auth_code = request.POST.get("auth_code")  # 取到验证码
        if auth_code.upper() == request.session.get("auth_code").upper():  # 从session中获取验证码,判断是否正确
            # print(username, password, '==========')
            user = auth.authenticate(username=username, password=password)
            print(user)  # 通过auth模块获取用户名密码
            if user:  # 正确,判断用户名和密码是否正确
                login_response["is_login"] = True
                auth.login(request, user)
            else:
                login_response["error_msg"] = "用户名或密码不正确"  # 前端显示用户名或密码错误
        else:
            login_response["error_msg"] = '验证码不正确'  # 前端显示验证码错误
        return HttpResponse(json.dumps(login_response))  # 返回
    return render(request, "login.html")  # 若不是Ajax访问方式,返回登录页面重新登录
View Code

验证码:

# 登录
def login(request):
    if request.is_ajax():
        login_response = {"is_login": False, "error_msg": None}  # 定义一个字典
        username = request.POST.get("username")  # 取到用户名
        password = request.POST.get("password")  # 取到密码
        auth_code = request.POST.get("auth_code")  # 取到验证码
        if auth_code.upper() == request.session.get("auth_code").upper():  # 从session中获取验证码,判断是否正确
            # print(username, password, '==========')
            user = auth.authenticate(username=username, password=password)
            print(user)  # 通过auth模块获取用户名密码
            if user:  # 正确,判断用户名和密码是否正确
                login_response["is_login"] = True
                auth.login(request, user)
            else:
                login_response["error_msg"] = "用户名或密码不正确"  # 前端显示用户名或密码错误
        else:
            login_response["error_msg"] = '验证码不正确'  # 前端显示验证码错误
        return HttpResponse(json.dumps(login_response))  # 返回
    return render(request, "login.html")  # 若不是Ajax访问方式,返回登录页面重新登录
View Code

验证码刷新:

// 验证码刷新
    $(".auth_code_img").click(function () {
        $(this)[0].src+="?"
    })
View Code

注销:

#注销
def log_out(request):
    auth.logout(request)
    return redirect("/login/")
View Code

css代码:

.container{
    margin-top:20px;
  }
View Code

请求流程:

流程:

1:客户端-----------发送(第一次get请求)-------------客户端返回一个Html页面(登录页面)
2:验证码-----------src(url再次请求服务端)----------服务端执行验证码函数,生成验证码保存在session中
3:用户输入内容----点击提交发送ajax请求---(Post)----服务端从request中拿到ajax请求信息。
4:从session中取出取出验证码和--ajax中的信息进行匹配。
5:匹配成功---------进行下一步验证,失败返回错误信息,在Html页面渲染。
6:通过auth模块获取用户名密码,判断用户名和密码是否和数据库中的相同。
7:若相同,写入定义的字典中。
	一“is_login”:true-----保存在session中,跳转到首页
8:若不相同,返回登录页面,渲染错误信息。
              1,用ajax提交数据 $(".log_btn").click(function(){ $.ajax({ url:url路径 type:访问状态 headers: {"X-CSRFToken":
                  $.cookie('csrftoken')},#跨站请求访问 返回的数据 data:{ 字典名:$(".字段标识名").val() } 接收数据 sussecc:funsess(data){ 函数 } }) }
              2、图片刷新(写在sussecc函数中) 原理:给图片绑定一个点击事件:每次给src+?就会再次发送一次get请求,就起到了刷星的作用 dom对象 $(".validCode_img")
                  .click(function () { $(this)[0].src+="?";

随机验证码:

    方式一:将图片导入静态文件,用文件句柄打开图片返回给前端进行渲染
    方式二:导入PIL模块,利用Image生成一张图片保存后,用文件举兵打开,返回前端
    方式三:导入PIL、IO模块,还是利用Image生成图片,但是这次没有将图片保存到磁盘而是将图片利用IO模块中的BytesIO暂时的保存到内存中,用BytesIO句柄打开,返回到前端。
    方式四:对方式三进行优化,加上了random模块可以让图片随机生成,加上随机的5个字符,基本的验证码就显示出来了
 验证原理:
因为随机码是用for循环生成的先将它放入一个列表中,人后将列表转换
为字符串,存入session中便于做对比,接收前端发过来的数据,包括用
户名密码以及验证码三条数据,先拿session中保存的验证码与前段发来
的验证码进行匹配验证,如果匹配成功则进行用户名密码的匹配匹配成功
则登录成功
 
 代码: 
def get_authCode_img(request):
    #方式一
    # import os
    # path = os.path.join(settings.BASE_DIR, "static", "img", "a.jpg")
    # with open(path, "rb") as f:
    #     data = f.read()
    # return HttpResponse(data)
    # 方式2:
    # from  PIL import Image
    # img=Image.new(mode="RGB",size=(120,40),color="green")
    # f=open("validCode.png","wb")
    # img.save(f,"png")
    # with open("validCode.png","rb") as f:
    #     data=f.read()
    # return HttpResponse(data)
    # 方式3:
    # from io import BytesIO
    # from PIL import Image
    # img = Image.new(mode="RGB", size=(120, 40), color="blue")
    # f=BytesIO()
    # img.save(f,"png")
    # data=f.getvalue()
    # return HttpResponse(data)
# 方式4 :
    from io import BytesIO
    import random
    from PIL import Image,ImageDraw,ImageFont
    img = Image.new(mode="RGB", size=(120, 40), color=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
    draw=ImageDraw.Draw(img,"RGB")
    font=ImageFont.truetype("static/font/kumo.ttf",25)
    valid_list=[]
    for i in range(5):
        random_num=str(random.randint(0,9))
        random_lower_zimu=chr(random.randint(65,90))
        random_upper_zimu=chr(random.randint(97,122))
        random_char=random.choice([random_num,random_lower_zimu,random_upper_zimu])
        draw.text([5+i*24,10],random_char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
        valid_list.append(random_char)
    f=BytesIO()
    img.save(f,"png")
    data=f.getvalue()
    valid_str="".join(valid_list)
    print(valid_str)
    request.session["Keep_auth_code"]=valid_str   #将验证码写入session中
    return HttpResponse(data)
View Code

三:注册:

  页面

 

 

form组件:

#! usr/bin/env python
# -*- coding: utf-8 -*-
from django import forms
from django.forms import fields
from django.forms import widgets,ValidationError
from app01 import models
from django.core.validators import RegexValidator
class RegisterForm(forms.Form):
    """注册Form组件"""
    username = forms.CharField(
        required=True,
        min_length=3,
        max_length=8,
        error_messages={
            'required': '用户不能为空',
            'min_length': '用户长度不能小于3',
            'max_length': '用户长度不能大于8',
        },widget=widgets.TextInput(attrs={'placeholder': '用户名:', 'class': 'form-control'}))
    password = fields.CharField(
        required=True,
        min_length=3,
        max_length=8,
        error_messages={
            'required': '密码不能为空',
            'min_length': '密码长度不能小于3',
            'max_length': '密码长度不能大于8',
            # 'invalid': '密码格式错误',
        },
        # validators=[RegexValidator('d+', '只能是数字')],
        widget=widgets.PasswordInput(attrs={'placeholder': '密码:', 'class': 'form-control'}))
    confirm_password = fields.CharField(
        required=True,
        min_length=3,
        max_length=8,
        error_messages={
            'required': '确认密码不能为空',
            'min_length': '确认密码长度不能小于3',
            'max_length': '确认密码长度不能大于8',
        },
        widget=widgets.PasswordInput(attrs={'placeholder': '确认密码:', 'class': 'form-control'}))

    email = fields.EmailField(
        required=True,
        error_messages={
            'required':'邮箱不能为空',
            'invalid':'邮箱格式错误'},
        widget=widgets.EmailInput(attrs={'placeholder':'邮箱:','class':'form-control'}))


    def clean_username(self):
        """用户名"""
        ret = models.UserInfo.objects.filter(username=self.cleaned_data.get("username"))
        if not ret:
            return self.cleaned_data.get("username")
        else:
            raise ValidationError("用户名已注册")

    def clean_password(self):
        """密码"""
        data = self.cleaned_data.get("password")
        if not data.isdigit():
            return self.cleaned_data.get("password")
        else:
            raise ValidationError("密码不能全是数字")

    # def clean_auth_code(self):
    #     if self.cleaned_data.get("auth_code")==self.request.session.get("auth_code"):
    #         return self.cleaned_data.get("auth_code")
    #     else:
    #         raise ValidationError("验证码错误")

    def clean(self):
        if self.cleaned_data.get("password")==self.cleaned_data.get("confirm_password"):
             return self.cleaned_data
        else:
            raise ValidationError("两次密码不一致")

    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request=request
View Code

前端页面显示:

from django.shortcuts import render, HttpResponse, redirect
from app01.forms import *
from app01 import forms
from app01 import models
from django.db.models import Count
import json
from django.contrib import auth
# 登录
def login(request):
    if request.is_ajax():
        login_response = {"is_login": False, "error_msg": None}  # 定义一个字典
        username = request.POST.get("username")  # 取到用户名
        password = request.POST.get("password")  # 取到密码
        auth_code = request.POST.get("auth_code")  # 取到验证码
        if auth_code.upper() == request.session.get("auth_code").upper():  # 从session中获取验证码,判断是否正确
            # print(username, password, '==========')
            user = auth.authenticate(username=username, password=password)
            print(user)  # 通过auth模块获取用户名密码
            if user:  # 正确,判断用户名和密码是否正确
                login_response["is_login"] = True
                auth.login(request, user)
            else:
                login_response["error_msg"] = "用户名或密码不正确"  # 前端显示用户名或密码错误
        else:
            login_response["error_msg"] = '验证码不正确'  # 前端显示验证码错误
        return HttpResponse(json.dumps(login_response))  # 返回
    return render(request, "login.html")  # 若不是Ajax访问方式,返回登录页面重新登录
# 验证码
def get_authCode_img(request):
    from io import BytesIO
    import random
    from PIL import Image, ImageDraw, ImageFont
    img = Image.new(mode="RGB", size=(120, 40),
                    color=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
    draw = ImageDraw.Draw(img, "RGB")
    font = ImageFont.truetype("static/font/kumo.ttf", 25)
    valid_list = []
    for i in range(5):
        random_num = str(random.randint(0, 9))
        random_lower_zimu = chr(random.randint(65, 90))
        random_upper_zimu = chr(random.randint(97, 122))
        random_char = random.choice([random_num, random_lower_zimu, random_upper_zimu])
        draw.text([5 + i * 24, 10], random_char,
                  (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)), font=font)
        valid_list.append(random_char)
    f = BytesIO()
    img.save(f, "png")
    data = f.getvalue()
    valid_str = "".join(valid_list)
    print(valid_str)
    request.session["auth_code"] = valid_str  # 将验证码写入session中
    return HttpResponse(data)
#注销
def log_out(request):
    auth.logout(request)
    return redirect("/login/")
# 注册
def register(request):
    if request.is_ajax():
        form_obj = forms.RegisterForm(request,request.POST)
        print("---------")
        print(form_obj.is_valid())
        regResponse = {"user": None, "errorsList": None}
        if form_obj.is_valid():
            print("000000")
            username = form_obj.cleaned_data["username"]
            password = form_obj.cleaned_data["password"]
            # nickname = form_obj.cleaned_data["nickname"]
            # tel = form_obj.cleaned_data["tel"]
            email = form_obj.cleaned_data.get("email")
            avatar_img = request.FILES.get("avatar_img")
            user_obj = models.UserInfo.objects.create_user(username=username, password=password,email=email,avatar=avatar_img)
            regResponse["user"] = user_obj.username
        else:
            print("111")
            regResponse["errorsList"] = form_obj.errors
            print(regResponse)
        return HttpResponse(json.dumps(regResponse))
    form_obj= forms.RegisterForm(request)
    return render(request, "register.html", {"form_obj": form_obj})
# 主页
def index(request,*args,**kwargs):
    if kwargs:
        article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找点击的类的文章
    else:
        article_list = models.Article.objects.all()
    site_list = models.SiteCategory.objects.all()
    return render(request, "index.html",{"article_list":article_list,"site_list":site_list})
#个人主页
def homeSite(request,username,**kwargs):
    # print(kwargs)
    # print(username)
    """点击文章用户名或,头像跳转的此页"""
    current_user = models.UserInfo.objects.filter(username=username).first()#获取当前用户
    # current_blog = current_user.blog#获取当前博客
    if not current_user:
        return render(request,"notFound.html")
    current_blog = current_user.blog  # 获取当前博客
    #查询当前文章
    article_list=models.Article.objects.filter(user=current_user)
    #查询 当前用户的分类归档
    classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c")
    #查询当前用户的标签归档
    tag_list=models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name","c")
    #查询当前用户的标签归档
    date_list = models.Article.objects.filter(user=current_user).extra(
        select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(Count("id"))
    if kwargs:
        if kwargs.get("condition")=="classify":
            print(kwargs.get("condition"))
            article_list = models.Article.objects.filter(user=current_user,classify__title=kwargs.get("para"))
            # article_list = models.Article.objects.filter(user=current_user, category__title=kwargs.get("para"))
        elif kwargs.get("condition")=="tag":
            article_list = models.Article.objects.filter(user=current_user,tags__name=kwargs.get("para"))
        elif kwargs.get("condition")=="date":
            year,month=kwargs.get("para").aplit("/")
            article_list = models.Article.objects.filter(user=current_user,create_time__year=year,create_time__month=month)
    return render(request,"homeSite.html", locals())

#具体文章详细
def contentsArticle(request,username,article_id):
    """点击文章标题,跳转到此页"""
    current_user = models.UserInfo.objects.filter(username=username).first()  # 获取当前用户
    current_blog = current_user.blog#获取当前博客
    if not current_user:
        return render(request, "notFound.html")
    # 查询当前文章
    article_list = models.Article.objects.filter(user=current_user)
    # 查询 当前用户的分类归档
    classfication_list = models.Classfication.objects.all().filter(blog=current_blog).annotate(
        c=Count("article__id")).values_list("title", "c")
    # 查询当前用户的标签归档
    tag_list = models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name",
                                                                                                               "c")
    # 查询当前用户的标签归档
    date_list = models.Article.objects.filter(user=current_user).extra(
        select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(
        Count("id"))
    article_obj = models.Article.objects.filter(id=article_id).first()
    return render(request,"contents_article.html",loca
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>用户注册页面</title>
    <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="/static/css/register.css" rel="stylesheet">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/js/jquery.cookie.js"></script>
</head>
<body>
<div class="container">
    <div class="row col-md-4 col-lg-offset-4">
        <form>
            {% csrf_token %}
            <h2 class="form-signin-heading col-lg-offset-3 text-info">请您注册:</h2>
            <div class="form-group">
                <label for="username">用户名:</label>
                <p>{{ form_obj.username }} {{ form_obj.errors.username.0 }}</p>
            </div>
            <div class="form-group">
                <label for="password">密码:</label>
                <p>{{ form_obj.password }} {{ form_obj.errors.password.0 }}</p>
            </div>
            <div class="form-group">
                <label for="confirm_password">确认密码:</label>
                <p>{{ form_obj.confirm_password }} {{ form_obj.errors.confirm_password.0 }}</p>
            </div>
{#            <div class="form-group">#}
{#                <label for="nickname">昵称:</label>#}
{#                <p>{{ form_obj.nickname }} {{ form_obj.errors.nickname.0 }}</p>#}
{#            </div>#}
{#            <div class="form-group">#}
{#                <label for="tel">电话:</label>#}
{#                <p>{{ form_obj.tel }} {{ form_obj.errors.tel.0 }}</p>#}
{#            </div>#}
            <div class="form-group">
                <label for="email">邮箱:</label>
                <p>{{ form_obj.email }} {{ form_obj.errors.email.0 }}</p>
            </div>
            <div class="form-group avatar">
                 <label for="avatar">头像</label>
                 <img src="/static/img/default.png" alt="" id="avatar_img">
                 <input type="file" id="avatar_file">
            </div >
            <div class="col-lg-offset-5">
                <input type="button" value="提交" class="btn btn-primary" id="avatar_Btn"><span class="error"></span>
            </div>
        </form>
    </div>
</div>
<script>
    $("#avatar_file").change(function () {
        //头像预览
    var ele_file = $(this)[0].files[0];
    var reader = new FileReader();
    reader.readAsDataURL(ele_file);
    reader.onload = function () {
        $("#avatar_img")[0].src = this.result
    }
});

    $("#avatar_Btn").click(function () {
    var formdata = new FormData();
    formdata.append("username", $("#id_username").val());
    formdata.append("password", $("#id_password").val());
    formdata.append("confirm_password", $("#id_confirm_password").val());
{#    formdata.append("nickname", $("#id_nickname").val());#}
{#    formdata.append("tel", $("#id_tel").val());#}
    formdata.append("email", $("#id_email").val());
    formdata.append("avatar_img",$("#id_avatar_img").val());
    $.ajax({
        url: "/register/",
        type: "POST",
        data: formdata,
        contentType: false,
        processData: false,
        headers:{"X-CSRFToken":$.cookie('csrftoken')},

        success: function (data) {
            console.log(data);
            var data = JSON.parse(data);
            if (data.user) {
                location.href = "/login/"
            }


            //全局钩子的错误提示
            else {
                    console.log(data.errorsList);
                     $(".pull-right").html("").parent().removeClass("has-error");//去除第一次错误信息
                       $.each(data.errorsList,function (i,j) {
                       console.log(i,j);
                       $span=$("<span>");
                       $span.addClass("pull-right").css("color","red");//给错误信息添加一个红色
                       $span.html(j[0]);
                       $("#id_"+i).after($span).parent().addClass("has-error");//找到当前错误的input框
                       if (i=="__all__"){
                            $("#id_confirm_password").after($span)
                       }
                   })
                }
            }
        })
    })
</script>
</body>
</html>
View Code

后端代码:

def register(request):
    if request.is_ajax():
        form_obj = forms.RegisterForm(request,request.POST)
        print("---------")
        print(form_obj.is_valid())
        regResponse = {"user": None, "errorsList": None}
        if form_obj.is_valid():
            print("000000")
            username = form_obj.cleaned_data["username"]
            password = form_obj.cleaned_data["password"]
            # nickname = form_obj.cleaned_data["nickname"]
            # tel = form_obj.cleaned_data["tel"]
            email = form_obj.cleaned_data.get("email")
            avatar_img = request.FILES.get("avatar_img")
            user_obj = models.UserInfo.objects.create_user(username=username, password=password,email=email,avatar=avatar_img)
            regResponse["user"] = user_obj.username
        else:
            print("111")
            regResponse["errorsList"] = form_obj.errors
            print(regResponse)
        return HttpResponse(json.dumps(regResponse))
    form_obj= forms.RegisterForm(request)
    return render(request, "register.html", {"form_obj": form_obj})
View Code

css代码:

.container{
    margin-top:50px;
  }

.avatar{
    position: relative;
     60px;
    height: 60px;
}
#avatar_img,#avatar_file{
    position: absolute;
    top:0;
    left: 40px;
     60px;
    height: 60px;
}
#avatar_file{
    opacity: 0;
}
View Code

头像预览JS:

/**
 * Created by pc on 2017-11-21.
 */
//头像预览
$("#avatar_file").change(function () {
    var ele_file = $(this)[0].files[0];
    var reader = new FileReader();
    reader.readAsDataURL(ele_file);
    reader.onload = function () {
        $("#avatar_img")[0].src = this.result
    }
});
$("#avatar_Btn").click(function () {
    var formdata = new FormData();
    formdata.append("username", $("#id_username")).val();
    formdata.append("password", $("#id_password")).val();
    formdata.append("confirm_password", $("#id_confirm_password")).val();
    formdata.append("nickname", $("#id_nickname")).val();
    formdata.append("tel", $("#id_tel")).val();
    formdata.append("email", $("#id_email")).val();
    formdata.append("avatar_img",$("#id_avatar_img")).val();
    $.ajax({
        url: "/register/",
        type: "POST",
        data: formdata,
        contentType: false,
        processData: false,
        header: {"X-CSRFToken": $.cookie('csrftoken')},
        success: function (data) {
            console.log(data);
            var data = JSON.parse(data);
            if (data.user) {
                location.href = "/login/"
            }
            else {
                console.log(data.errorsList);
                $.each(data.errorsList, function (i, j) {
                    console.log(i, j);
                    $span = $("<span>");
                    $span.addClass("pull-right").css("color", "red");
                    $span.html(j[0]);
                    $("#id_" + i).after($span).parent().addClass("has-error");
                    if (i=="__all__") {
                        $("#id_repeat_pwd").after($span)
                    }
                })
            }
        }
    })
});
View Code

settings配置:

AUTH_USER_MODEL = "app01.UserInfo"

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static"),
]
MEDIA_ROOT=os.path.join(BASE_DIR,"app01","media","uploads")
MEDIA_URL="/media/"
View Code

流程:

注册
    1. form组件生成html标签 
        在RegFrom类中继承From这个类,
        利用这个类的方法,生成input标签,在这个类中可设置,标签的属性
        - username
        - password
        - email
    2. 利用后端传来的form在前端生成html标签
        第一次get请求时后返回RegFrom类实例化的对象,
            前端生成- username,- password,- emai,- avatar对应的四个标签
             
            显示图片:
            - 图片和上传文件折叠
                - 作用:上传文件覆盖图片,透明度为零 用户点击图片其实点击上传文件
                -- 把上传文件和图片的父亲标签设置为相对路径 设置长宽,自己
            - 图片预览
                - 用户点击上传文件 上传文件的标签发生变化,会触发change事件
                - 取到用户上传的文件  var ele_file = this.files[0]; 
                - 创建FileReader()对象4
                - 把上传文件的对象的路径写入FileReader()对象,结果为FileReader().result
                - FileReader()加载onload事件,把FileReader().result结果写入到img标签
 
    3. 用户提交数据
          
          用户通过ajav提交数据:
          如果要传二进制的数据必须要用FormData打包
                 在传二进制的时候必须要到的参数
                         -------contentType:false,
                         ------processData:false,
                         -----headers:{"X-CSRFToken":$.cookie('csrftoken')},防止跨站请求     
               --用FormData打包数据
                  var formdata=new FormData();
                      formdata.append("username",$("#id_username").val());
                --通过data把数据传到后台函数
 
                 
    4.验证数据
         post请求走Regfrom函数
             -有错误利用RegForm 的钩子返回错误,----》
                    有错误将错误信息用键值对保存到errorst中
                    没有错误将前端拿到的数据放入cleaned_data中
                注册函数中判断form_obj.is_valid对象是否正确
                    ---正确则获取数据写入数据库---返回一个状态 regResponse["user"]=user_obj.username-----给前端
                    ---错误则获取数据写入数据库---返回一个状太regResponse["errorsList"]=form_obj.errors-----给前端
                  
              
         后台函数利用form_obj.cleaned_data拿到数据
    5、前端用ajax接收处理错误信息
                       $.each(data.errorsList,function (i,j) {
{#                       controls.log(data.errorsList)#}
{#                       console.log(i,j);#}
                             //   i           j
                        ------- username ["用户名不能为空"]
                        ------- password ["密码不能为空"]
                        -------  repeat_pwd ["验证密码不能为空"]
                        -------  email ["邮箱不能为空"]
                       $span=$("<span>");
                       $span.addClass("pull-right").css("color","red");
                        --------{# 添加一个span标签#}
                       $span.html(j[0]);
                        --------{#把log的值j写入span中#}
                       $("#id_"+i).after($span).parent().addClass("has-error")
                       -------#id_"+i找到当前的错误的input框
                       -------parent().addClass("has-error")给错误的input框加一个红色的颜色
                       if (i=="__all__"){
                            $("#id_repeat_pwd").after($span)
                        -------全局钩子的错误信息
                       }
                   })
View Code

  四:博客主页:

页面:

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale">
    <title>{{username}}博客首页</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/homeSite.css">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="MenuBar">
        <div class="heeder">
            <div class="leftbutton">
                    <span class="abuttn">{{current_user.username}}</span>
                    <a href="" class="abuttn">博客园</a>
            </div>
            <div class="key-search">
                <form action="/" method="post">
                    <a href="#" class="i">
                        <span class="ico"></span>
                    </a>
                </form>
            </div>
            <div class="rightbutton">
                <a href="" class="abuttn">首页</a>
                <a href="" class="abuttn">新随笔</a>
                <a href="" class="abuttn">联系</a>
                <a href="" class="abuttn">订阅</a>
                <a href="" class="abuttn">管理</a>
            </div>
        </div>
    </div>
    <div class="container homeSite">
        <div class="row">
            <div class="col-md-3 userinfo">
                <div class="well well-lg ">
                    <h4 class="col-lg-offset-3">个人信息</h4>
                    <p>---------------------------------------------</p>
                    <p><img src="{{current_user.avatar.url}}" alt="" width="100px" height="100px" class="img-circle"></p>
                    <p>昵称:&nbsp&nbsp&nbsp&nbsp<span>{{current_user.username}}</span></p>
                    <p>园龄:</p>
                    <p>粉丝:</p>
                    <p>关注:</p>
                    <a href="">+关注</a>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading"><b>分类归档</b></div>
                    <div class="panel-body">
                        {% for classfication in classfication_list %}
                            <p><a href="/app01/{{ current_user.username }}/classify/{{classfication.0}}">{{classfication.0}}({{classfication.1}})</a></p>
{#                            <p>{{ classfication }}</p>#}
                        {% endfor %}
                    </div>
                    <div class="panel-heading"><b>标签归档</b></div>
                    <div class="panel-body">
                        {% for tag in tag_list %}
                            <p><a href="/app01/{{current_user.username}}/tag/{{tag.0}}">{{tag.0}}({{tag.1}})</a></p>
                        {% endfor %}


                    </div>
                    <div class="panel-heading"><b>日期归档</b></div>
                    <div class="panel-body">
                        {% for date in date_list %}
                            <p><a href="/app01/{{current_user.username}}/date/{{date.0}}">{{date.0}}({{date.1}})</a></p>
                        {% endfor %}
                    </div>
                </div>
            </div>
{#            文章#}
            <div class="col-md-9 articleinfo">
            {% block content %}
                {% for article in article_list %}
                        <div class="well well-lg ">
                            <div class="col-lg-offset-9">
                                <h4>{{article.create_time|date:"Y年m月d日"}}</h4>
                            </div>
                            <p>---------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p>
                            <h3><a href="/app01/{{current_user.username}}/article/{{article.id}}"><b>{{article.title}}</b></a></h3>
                            <hr>
                            <div class="summary">
                                <p>{{article.summary}}<span><a href="">阅读全文</a></span></p>
                            </div>
                            <hr>
                            <div class="col-lg-offset-5 info">
                                发表于:<span>{{article.create_time|date:"Y-m-d  H:i"}}</span>
                                &nbsp&nbsp评论:<span>({{article.comment_count}})</span>
                                &nbsp&nbsp点赞:<span>({{article.poll_count}})</span>
                                &nbsp&nbsp阅读:<span>({{article.read_count}})</span>
                                &nbsp&nbsp&nbsp&nbsp<span><a href="">编辑</a></span>
                            </div>
                        </div>
                    {% endfor %}
            {% endblock %}

            </div>
        </div>
    </div>
</body>
</html>
View Code

后端代码:

def index(request,*args,**kwargs):
    if kwargs:
        article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找点击的类的文章
    else:
        article_list = models.Article.objects.all()
    site_list = models.SiteCategory.objects.all()
    return render(request, "index.html",{"article_list":article_list,"site_list":site_list})
View Code

            1:在url中写主页路由
                url(r'^index', views.index)

url(r'^index', views.index),#主页                

            2:创建视图函数,从数据库取出数据,返回到前端。
                -------找到文章表,取出文章对象,返回。
                
                -------找到网站分类表,取出分类对象,返回。

def index(request,*args,**kwargs):
    if kwargs:
        article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找点击的类的文章
    else:
        article_list = models.Article.objects.all()
    site_list = models.SiteCategory.objects.all()
    return render(request, "index.html",{"article_list":article_list,"site_list":site_list})

               
            3:返回到主页html进行渲染:
            
                1:-----拿到文章对象用for标签循环,{{.文章内容}}进行渲染。
                

<div class="col-md-6">
            <div class=" article_list">
                {% for article in article_list %}
                    <div><a href="">{{article.title}}</a></div>
                    <div class="row">
                        <div class="avatar col-md-2">
                            <a href="{% url 'aaa'  article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a>
                        </div>
                        <div class="summary col-md-10" >
                            <p>{{article.summary}}</p>
                        </div>
                    </div>
                    <div class="article_info row">
                        &nbsp&nbsp<a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a> &nbsp&nbsp发布与:{{article.create_time|date:"Y-m-d H:i"}}
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-comment"></span>评论({{article.comment_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{article.poll_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-share-alt"></span>阅读({{article.read_count}})</a>
                    </div>
                    <hr>
                {% endfor %}
            </div>


                2:-----拿到分类对象用for标签循环,{{.网站分类,父}}进行渲染。
                
                3:-----拿到网站分类对象,{{.(反向查询,表名_set).网站分类,子}}进行渲染。
               

<div class="row col-md-3">
            <div class="panel panel-primary">
                <div class="panel-body">
                    网站分类
                </div>
                <div class="panel-footer">
                    {% for site in site_list %}
                        <div class="panel panel-primary">
                            <div class="panel-heading cate_title">{{site.name}}</div>
                            <div class="panel-body hides">
                                {% for sitearticlecategory in site.sitearticlecategory_set.all %}
                                    <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p>
                                {% endfor %}
                            </div>
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
View Code


              4:JQ做动态折叠效果,鼠标悬浮展开,鼠标移开折叠。
            
                    1:-----选择器找到网站分类,给他绑定一个(悬浮)事件,当触发这个事件(鼠标悬浮),执行function,$(this)找到选择器对象,执行展开事件。
                
                    2:-----选择器找到网站分类的父级,给他绑定一个(悬浮)执行function,$(this)找到选择器对象,执行折叠事件事件。       

$(".cate_title").mouseover(function () {
                            $(this).next().slideDown(300)
                        }).parent().mouseleave(function () {
                             $(this).children(".panel-footer").slideUp(300)
                         });


            5:点击网站分类,子分类,查找到这个分类下的所有文章。
            
                -------分类渲染在<a>标签中,给他一个url,鼠标点击,------走urls进行路由匹配--------找url的视图函数--------进行查找
                
                        a标签:---------/site/{{网站分类,name}}
                        
                        url:------------以site开头,有名分组(接收点击的分类),按关键字传参.*匹配所有,返回一个键值对,返回到视图函数。
                                        url(r'^site/(?P<site_article_category>.*)/$', views.index),
                                        

url(r'^site/(?P<site_article_category>.*)/$', views.index),


                        视图函数--------**kwargs接收键值对,判断kwargs,判断正确,进行网站查询,否则查询所有文章。
                        
                        查询------------找到文章表,过滤(反向查询按字段)出文章的网站分类,子分类 =kwargs传过来的分类,返回到前端进行渲染。
                                    article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))
                                   

def index(request,*args,**kwargs):
    if kwargs:
        article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))#查找点击的类的文
View Code

首页:

<!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">
    <title>博客系统首页</title>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <style>
        .hides{ display: none; }
    </style>
</head>
<body>
<nav class="navbar navbar-inverse primary">
    <div class="container">
            <a class="navbar-brand" href="#">博客园</a>
        <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse">
            <ul class="nav navbar-nav navbar-right">
{#                {% if request.user.is_authenticated %}#}
                    <li><a href=""><span class="glyphicon glyphicon-user">{{request.user.uaername}}</span></a></li>
                    <li><a href="/#/">注销</a></li>
                    <li><a href="/#/">修改密码</a></li>
{#                {% else %}#}
                    <li><a href="/#/">登录</a></li>
                    <li><a href="/#/">注册</a></li>
{#                {% endif %}#}
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="搜索">
            </form>
        </div>
    </div>
</nav>
<div class="container">
        <div class="row col-md-3">
            <div class="panel panel-primary">
                <div class="panel-body">
                    网站分类
                </div>
                <div class="panel-footer">
                    {% for site in site_list %}
                        <div class="panel panel-primary">
                            <div class="panel-heading cate_title">{{site.name}}</div>
                            <div class="panel-body hides">
                                {% for sitearticlecategory in site.sitearticlecategory_set.all %}
                                    <p><a href="/site/{{sitearticlecategory.name}}">{{sitearticlecategory.name}}</a></p>
                                {% endfor %}
                            </div>
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
        <div class="col-md-6">
            <div class=" article_list">
                {% for article in article_list %}
                    <div><a href="">{{article.title}}</a></div>
                    <div class="row">
                        <div class="avatar col-md-2">
                            <a href="{% url 'aaa'  article.user.username %}"><img src="{{article.user.avatar.url}}" alt="" width="80px" height="80px"></a>
                        </div>
                        <div class="summary col-md-10" >
                            <p>{{article.summary}}</p>
                        </div>
                    </div>
                    <div class="article_info row">
                        &nbsp&nbsp<a href="/app01/{{ article.user.username }}"><b>{{article.user.username}}</b></a> &nbsp&nbsp发布与:{{article.create_time|date:"Y-m-d H:i"}}
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-comment"></span>评论({{article.comment_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{article.poll_count}})</a>
                        &nbsp&nbsp<a href=""><span class="glyphicon glyphicon-share-alt"></span>阅读({{article.read_count}})</a>
                    </div>
                    <hr>
                {% endfor %}
            </div>
        </div>
        <div class="col-md-3">
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
            <div class="panel panel-default">
                <div class="panel-body">
                    Panel content
                </div>
                <div class="panel-footer">Panel footer</div>
            </div>
        </div>
    </div>
<script>
     $(".cate_title").mouseover(function () {
        $(this).next().slideDown(300)
    }).parent().mouseleave(function () {
         $(this).children(".panel-footer").slideUp(300)
     });
{#    $(".cate_title").mouseenter(function () {#}
{#        $(this).next().slideDown(300)#}
{#    });#}
{#    $(".panel-footer").mouseleave(function () {#}
{#        $(this).next().slideUp(300)#}
{#    });#}
</script>
</body>
</html>
View Code

四:个人博客主页:  

页面:

 

 前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale">
    <title>{{username}}博客首页</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/homeSite.css">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="MenuBar">
        <div class="heeder">
            <div class="leftbutton">
                    <span class="abuttn">{{current_user.username}}</span>
                    <a href="" class="abuttn">博客园</a>
            </div>
            <div class="key-search">
                <form action="/" method="post">
                    <a href="#" class="i">
                        <span class="ico"></span>
                    </a>
                </form>
            </div>
            <div class="rightbutton">
                <a href="" class="abuttn">首页</a>
                <a href="" class="abuttn">新随笔</a>
                <a href="" class="abuttn">联系</a>
                <a href="" class="abuttn">订阅</a>
                <a href="" class="abuttn">管理</a>
            </div>
        </div>
    </div>
    <div class="container homeSite">
        <div class="row">
            <div class="col-md-3 userinfo">
                <div class="well well-lg ">
                    <h4 class="col-lg-offset-3">个人信息</h4>
                    <p>---------------------------------------------</p>
                    <p><img src="{{current_user.avatar.url}}" alt="" width="100px" height="100px" class="img-circle"></p>
                    <p>昵称:&nbsp&nbsp&nbsp&nbsp<span>{{current_user.username}}</span></p>
                    <p>园龄:</p>
                    <p>粉丝:</p>
                    <p>关注:</p>
                    <a href="">+关注</a>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading"><b>分类归档</b></div>
                    <div class="panel-body">
                        {% for classfication in classfication_list %}
                            <p><a href="/app01/{{ current_user.username }}/classify/{{classfication.0}}">{{classfication.0}}({{classfication.1}})</a></p>
{#                            <p>{{ classfication }}</p>#}
                        {% endfor %}
                    </div>
                    <div class="panel-heading"><b>标签归档</b></div>
                    <div class="panel-body">
                        {% for tag in tag_list %}
                            <p><a href="/app01/{{current_user.username}}/tag/{{tag.0}}">{{tag.0}}({{tag.1}})</a></p>
                        {% endfor %}


                    </div>
                    <div class="panel-heading"><b>日期归档</b></div>
                    <div class="panel-body">
                        {% for date in date_list %}
                            <p><a href="/app01/{{current_user.username}}/date/{{date.0}}">{{date.0}}({{date.1}})</a></p>
                        {% endfor %}
                    </div>
                </div>
            </div>
{#            文章#}
            <div class="col-md-9 articleinfo">
            {% block content %}
                {% for article in article_list %}
                        <div class="well well-lg ">
                            <div class="col-lg-offset-9">
                                <h4>{{article.create_time|date:"Y年m月d日"}}</h4>
                            </div>
                            <p>---------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p>
                            <h3><a href="/app01/{{current_user.username}}/article/{{article.id}}"><b>{{article.title}}</b></a></h3>
                            <hr>
                            <div class="summary">
                                <p>{{article.summary}}<span><a href="">阅读全文</a></span></p>
                            </div>
                            <hr>
                            <div class="col-lg-offset-5 info">
                                发表于:<span>{{article.create_time|date:"Y-m-d  H:i"}}</span>
                                &nbsp&nbsp评论:<span>({{article.comment_count}})</span>
                                &nbsp&nbsp点赞:<span>({{article.poll_count}})</span>
                                &nbsp&nbsp阅读:<span>({{article.read_count}})</span>
                                &nbsp&nbsp&nbsp&nbsp<span><a href="">编辑</a></span>
                            </div>
                        </div>
                    {% endfor %}
            {% endblock %}

            </div>
        </div>
    </div>
</body>
</html>
View Code

后端代码:

#个人主页
def homeSite(request,username,**kwargs):
    # print(kwargs)
    # print(username)
    """点击文章用户名或,头像跳转的此页"""
    current_user = models.UserInfo.objects.filter(username=username).first()#获取当前用户
    # current_blog = current_user.blog#获取当前博客
    if not current_user:
        return render(request,"notFound.html")
    current_blog = current_user.blog  # 获取当前博客
    #查询当前文章
    article_list=models.Article.objects.filter(user=current_user)
    #查询 当前用户的分类归档
    classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c")
    #查询当前用户的标签归档
    tag_list=models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name","c")
    #查询当前用户的标签归档
    date_list = models.Article.objects.filter(user=current_user).extra(
        select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(Count("id"))
    if kwargs:
        if kwargs.get("condition")=="classify":
            print(kwargs.get("condition"))
            article_list = models.Article.objects.filter(user=current_user,classify__title=kwargs.get("para"))
            # article_list = models.Article.objects.filter(user=current_user, category__title=kwargs.get("para"))
        elif kwargs.get("condition")=="tag":
            article_list = models.Article.objects.filter(user=current_user,tags__name=kwargs.get("para"))
        elif kwargs.get("condition")=="date":
            year,month=kwargs.get("para").aplit("/")
            article_list = models.Article.objects.filter(user=current_user,create_time__year=year,create_time__month=month)
    return render(request,"homeSite.html", locals())
View Code

url路由:

from django.conf.urls import include, url
from django.contrib import admin
from django.views.static import serve
from Blog_long import settings
from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^login', views.login),  #登录
    url(r'^get_authCode_img/', views.get_authCode_img), #验证码
    url(r'^log_out',views.log_out),  #注销
    url(r'^register', views.register),  # 注册
    url(r'^index', views.index),#主页
    # media 配置
    url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
    #首页点击分类查询到属于这个类的文章
    url(r'^site/(?P<site_article_category>.*)/$', views.index),
    #个人站点首页,路由分发
    url(r'^app01/', include('app01.urls')),

]
View Code

分发路由:

from django.conf.urls import include, url
from app01 import views
urlpatterns = [
    url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
    url(r'^(?P<username>.*)/article/(?P<article_id>d+)', views.contentsArticle),
    url(r'^(?P<username>.*)',views.homeSite,name="aaa"),
]
View Code   

            1:点击首页中的--头像--和--发布人--,跳转到所对应的个人个人博客首页中。
            
                --头像,发布人都渲染在<a>标签中。
                
                --路由分发:以...开头,就映入到某个应用下的urls中进行匹配。
                
                    url(r'^app01/', include('app01.urls')),

url(r'^app01/', include('app01.urls')),

                   
                --给a标签一个url,点击走----url进行路由匹配,匹配成功走----所对应的视图函数。
                

url(r'^(?P<username>.*)', views.homeSite,name="aaa"),

                    <a>标签:----------点击发布人-----发送一个url:以app01/开头,引入到app01下的urls中,当前点击的用户名。进行路由匹配。
                                        "/app01/{{ article.user.username }}"
                                        0
                                ------点击头像-------通过别名,反向解析------找到别名是...的url,替换
                                ------视图函数中也可以用反向解析,原理相同,导入removes,传参数要用args。
                                        {% url 'aaa'  article.user.username %}
                                        
                    urls:-------------有名分组,按关键字传参,接收当前点击的用户名,返回到所对应的视图函数中,加别名,用于反向解析。
                                        url(r'^(?P<username>.*)', views.homeSite,name="aaa"),
                    
                    视图函数:--------接收kwargs键值对,和当前用户名-----查询当前用户名是点击的用户名,的用户信息对象,判断用户信息,如果不是返回错误信息。
                                    --返回个人博客页面,返回用户信息。
                    
                    查询:------------通过个人用户信息查询到个人个人站点(个人博客)
                   

def homeSite(request,username,**kwargs):
    current_user = models.UserInfo.objects.filter(username=username).first()#获取当前用户
    current_blog = current_user.blog
    print(current_blog)#获取当前博客
    if not current_user:
        return render(request,"notFound.html")
    #查询当前文章
    article_list=models.Article.objects.filter(user=current_user)
    #查询 当前用户的分类归档
    classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c")
    #查询当前用户的标签归档
    tag_list=models.Tag.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("name","c")
    #查询当前用户的标签归档
    date_list = models.Article.objects.filter(user=current_user).extra(
        select={"filter_create_date": "strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(
        Count("id"))
    if kwargs:
        if kwargs.get("condition")=="classify":
            article_list = models.Article.objects.filter(user=username,classify__title=kwargs.get("para"))
        elif kwargs.get("condition")=="tag":
            article_list = models.Article.objects.filter(user=username,tags__name=kwargs.get("para"))
        elif kwargs.get("condition")=="date":
            year,month=kwargs.get("para").aplit("/")
            article_list = models.Article.objects.filter(user=username,create_time__year=year,create_time__month=month)
    return render(request,"homeSite.html", locals())
View Code

            2:查询当前用户的文章对象-----找到文章表,过滤出user=当前用户的文章,返回到页面进行渲染。
            
            3:拿到用户信息,---------返回到页面渲染个人信息。
                
            4:分类归档
            
                1:-----查询当前用户,个人站点的分类对象-----分组查询到(查询当前用户,个人站点的分类对象)的数目
                        classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c")
                        
                2:-----返回到页面进行渲染。
                        ----for循环分类对象,是一个元组,.0拿到分类,.1拿到分类数量。进行渲染。
                        
                3:-----点击当前分类------查询到当前分类的文章进行渲染。
                        ----<a>标签-------当前分类渲染在a标签中,点击,发送一个url-----/app01/{{ current_user.username }}/classify/{{classfication.0}}----走urls。
                        ----urls:---------以app01开头,有名分组(当前用户),有名分组(归档方式),有名分组(具体分类)-----返回当前用户名,键值对到---视图函数----走视图函数。
                            url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
                        ----视图函数------拿到当前用户名,键值对。
                            ----判断kwargs中有名分组(分类)等不等于归档分类 ----if kwargs.get("condition")=="classify":----判断正确进行查询
                        ----查询,-------查询当前用户个人站点所点击分类的文章。-----返回到页面进行渲染。
                            ----article_list = models.Article.objects.filter(user=username,classify__title=kwargs.get("para"))
            5:标签归档-----点击当前标签------查询到当前标签的文章进行渲染。
                        ----<a>标签-------当前分类渲染在a标签中,点击,发送一个url-----/app01/{{ current_user.username }}/tag/{{classfication.0}}----走urls。
                        ----urls:---------以app01开头,有名分组(当前用户),有名分组(归档方式),有名分组(具体标签)-----返回当前用户名,键值对到---视图函数----走视图函数。
                            url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
                        ----视图函数------拿到当前用户名,键值对。
                            ----判断kwargs中有名分组(分类)等不等于归档标签 ----if kwargs.get("condition")=="tag":----判断正确进行查询
                        ----查询,-------查询当前用户个人站点所点击标签的文章。-----返回到页面进行渲染。
                            ----article_list = models.Article.objects.filter(user=username,tags__name=kwargs.get("para"))
            
            6:日期归档-----点击当前日期------查询到当前日期的文章进行渲染。
                        ----<a>标签-------当前分类渲染在a标签中,点击,发送一个url-----/app01/{{ current_user.username }}/data/{{classfication.0}}----走urls。
                        ----urls:---------以app01开头,有名分组(当前用户),有名分组(归档方式),有名分组(具体日期)-----返回当前用户名,键值对到---视图函数----走视图函数。
                            url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
                        ----视图函数------拿到当前用户名,键值对。
                            ----判断kwargs中有名分组(日期)等不等于归档分类 ----if kwargs.get("condition")=="data":----判断正确进行查询
                        ----查询,-------查询当前用户个人站点所点击标签的文章。-----返回到页面进行渲染。
                            ----获取时间----year,month=kwargs.get("para").aplit("/")
                            ----article_list = models.Article.objects.filter(user=username,create_time__year=year,create_time__month=month)
            
 个人博客首页:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale">
    <title>{{username}}博客首页</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/homeSite.css">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="MenuBar">
        <div class="heeder">
            <div class="leftbutton">
                    <span class="abuttn">{{current_user.username}}</span>
                    <a href="" class="abuttn">博客园</a>
            </div>
            <div class="key-search">
                <form action="/" method="post">
                    <a href="#" class="i">
                        <span class="ico"></span>
                    </a>
                </form>
            </div>
            <div class="rightbutton">
                <a href="" class="abuttn">首页</a>
                <a href="" class="abuttn">新随笔</a>
                <a href="" class="abuttn">联系</a>
                <a href="" class="abuttn">订阅</a>
                <a href="" class="abuttn">管理</a>
            </div>
        </div>
    </div>
    <div class="container homeSite">
        <div class="row">
            <div class="col-md-3 userinfo">
                <div class="well well-lg ">
                    <h4 class="col-lg-offset-3">个人信息</h4>
                    <p>---------------------------------------------</p>
                    <p><img src="{{current_user.avatar.url}}" alt="" width="100px" height="100px" class="img-circle"></p>
                    <p>昵称:&nbsp&nbsp&nbsp&nbsp<span>{{current_user.nickname}}</span></p>
                    <p>园龄:</p>
                    <p>粉丝:</p>
                    <p>关注:</p>
                    <a href="">+关注</a>
                </div>
                <div class="panel panel-primary">
                    <div class="panel-heading"><b>分类归档</b></div>
                    <div class="panel-body">
                        {% for classfication in classfication_list %}
                            <p><a href="/app01/{{ current_user.username }}/classify/{{classfication.0}}">{{classfication.0}}({{classfication.1}})</a></p>
{#                            <p>{{ classfication }}</p>#}
                        {% endfor %}
                    </div>
                    <div class="panel-heading"><b>标签归档</b></div>
                    <div class="panel-body">
                        {% for tag in tag_list %}
                            <p><a href="/app01/{{current_user.username}}/tag/{{tag.0}}">{{tag.0}}({{tag.1}})</a></p>

                        {% endfor %}


                    </div>
                    <div class="panel-heading"><b>日期归档</b></div>
                    <div class="panel-body">
                        {% for date in date_list %}
                            <p><a href="/app01/{{current_user.username}}/date/{{date.0}}">{{date.0}}({{date.1}})</a></p>
                        {% endfor %}
                    </div>
                </div>
            </div>
{#            文章#}
            <div class="col-md-9 articleinfo">
                {% for article in article_list %}
                    <div class="well well-lg ">
                        <div class="col-lg-offset-9">
                            <h4>{{article.create_time|date:"Y年m月d日"}}</h4>
                        </div>
                        <p>---------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p>
                        <h3><a href=""><b>{{article.title}}</b></a></h3>
                        <hr>
                        <div class="summary">
                            <p>{{article.summary}}<span><a href="">阅读全文</a></span></p>
                        </div>
                        <hr>
                        <div class="col-lg-offset-5 info">
                            发表于:<span>{{article.create_time|date:"Y-m-d  H:i"}}</span>
                            &nbsp&nbsp评论:<span>({{article.comment_count}})</span>
                            &nbsp&nbsp点赞:<span>({{article.poll_count}})</span>
                            &nbsp&nbsp阅读:<span>({{article.read_count}})</span>
                            &nbsp&nbsp&nbsp&nbsp<span><a href="">编辑</a></span>
                        </div>
                    </div>
                {% endfor %}
            </div>
        </div>
    </div>
</body>
</html>
View Code

博客首页-----和-----个人博客首页--流程:

1:在url中写主页路由
                url(r'^index', views.index)
                
            2:创建视图函数,从数据库取出数据,返回到前端。
            
                -------找到文章表,取出文章对象,返回。
                
                -------找到网站分类表,取出分类对象,返回。
                
            3:返回到主页html进行渲染:
            
                1:-----拿到文章对象用for标签循环,{{.文章内容}}进行渲染。
                
                2:-----拿到分类对象用for标签循环,{{.网站分类,父}}进行渲染。
                
                3:-----拿到网站分类对象,{{.(反向查询,表名_set).网站分类,子}}进行渲染。
                
            4:JQ做动态折叠效果,鼠标悬浮展开,鼠标移开折叠。
            
                1:-----选择器找到网站分类,给他绑定一个(悬浮)事件,当触发这个事件(鼠标悬浮),执行function,$(this)找到选择器对象,执行展开事件。
                
                2:-----选择器找到网站分类的父级,给他绑定一个(悬浮)执行function,$(this)找到选择器对象,执行折叠事件事件。        
                         $(".cate_title").mouseover(function () {
                            $(this).next().slideDown(300)
                        }).parent().mouseleave(function () {
                             $(this).children(".panel-footer").slideUp(300)
                         });
                         
            5:点击网站分类,子分类,查找到这个分类下的所有文章。
            
                -------分类渲染在<a>标签中,给他一个url,鼠标点击,------走urls进行路由匹配--------找url的视图函数--------进行查找
                
                        a标签:---------/site/{{网站分类,name}}
                        
                        url:------------以site开头,有名分组(接收点击的分类),按关键字传参.*匹配所有,返回一个键值对,返回到视图函数。 
                                        url(r'^site/(?P<site_article_category>.*)/$', views.index),
                                        
                        视图函数--------**kwargs接收键值对,判断kwargs,判断正确,进行网站查询,否则查询所有文章。
                        
                        查询------------找到文章表,过滤(反向查询按字段)出文章的网站分类,子分类 =kwargs传过来的分类,返回到前端进行渲染。
                                    article_list = models.Article.objects.filter(site_article_category__name=kwargs.get("site_article_category"))
                                    
    四:个人博客主页:
    
            1:点击首页中的--头像--和--发布人--,跳转到所对应的个人个人博客首页中。
            
                --头像,发布人都渲染在<a>标签中。
                
                --路由分发:以...开头,就映入到某个应用下的urls中进行匹配。
                
                    url(r'^app01/', include('app01.urls')),
                    
                --给a标签一个url,点击走----url进行路由匹配,匹配成功走----所对应的视图函数。
                
                    <a>标签:----------点击发布人-----发送一个url:以app01/开头,引入到app01下的urls中,当前点击的用户名。进行路由匹配。
                                        "/app01/{{ article.user.username }}"
                                        0
                                ------点击头像-------通过别名,反向解析------找到别名是...的url,替换
                                ------视图函数中也可以用反向解析,原理相同,导入removes,传参数要用args。
                                        {% url 'aaa'  article.user.username %}
                                        
                    urls:-------------有名分组,按关键字传参,接收当前点击的用户名,返回到所对应的视图函数中,加别名,用于反向解析。
                                        url(r'^(?P<username>.*)', views.homeSite,name="aaa"),
                    
                    视图函数:--------接收kwargs键值对,和当前用户名-----查询当前用户名是点击的用户名,的用户信息对象,判断用户信息,如果不是返回错误信息。
                                    --返回个人博客页面,返回用户信息。
                    
                    查询:------------通过个人用户信息查询到个人个人站点(个人博客)
                    
            2:查询当前用户的文章对象-----找到文章表,过滤出user=当前用户的文章,返回到页面进行渲染。
            
            3:拿到用户信息,---------返回到页面渲染个人信息。
                
            4:分类归档
            
                1:-----查询当前用户,个人站点的分类对象-----分组查询到(查询当前用户,个人站点的分类对象)的数目
                        classfication_list=models.Classfication.objects.all().filter(blog=current_blog).annotate(c=Count("article__id")).values_list("title","c")
                        
                2:-----返回到页面进行渲染。
                        ----for循环分类对象,是一个元组,.0拿到分类,.1拿到分类数量。进行渲染。
                        
                3:-----点击当前分类------查询到当前分类的文章进行渲染。
                        ----<a>标签-------当前分类渲染在a标签中,点击,发送一个url-----/app01/{{ current_user.username }}/classify/{{classfication.0}}----走urls。
                        ----urls:---------以app01开头,有名分组(当前用户),有名分组(归档方式),有名分组(具体分类)-----返回当前用户名,键值对到---视图函数----走视图函数。
                            url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
                        ----视图函数------拿到当前用户名,键值对。
                            ----判断kwargs中有名分组(分类)等不等于归档分类 ----if kwargs.get("condition")=="classify":----判断正确进行查询
                        ----查询,-------查询当前用户个人站点所点击分类的文章。-----返回到页面进行渲染。
                            ----article_list = models.Article.objects.filter(user=username,classify__title=kwargs.get("para"))
            5:标签归档-----点击当前标签------查询到当前标签的文章进行渲染。
                        ----<a>标签-------当前分类渲染在a标签中,点击,发送一个url-----/app01/{{ current_user.username }}/tag/{{classfication.0}}----走urls。
                        ----urls:---------以app01开头,有名分组(当前用户),有名分组(归档方式),有名分组(具体标签)-----返回当前用户名,键值对到---视图函数----走视图函数。
                            url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
                        ----视图函数------拿到当前用户名,键值对。
                            ----判断kwargs中有名分组(分类)等不等于归档标签 ----if kwargs.get("condition")=="tag":----判断正确进行查询
                        ----查询,-------查询当前用户个人站点所点击标签的文章。-----返回到页面进行渲染。
                            ----article_list = models.Article.objects.filter(user=username,tags__name=kwargs.get("para"))
            
            6:日期归档-----点击当前日期------查询到当前日期的文章进行渲染。
                        ----<a>标签-------当前分类渲染在a标签中,点击,发送一个url-----/app01/{{ current_user.username }}/data/{{classfication.0}}----走urls。
                        ----urls:---------以app01开头,有名分组(当前用户),有名分组(归档方式),有名分组(具体日期)-----返回当前用户名,键值对到---视图函数----走视图函数。
                            url(r'^(?P<username>.*)/(?P<condition>classify|tag|date)/(?P<para>.*)', views.homeSite),
                        ----视图函数------拿到当前用户名,键值对。
                            ----判断kwargs中有名分组(日期)等不等于归档分类 ----if kwargs.get("condition")=="data":----判断正确进行查询
                        ----查询,-------查询当前用户个人站点所点击标签的文章。-----返回到页面进行渲染。
                            ----获取时间----year,month=kwargs.get("para").aplit("/")
                            ----article_list = models.Article.objects.filter(user=username,create_time__year=year,create_time__month=month)
View Code

 五:文章详细(重点:点赞,评论)

   解决bug:登录点赞,不登录返回登录页面。

六:后台管理

   1:后台页面设计:-----------------给(管理)a标签一个路由:/app01/manage/

    url:

url(r'^manage/$',views.manage),

  前端代码:

<!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">
    <title>后台管理</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <script src="/static/kindeditor/kindeditor-all-min.js"></script>
</head>
<body>
<div class="" style="background-color: #2459a2;height: 50px; 100%">
    <div class="container">
        <a class="navbar-brand" href="#"><b>{{ user.username }}博客园后台管理</b></a>
        <div id="bs-example-navbar-collapse-9" class="collapse navbar-collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><a href="/logout/">注销</a></li>
                <li><a href="/setpassword/">修改密码</a></li>
            </ul>
        </div>
    </div>
</div>
<p></p>
<div class="row col-md-2">
    <div class="panel panel-primary ">
        <div class="panel-heading"><b>操作</b></div>
        <div class="panel-body">
            <div class="panel-footer"><a href="/app01/manage/"><< 文章管理 >></a></div>
            <div class="panel-footer"><a href=""><< 分类管理 >></a></div>
            <div class="panel-footer"><a href=""><< 标签管理 >></a></div>
            <div class="panel-footer"><h2>{{ user }}!</h2></div>
        </div>
    </div>
</div>
<div class="col-md-9 sidebar alert-warning col-lg-offset-1">
    {% block manage %}
        <div class="bs-example" data-example-id="contextual-table">
            <table class="table">
                <thead>
                <tr>
                    <th>标题</th>
                    <th>评论数</th>
                    <th>点赞数</th>
                    <th>操作</th>
                    <th>操作</th>
                    <th><a href="/app01/manage/add_article/">
                        <button class="btn btn-primary">添加</button>
                    </a></th>
                </tr>
                </thead>
                <tbody>
                {% for article in article_list %}
                    <tr>
                        <td>{{ article.title }}</td>
                        <td>{{ article.comment_count }}</td>
                        <td>{{ article.poll_count }}</td>
                        <td><a href="">
                            <button class="btn btn-primary">编辑</button>
                        </a></td>
                        <td><a href="">
                            <button class="btn btn-danger">删除</button>
                        </a></td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    {% endblock %}
</div>
</body>
</html>
View Code

  后端代码:

def manage(request):
    if not request.user.is_authenticated():
        return redirect("/login/")
    article_list = models.Article.objects.filter(user=request.user).all()
    print(article_list)
    return render(request,"manage.html",{"article_list":article_list})
View Code

  2:文章管理:

     ----添加文章:

           url:

url(r'^manage/add_article/$',views.add_article),

           前端代码:

{% extends "manage.html"%}
{% block manage %}
    {% csrf_token %}
    <h4>添加文章:</h4>
    <form action="/app01/manage/add_article/" method="post" novalidate>
    {% csrf_token %}
        <div>
            <label for="title">标题:</label>
            <p>{{ article_form.title }} {{ article_form.errors.title.0 }}</p>
        </div>
        <div>
            <label for="content">内容:</label>
            <p>{{ article_form.content }} {{ article_form.errors.content.0 }}</p>
        </div>
        <p><button class="btn-sm btn-primary">提交</button></p>
    </form>
     <script>
            KindEditor.ready(function (K) {
                window.editor = K.create('#id_content', {
{#                    宽#}
                     "1100px",
{#                    高#}
                    height: "450px",
{#                    是否可以拖动#}
                    resizeType: 0,
{#                    指定上传文件的终端,对应在url,视图函数#}
                    uploadJson: "/uploadFile/",

                    extraFileUploadParams: {
                        csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
                    }
                });
            })
     </script>
{% endblock %}
View Code

          添加文章Form组件:

#文章From组件
class ArticleFrom(forms.Form):
    title = forms.CharField(
        required=True,
        max_length=20,
        error_messages={
            "required":"不能为空",
        },widget=widgets.TextInput(attrs={ 'class': 'form-control'}))
    content = forms.CharField(
        required=True,
        error_messages={
            "required": "不能为空",
    },widget=widgets.Textarea(attrs={ 'class': 'form-control'}))
    def clean_content(self):
        # 拿到文章内容
        html_str=self.cleaned_data.get("content")
        #调用函数
        clean_content=xss_plugin.filter_xss(html_str)
        self.cleaned_data["content"]=clean_content
        return self.cleaned_data.get("content")
View Code

          后端代码:

def add_article(request):
    if request.method=="POST":
        article_form = ArticleFrom(request.POST)
        if article_form.is_valid():
            title = article_form.cleaned_data.get("title")
            content = article_form.cleaned_data.get("content")
            article_obj = models.Article.objects.create(title=title,summary=content[0:30],create_time=datetime.datetime.now(),user=request.user)
            models.Article_detail.objects.create(content=content,article=article_obj)
            return HttpResponse("添加成功")
        else:
            pass
    article_form=ArticleFrom
    return render(request,"add_article.html",{"article_form":article_form})
View Code

  3:添加kindeditor编辑器

    下载:http://kindeditor.net/docs/option.html

编辑器(kindeditor)--------------------------------------http://kindeditor.net/docs/option.html 

     导入

    

    引用:

    绑定编辑器:

    

    代码:

View Code

    url:

#编辑器上传文件
    url(r'^uploadFile/$', views.uploadFile),

     视图函数:-----------------文件预览

    

  

    

View Code

    4:XSS攻击----用(beautifulsoup4模块实现)

    (beautifulsoup4)----------------------------------------http://www.cnblogs.com/yuanchenqi/articles/7617280.html

       ----下载:

        

      ----xss组件:

        

        代码:

from bs4 import BeautifulSoup
def filter_xss(html_str):
    valid_tag_list = ["p", "div", "a", "img", "html", "body", "br", "strong", "b"]
    valid_dict = {"p": ["id", "class"], "div": ["id", "class"]}
    soup = BeautifulSoup(html_str, "html.parser")  # soup  ----->  document
    ######### 改成dict
    for ele in soup.find_all():
        # 过滤非法标签
        if ele.name not in valid_dict:
            ele.decompose()
        # 过滤非法属性
        else:
            attrs = ele.attrs  # p {"id":12,"class":"d1","egon":"dog"}
            l = []
            for k in attrs:
                if k not in valid_dict[ele.name]:
                    l.append(k)
            for i in l:
                del attrs[i]
    print(soup)
    return soup.decode()
View Code

      -----from组件 过滤,钩子

        代码:

from django import forms
from django.forms import fields
from django.forms import widgets,ValidationError
from app01 import models
from app01.plugins import xss_plugin
from django.core.validators import RegexValidator
#注册Form组件
class RegisterForm(forms.Form):
    """注册Form组件"""
    username = forms.CharField(
        required=True,
        min_length=3,
        max_length=8,
        error_messages={
            'required': '用户不能为空',
            'min_length': '用户长度不能小于3',
            'max_length': '用户长度不能大于8',
        },widget=widgets.TextInput(attrs={'placeholder': '用户名:', 'class': 'form-control'}))
    password = fields.CharField(
        required=True,
        min_length=3,
        max_length=8,
        error_messages={
            'required': '密码不能为空',
            'min_length': '密码长度不能小于3',
            'max_length': '密码长度不能大于8',
            # 'invalid': '密码格式错误',
        },
        # validators=[RegexValidator('d+', '只能是数字')],
        widget=widgets.PasswordInput(attrs={'placeholder': '密码:', 'class': 'form-control'}))
    confirm_password = fields.CharField(
        required=True,
        min_length=3,
        max_length=8,
        error_messages={
            'required': '确认密码不能为空',
            'min_length': '确认密码长度不能小于3',
            'max_length': '确认密码长度不能大于8',
        },
        widget=widgets.PasswordInput(attrs={'placeholder': '确认密码:', 'class': 'form-control'}))

    email = fields.EmailField(
        required=True,
        error_messages={
            'required':'邮箱不能为空',
            'invalid':'邮箱格式错误'},
        widget=widgets.EmailInput(attrs={'placeholder':'邮箱:','class':'form-control'}))


    def clean_username(self):
        """用户名"""
        ret = models.UserInfo.objects.filter(username=self.cleaned_data.get("username"))
        if not ret:
            return self.cleaned_data.get("username")
        else:
            raise ValidationError("用户名已注册")

    def clean_password(self):
        """密码"""
        data = self.cleaned_data.get("password")
        if not data.isdigit():
            return self.cleaned_data.get("password")
        else:
            raise ValidationError("密码不能全是数字")

    # def clean_auth_code(self):
    #     if self.cleaned_data.get("auth_code")==self.request.session.get("auth_code"):
    #         return self.cleaned_data.get("auth_code")
    #     else:
    #         raise ValidationError("验证码错误")

    def clean(self):
        if self.cleaned_data.get("password")==self.cleaned_data.get("confirm_password"):
             return self.cleaned_data
        else:
            raise ValidationError("两次密码不一致")

    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request=request
#文章From组件
class ArticleFrom(forms.Form):
    title = forms.CharField(
        required=True,
        max_length=20,
        error_messages={
            "required":"不能为空",
        },widget=widgets.TextInput(attrs={ 'class': 'form-control'}))
    content = forms.CharField(
        required=True,
        error_messages={
            "required": "不能为空",
    },widget=widgets.Textarea(attrs={ 'class': 'form-control'}))
    def clean_content(self):
        # 拿到文章内容
        html_str=self.cleaned_data.get("content")
        #调用函数
        clean_content=xss_plugin.filter_xss(html_str)
        self.cleaned_data["content"]=clean_content
        return self.cleaned_data.get("content")
View Code
原文地址:https://www.cnblogs.com/w-s-l123/p/7889024.html