Python学习之路—2018/7/14
3.功能開發(fā)
3.3 設(shè)計博客首頁
博客首頁中最重要的就是中間的文章區(qū)域,所以我首先把文章區(qū)域設(shè)計出來,一開始并沒有數(shù)據(jù),如果用orm添加或者直接在數(shù)據(jù)庫添加數(shù)據(jù)較為麻煩,這時候需要用到django提供的admin,在地址欄輸入127.0.0.1:8000/admin,會看見如下的頁面:
這時候輸入超級用戶的賬號和密碼,超級用戶通過終端輸入python manage.py createsuperuser進行添加,登錄過后是會看見如下頁面:
接下來在這個頁面進行數(shù)據(jù)的添加,需要注意是添加的順序,首先應(yīng)該添加User表,加下來分別是Blog表、Sort表、Tag表,最后是Article表以及Article to tag表,評論表和點贊表可以暫時不填。添加完數(shù)據(jù)以后就開始設(shè)計博客主界面了。
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> <!--頂部導(dǎo)航欄--> <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> <!-- 主體內(nèi)容 --> <div class="container-fluid"><div class="row"><!-- 左側(cè)區(qū)域 --><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><!-- 中間文章區(qū)域 --><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>發(fā)布于 {{ 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><!-- 右側(cè)區(qū)域 --><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 設(shè)計個人站點首頁
由于個人站點以及后面的文章詳情頁他們的不同知識文章區(qū)域,所以為了避免重復(fù)的代碼,首先設(shè)計一個模板頁面,將需要用到的數(shù)據(jù)先規(guī)劃好,個人站點需要名字、圓齡、隨筆分類以及對應(yīng)文章數(shù)量、標簽分類以及對應(yīng)的文章數(shù)量、時間分類以及對應(yīng)的文章數(shù)量以及文章列表。
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 %}
在開發(fā)中,如果遇到視圖與數(shù)據(jù)相結(jié)合作為模板的時候,可以使用inclusion_tag(xxx),它接受一個參數(shù),這個參數(shù)是你需要渲染的html代碼。步驟大概如下:
在項目中創(chuàng)建一個名為templatetags的包(名字必須是這個)
在templatetags的包中創(chuàng)建存放自定義標簽的py文件
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 即數(shù)據(jù)和視圖相結(jié)合的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) # 園齡# 當前站點的每一個分類名稱以及文章數(shù)sort_list = Sort.objects.filter(blog=blog).values("sid").annotate(c=Count("article__aid")).values_list("title", "c")# 當前站點每個標簽名稱以及文章數(shù)tag_list = Tag.objects.filter(blog=blog).values("tid").annotate(c=Count("article__aid")).values_list("name", "c")# 當前站點每一個年月的名稱以及文章數(shù)# 方式一# 當用到較為復(fù)雜的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} # 將所需數(shù)據(jù)存放在字典中傳遞給html部分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>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 %}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; }views.py
urls.py
urlpatterns = [# 個人站點查詢re_path(r'^(?P<username>\w+)/$', home_site),# 個人站點跳轉(zhuǎn)re_path(r'^(?P<username>\w+)/(?P<condition>sort|tag|date)/(?P<parm>.*)/$', home_site), ]展示效果:
它的順序是:
注意:
- 利用inclusion_tag完成數(shù)據(jù)與視圖的結(jié)合
- 個人站點url的跳轉(zhuǎn)(例如點擊分類會出現(xiàn)當代當前分類的所有文章)主要通過給每個分類/標簽/時間添加a標簽,指向url,而在視圖函數(shù)中通過增加參數(shù)來完成篩選,將篩選后的文章列表傳遞給html
- 當只需要用到datetime的個別元素,例如年月,可以使用django的Trunc函數(shù),例如TruncMonth只會截斷到月,剩余的日時分秒不會被取到
- 避免過多的重復(fù)代碼
實現(xiàn)效果:
轉(zhuǎn)載于:https://www.cnblogs.com/ExBurner/p/9308099.html
總結(jié)
以上是生活随笔為你收集整理的Python学习之路—2018/7/14的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用属性升级MyBank
- 下一篇: 【NOIP2013模拟】黑魔法师之门