• 博客系统


     博客系统项目整理:

     一:创建表:

    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
  • 相关阅读:
    33.数组声明方式(var构造函数) 、检测数组类型、数组的属性(封装好的就一个length)、数组的方法
    31.this指向(写出调用链,找最近对象) this的默认绑定 隐式绑定 显示绑定(call(绑定对象) apply(绑定对象) 当括号内没放绑定对象的时候恢复默认绑定) bind
    31.
    30.函数作用域链 (GO AO 也叫词法作用域链)、 调用栈、调用栈涉及this绑定
    29.包装类(构造函数) 包装类作用及调用栈
    916. Word Subsets
    246. Strobogrammatic Number
    445. Add Two Numbers II
    2. Add Two Numbers
    341. Flatten Nested List Iterator
  • 原文地址:https://www.cnblogs.com/w-s-l123/p/7889024.html
Copyright © 2020-2023  润新知