Python学习之路—2018/7/12

3.功能开发

3.3 设计博客首页

博客首页中最重要的就是中间的文章区域,所以我首先把文章区域设计出来,一开始并没有数据,如果用orm添加或者直接在数据库添加数据较为麻烦,这时候需要用到django提供的admin,在地址栏输入127.0.0.1:8000/admin,会看见如下的页面:

这时候输入超级用户的账号和密码,超级用户通过终端输入python manage.py createsuperuser进行添加,登录过后是会看见如下页面:

接下来在这个页面进行数据的添加,需要注意是添加的顺序,首先应该添加User表,加下来分别是Blog表、Sort表、Tag表,最后是Article表以及Article to tag表,评论表和点赞表可以暂时不填。添加完数据以后就开始设计博客主界面了。

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>博客首页</title><link rel="icon" href="/static/blog/image/favicon.ico"><link rel="stylesheet" href="/static/blog/css/bootstrap.min.css"><link rel="stylesheet" href="/static/blog/css/index.css">
</head>
<body>
<!--顶部导航栏-->
<nav class="navbar navbar-default"><div class="container-fluid"><div class="navbar-header"><a class="navbar-brand" href="/index">博客园</a></div><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav"><li><a href="#">新闻</a></li><li><a href="#">博文</a></li></ul><ul class="nav navbar-nav navbar-right">{% if request.user.is_authenticated %}<li><a href="#"><img src="/static/blog/image/user_log.png" id="user_log">{{ request.user.username }}</a></li><li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"aria-expanded="false">用户中心 <span class="caret"></span></a><ul class="dropdown-menu"><li><a href="#">修改密码</a></li><li role="separator" class="divider"></li><li><a href="#">修改头像</a></li><li role="separator" class="divider"></li><li><a href="/logout">注销</a></li></ul></li>{% else %}<li><a href="/register">注册</a></li><li><a href="/login">登录</a></li>{% endif %}</ul></div><!-- /.navbar-collapse --></div><!-- /.container-fluid -->
</nav>
<!-- 主体内容 -->
<div class="container-fluid"><div class="row"><!-- 左侧区域 --><div class="col-md-3"><div class="panel panel-default"><div class="panel-heading">Panel heading without title</div><div class="panel-body">Panel content</div></div><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">Panel title</h3></div><div class="panel-body">Panel content</div></div></div><!-- 中间文章区域 --><div class="col-md-6"><div class="article_list">{% for article in article_list %}<div class="article_item"><h5><a>{{ article.title }}</a></h5><div class="article_desc media-body"><span class="media-left"><a href="/{{ article.user.username }}"><img src="/media/{{ article.user.avatar }}" id="user_avatar"></a></span><span class="media-right">{{ article.abstract }}</span></div><div class="article_foot small"><span><a href="/{{ article.user.username }}">{{ article.user.username }}</a></span>   <span>发布于 {{ article.create_time|date:"Y-m-d H:i"}}  </span><span><a><img src="/static/blog/image/comment.png">评论({{ article.comment_count }})</a> </span><span><a><img src="/static/blog/image/like.png">点赞({{ article.comment_count }})</a></span></div></div><hr>{% endfor %}</div></div><!-- 右侧区域 --><div class="col-md-3">1</div></div>
</div>
</body>
<script type="text/javascript" src="/static/blog/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="/static/blog/js/bootstrap.min.js"></script>
</html>

index.css

a:hover {cursor: pointer;text-decoration: none;
}.login-head {margin-bottom: 10px;border-bottom: 1px solid #ddd;
}.login-head a {margin-left: 287px;color: #5cb85c;
}#avatar_img {width: 60px;height: 60px;margin-left: 20px;
}.error {color: red;
}#user_log {margin-right: 5px;
}#user_avatar {width: 60px;height: 60px;
}.article_foot {margin-top: 10px;
}.article_foot img {vertical-align: -3px;margin-right: 2px;
}

views.py

# 博客首页
def index(request):article_list = Article.objects.all().order_by("-create_time")return render(request, "index.html", locals())# 注销
def logout(request):auth.logout(request)return redirect("/login")

urls.py

urlpatterns = [path('index/', index),
]

展示效果:

3.4 设计个人站点首页

由于个人站点以及后面的文章详情页他们的不同知识文章区域,所以为了避免重复的代码,首先设计一个模板页面,将需要用到的数据先规划好,个人站点需要名字、圆龄、随笔分类以及对应文章数量、标签分类以及对应的文章数量、时间分类以及对应的文章数量以及文章列表。

