zoukankan      html  css  js  c++  java
  • 博客系统

     博客系统项目整理:

     一:创建表:

    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
  • 相关阅读:
    【SpringMVC】数据校验时,抛出javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: java.util.Date.
    【SpringMVC】添加操作时返回400
    【c#】 使用Directory.GetFiles获取局域网中任意电脑指定文件夹下的文件
    【opencv】Java实现opencv 调用本地摄像头,实现人脸识别、人形识别、人眼识别
    【opencv】Java实现的opencv3.x版本后Highhui报错
    【opencv】Java+eclipse+opencv 环境搭建 helloword入门demo
    【微信小程序】--小程序中循环遍历(包括js中遍历和wxml中的遍历)
    【微信小程序】--bindtap参数传递,配合wx.previewImage实现多张缩略图预览
    linux命令:tail
    system()
  • 原文地址:https://www.cnblogs.com/w-s-l123/p/7889024.html
Copyright © 2011-2022 走看看