base.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ user.username }} - 博客园</title><link rel="icon" href="/static/blog/image/favicon.ico"><link rel="stylesheet" href="/static/blog/css/bootstrap.min.css"><link rel="stylesheet" type="text/css" href="/static/blog/css/home_site.css"><style type="text/css">a:hover {cursor: pointer;text-decoration: none;}.panel-body a:hover {color: red;}</style>
</head>
<body>
<div id="home"><div id="header"><div id="blogTitle"><h1><a href="/{{ user.username }}">{{ user.username }}</a></h1></div><div id="navigator"><ul id="navList"><li><a href="/index">博客园</a></li><li><a href="/{{ username }}">首页</a></li><li><a>管理</a></li></ul></div></div><div id="main"><div class="col-md-3">{% load my_tags %}{% get_style username %}</div><div class="col-md-9">{% block content %}{% endblock %}</div></div>
</div>
</body>
</html>

首先介绍一下{% load my_tags %} {% get_style username %}

在开发中,如果遇到视图与数据相结合作为模板的时候,可以使用inclusion_tag(xxx),它接受一个参数,这个参数是你需要渲染的html代码。步骤大概如下:

  1. 在项目中创建一个名为templatetags的包(名字必须是这个)

  2. 在templatetags的包中创建存放自定义标签的py文件

  3. my_tags.py

    from django import template
    from django.db.models import Count
    from django.db.models.functions import TruncMonth
    import datetime
    from blog.models import *register = template.Library()@register.inclusion_tag("get_style.html")  # get_style.html 即数据和视图相结合的Html部分
    def get_style(username):user = User.objects.filter(username=username).first()if user:blog = user.blognow = datetime.datetime.now()both = user.create_timeday = (now - both).daysage = int(day / 30)  # 园龄# 当前站点的每一个分类名称以及文章数sort_list = Sort.objects.filter(blog=blog).values("sid").annotate(c=Count("article__aid")).values_list("title", "c")# 当前站点每个标签名称以及文章数tag_list = Tag.objects.filter(blog=blog).values("tid").annotate(c=Count("article__aid")).values_list("name", "c")# 当前站点每一个年月的名称以及文章数# 方式一# 当用到较为复杂的sql查询语句时(例如日期的阶段,大小的比较),需要用到extra(select="")方法# date_list = Article.objects.filter(user=user).extra(#     select={"Y_m_date": "date_format(create_time, '%%Y年%%c月')"}).values("Y_m_date").annotate(#     c=Count("aid")).values_list("Y_m_date", "c")# 方式二,使用django封装的TruncMonth()方法,它会将日期截断到月,抛弃后面的,接下来只需要在html中通过date标签来格式化日期格式就OK了"""Article.objects.filter(user=user).annotate(Y_m_date=TruncMonth("create_time"))    将日期截断至月份并加入到字段中.values("Y_m_date")    group by Y_m_date.annotate(c=Count("aid"))   select count(aid) as c.values_list("Y_m_date", "c")    select Y_m_date, c"""date_list = Article.objects.filter(user=user) \.annotate(Y_m_date=TruncMonth("create_time")) \.values("Y_m_date") \.annotate(c=Count("aid")) \.values_list("Y_m_date", "c")return {"user": user, "blog": blog, "sort_list": sort_list, "tag_list": tag_list, "date_list": date_list, "age": age}  # 将所需数据存放在字典中传递给html部分
  4. get_style.html

    <div id="user_info">昵称:{{ user.username }}<br>园龄:{{ age }}个月
    </div>
    <div class="panel panel-primary"><div class="panel-heading">随笔分类</div>{% for sort in sort_list %}<div class="panel-body"><a href="/{{ user.username }}/sort/{{ sort.0 }}">{{ sort.0 }}({{ sort.1 }})</a></div>{% endfor %}
    </div>
    <div class="panel panel-primary"><div class="panel-heading">我的标签</div>{% for tag in tag_list %}<div class="panel-body"><a href="/{{ user.username }}/tag/{{ tag.0 }}/">{{ tag.0 }}({{ tag.1 }})</a></div>{% endfor %}
    </div>
    <div class="panel panel-primary"><div class="panel-heading">文章归档</div>{% for date in date_list %}<div class="panel-body"><a href="/{{ user.username }}/date/{{ date.0|date:"Y-n" }}/">{{ date.0|date:"Y年n月" }}({{ date.1 }})</a></div>{% endfor %}
    </div>
  5. home_site.html

    {% extends "base.html" %}{% block content %}{% for article in article_list %}<div class="article_item"><div class="article_date">{{ article.create_time|date:"Y月n月d日" }}</div><div class="article_title"><a>{{ article.title }}</a></div><div class="article_desc"><span class="media-right">摘要:{{ article.abstract }}</span></div><div class="article_foot">posted @ {{ article.create_time|date:"Y-m-d H:i" }} {{ user.username }}评论({{ article.comment_count }}) 点赞({{ article.up_count }})</div></div>{% endfor %}
    {% endblock %}
  6. home_site.css

    * {margin: 0;padding: 0;
    }body {background: url('/static/blog/image/web_site_bk.jpg') fixed no-repeat;background-position: 50% 5%;background-size: cover;font-family: inherit;
    }#home {margin: 0 auto;width: 80%;min-width: 980px;background-color: rgba(245, 245, 245, 0.7);padding: 30px;margin-top: 50px;margin-bottom: 50px;box-shadow: 0 2px 6px rgba(100, 100, 100, 0.3);overflow: hidden;
    }a {text-decoration: none;
    }a:visited, a:link {color: black;
    }#blogTitle {margin-bottom: 25px;
    }#blogTitle h1 {font-size: 36px;font-weight: bold;line-height: 1.8em;margin-top: 10px;margin-left: 35px;
    }#blogTitle a:hover {color: #ff4001;
    }#navigator {background-color: #009ACD;height: 60px;line-height: 60px;overflow: hidden;clear: both;float: left;
    }#navList {min-height: 30px;float: left;margin-right: 579px;
    }#navList li {float: left;list-style: none;
    }#navList li:hover {background-color: #343434;
    }#navList a {display: block;padding: 0 1.5em;height: 60px;float: left;font-size: 1.2em;text-align: center;transition-duration: 0.3s;color: #eee;
    }#navList a:hover {text-decoration: none;
    }#blogStats {float: right;padding-right: 10px;text-align: right;color: #eee;
    }#main {min-width: 950px;text-align: left;padding: 20px 0 0 10px;overflow: hidden;
    }#user_avatar {width: 60px;height: 60px;margin-left: 20px;
    }.article_item {min-height: 10px;box-shadow: 1px 1px 2px #A7A8AD;color: #666666;margin: 0 5px 60px 0;padding: 5px 20px 10px;background: rgba(255, 255, 255, 0.5)
    }.article_title {border-left: 8px solid rgba(33, 160, 139, 0.68);margin-left: 10px;margin-bottom: 10px;font-size: 20px;float: right;width: 100%;clear: both;font-weight: bold;border-bottom: 1px dashed #ccc;line-height: 2.5em;padding-left: 10px;
    }.article_title a:hover {margin-left: 20px;
    }.article_desc {margin-top: 70px;
    }.article_date {width: 100%;color: black;line-height: 2.2em;font-size: 22px;clear: both;border-bottom: 1px solid #ccc;text-align: center;
    }.article_foot {color: #757575;width: 100%;clear: both;text-align: left;font-size: 13px;margin-top: 20px;line-height: 1.8;padding-bottom: 20px;
    }#user_info {border-radius: 7px;box-shadow: 1px 1px 2px #A7A8AD;color: black;padding: 15px 15px 10px;background: rgba(255, 255, 255, 0.5);margin-bottom: 30px;
    }.panel {background: rgba(255, 255, 255, 0.5);margin-bottom: 30px;
    }.panel-heading {font-size: 20px;
    }.panel-body {border-bottom: 1px solid white;
    }
  7. views.py

def home_site(request, username, **kwargs):"""个人站点:param request::param username::return:"""user = User.objects.filter(username=username).first()if user:article_list = Article.objects.filter(user=user)# 当前的站点下的所有文章# 基于对象查询   article_list = user.article_set.all()# 基于双下划线查询if kwargs:condition = kwargs.get("condition")parm = kwargs.get("parm")if condition == "sort":article_list = article_list.filter(sort__title=parm)elif condition == "tag":article_list = article_list.filter(tag__name=parm)elif condition == "date":year = parm.split("-")[0]month = parm.split("-")[1]article_list = article_list.filter(create_time__year=year, create_time__month=month)article_list = article_list.order_by("-create_time")return render(request, "home_site.html", locals())else:return render(request, "404.html")

urls.py

urlpatterns = [# 个人站点查询re_path(r'^(?P<username>\w+)/$', home_site),# 个人站点跳转re_path(r'^(?P<username>\w+)/(?P<condition>sort|tag|date)/(?P<parm>.*)/$', home_site),
]

展示效果:

它的顺序是:

  1. 在自定义的标签中,首先会执行代码,将数据传递给inclusion_tag(xxx)参数中的html,即get_style.html
  2. get_style.html根据传来的数据完成自身的渲染
  3. base.html中调用inclusion_tag标签的部分完成渲染,即添加get_style.html内容
  4. 个人站点页面继承模板页面,最终呈现

注意:

  • 利用inclusion_tag完成数据与视图的结合
  • 个人站点url的跳转(例如点击分类会出现当代当前分类的所有文章)主要通过给每个分类/标签/时间添加a标签,指向url,而在视图函数中通过增加参数来完成筛选,将筛选后的文章列表传递给html
  • 当只需要用到datetime的个别元素,例如年月,可以使用django的Trunc函数,例如TruncMonth只会截断到月,剩余的日时分秒不会被取到
  • 避免过多的重复代码

实现效果:

转载于:https://www.cnblogs.com/ExBurner/p/9308099.html

Python学习之路—2018/7/14相关推荐

  1. Python学习之路—2018/6/20

    Python学习之路-2018/6/20 1.模板语法之变量 views.py def index(request):import datetimes="gyq"l=[1,2,3] ...

  2. Python学习之路—2018/6/27

    Python学习之路-2018/6/27 1.多表操作 添加记录 添加多对多关系 方式一:传入Author对象 book = Book.objects.get(bid=1) gy = Author.o ...

  3. 2018python培训-Python学习之路—2018/7/2

    Hello World Ajax +=提交 用户名 密码 提交

  4. Python学习之路9☞面向对象的程序设计

    Python学习之路9☞面向对象的程序设计 一 面向对象的程序设计的由来 见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 二 什 ...

  5. Python学习之路5☞文件处理

    Python学习之路5☞文件处理 一.文件处理流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 1 正趣果上果 2 Interesting fruit fruit 3 4 ...

  6. Python学习之路【第一篇】-Python简介和基础入门

    1.Python简介 1.1 Python是什么 相信混迹IT界的很多朋友都知道,Python是近年来最火的一个热点,没有之一.从性质上来讲它和我们熟知的C.java.php等没有什么本质的区别,也是 ...

  7. python之路 mysql 博客园_教为学:Python学习之路(二):MySQLdb的几种安装方式,以及用Python测试连接MySql...

    教为学:Python学习之路(二):MySQLdb的几种安装方式,以及用Python测试连接MySql Easy_install安装MySQLdb 很简单,以至于我不晓得该怎么说.一句话. sodu ...

  8. 对QT学习之路12-14的源代码补充与修正

    QT学习之路12-14的源代码有些不完整,为了更好的让大家学习,本人做了一点修正与补充,谢谢.源代码如下: 头文件: #ifndef MAINWINDOW_H #define MAINWINDOW_H ...

  9. python 学习之路开始了

    python 学习之路开始了.....记录点点滴滴.... 转载于:https://www.cnblogs.com/chobit/p/6163287.html

最新文章

  1. c++11 function
  2. php自动导入,PHP自动导入类
  3. Cloudify — Blueprints
  4. 软件工程系列教材:软件架构设计实践教程
  5. Silverlight2 边学边练 之三 小球自由落体
  6. 20160808_安装JDK7u79
  7. Remoting简介
  8. procreate 笔刷_Procreate新手漫画入门:笔刷,图层,上色
  9. 鸟哥的linux私房菜简答题答案,《鸟哥的Linux私房菜》7章 Linux文件与目录管理 习题答案...
  10. 按下组合键 可以迅速锁定计算机,Win7锁定计算机快捷键是什么?Win7使用锁定计算机快捷键的方法...
  11. html中grid布局,CSS:玩转grid布局
  12. 选手及评委素材信息规范处理说明
  13. PHP教程一环境搭建 Wampserve 下载和安装
  14. 反相高低频技术磨皮法
  15. 基于Pytorch实现人脸关键点检测模型MTCNN
  16. 屏幕镜像显示无法连接服务器,Ios屏幕镜像连不上怎么办?
  17. 疫情期间的中老年众生相:刷抖音/云买菜/直播购物,加速“触网”
  18. 国产linux系统 深度6,国产Linux系统深度Deepin体验
  19. vscode造成c盘空间占用剧增
  20. @Valid使用详解

热门文章

  1. ubuntu 14.04下spark简易安装
  2. 软件工程——理论、方法与实践 第六章
  3. 把磁盘崩溃了,总是进去维护模式,却删除不了fstab文件中的内容
  4. MapPoint之旅(2)-----Getting Started with MapPoint Web Service(1)
  5. OpenCV 1.x 2.x 编程简介(矩阵/图像/视频的基本读写操作)
  6. 从0开始学习GitHub系列之「Git 速成」
  7. UVA 253 Cube painting
  8. C++对象模型详解(上)
  9. Linux基础知识(一)
  10. 解决Maven项目pom.xml文件报xxx\target\classes\META-INF\MANIFEST.MF (系统找不到指定的路径。)问题...