1. 程式人生 > >Django博客項目之個人站點

Django博客項目之個人站點

個人站點 文章頁面

一、對url做分發

項目cnblog_s20的urls.py內容:

from django.conf.urls import url,include
from django.contrib import admin
from blog import views
from django.views.static import serve
from cnblog_s20 import settings
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^reg/', views.reg),
    url(r'^logout/', views.logout),
    url(r'^valid_img/', views.valid_img),
    url(r'^index/', views.index),
    url(r'^$', views.index),
    url(r'^blog/', include("blog.urls")),               #做分發,訪問blog做分發
    # media 配置
    url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]

應用的urls.py內容:

from django.conf.urls import url, include
from django.contrib import admin
from blog import views
from django.views.static import serve
from cnblog_s20 import settings
urlpatterns = [
    url(r'^(?P<username>\w+)/$',views.homesite),
    url(r'^(?P<username>\w+)/(?P<condition>tag|cate|achrive)/(?P<params>.*)',views.homesite),
    url(r'^(?P<username>\w+)/articels/(?P<article_id>\d+)',views.article_detail),
]

二、日期歸檔

1、數據庫類型

表示時間值的日期和時間類型為DATETIME、DATE、TIMESTAMP、TIME和YEAR

date類型-------> 2018-05-01
time類型-------> 19:42:22
datetime類型-------> 2018-05-01 19:42:22

MySQL對應的方法:  date_format
sqlite對應的方法 :striftime

2、extra

extra(select=None, where=None, params=None,
      tables=None, order_by=None, select_params=None)

有些情況下,Django的查詢語法難以簡單的表達復雜的 WHERE 子句,對於這種情況, Django 提供了 extra() QuerySet修改機制 — 它能在 QuerySet生成的SQL從句中註入新子句

(1)參數之select

The select 參數可以讓你在 SELECT 從句中添加其他字段信息,它應該是一個字典,存放著屬性名到 SQL 從句的映射。


queryResult=models.Article

           .objects.extra(select={'is_recent': "create_time > '2018-05-05'"})

結果集中每個 Entry 對象都有一個額外的屬性is_recent, 它是一個布爾值,表示 Article對象的create_time 是否晚於2018-05-05,true表示晚於2018-05-05

#sqlite數據庫:
    article_obj=models.Article.objects
              .extra(select={"standard_time":"strftime('%%Y-%%m-%%d',create_time)"})
              .values("standard_time","nid","title")
    print(article_obj)
    # <QuerySet [{'title': 'MongoDb 入門教程', 'standard_time': '2018-05-05', 'nid': 1}]>


(2)參數之where / tables

您可以使用where定義顯式SQL WHERE子句 - 也許執行非顯式連接。您可以使用tables手動將表添加到SQL FROM子句。


where和tables都接受字符串列表。所有where參數均為“與”任何其他搜索條件。

queryResult=models.Article
           .objects.extra(where=['nid in (1,3) OR title like "py%" ','nid>2'])

3、ORM分組查詢

當前站點以年月形式顯示的日期以及對應的文章數
article_list=Article.objectsv.filter(user=user).extra(select={"time":"strftime('%%Y-%%m',create_time)"}).values("time").annotate(c=Count("title")).values_list("time", "c")

4、表關系練習

(1)創建表關系

models.py文件內容:

from django.db import models
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=6, decimal_places=2)
    create_time = models.DateField()
    memo = models.CharField(max_length=32, default="")
    publish = models.ForeignKey(to="Publish", default=1)
    author = models.ManyToManyField("Author")
    def __str__(self):
        return self.title
class Publish(models.Model):
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
class Author(models.Model):
    name = models.CharField(max_length=32)
    def __str__(self): return self.name
class AuthorDetail(models.Model):
    tel = models.CharField(max_length=32)
    email = models.EmailField()
    author = models.OneToOneField("Author")
    def __str__(self): return self.email


(2)ORM分組查詢

annotate():按annotate前面的select字段進行group by

多表:
Publish.objects.all().annotate(c=Count(book)).values("name", "c")            #每一個出版社出版的名字和對應的書籍個數
Book.objects.all().annotate(c=Count(authors)).values("title", "c")           #每一本書籍和對應的作者的個數
Author.objects.all().annotate(x=Max(book__prcie))                             #每一個作者出版書籍的最高價格
單表:
Book.objects.all().values("publish").annotate(Count("title"))


ret = Article.objects.all().values("user").annotate(c=Count("title")).values("user_id", "c")    #每一個作者的user_id對應的文章數
ret = Category.objects.filter(blog=blog).annotate(c=Count("article")).values("title", "c")       #當前站點的每一個分類名稱和對應的文章數
ret = Tag.objects.filter(blog=blog).annotate(c=Count("article")).values("title", "c")           #當前站點的每一個標簽名稱和對應的文章數

三、個人站點函數及html頁面

views.py文件添加homesite視圖函數:

def homesite(request,username,**kwargs):
    # 查當前站點的用戶對象
    user=UserInfo.objects.filter(username=username).first()
    #  查詢當前站點對象
    blog=user.blog
    # 查詢當前站點的所有文章,實現點擊tag|cate|achrive中的a標簽可以查看對應的文章
    if kwargs:
        condition=kwargs.get("condition")                #得到url的路徑類型:tag|cate|achrive其中一個
        params=kwargs.get("params")
        if condition=="cate":
            article_list=Article.objects.filter(user=user).filter(category__title=params)     # 當前站點的所有文章的分類對象
        elif condition=="tag":
            article_list=Article.objects.filter(user=user).filter(tags__title=params)        # 當前站點的所有文章的標簽對象
        else:
            year,month=params.split("-")
            article_list=Article.objects.filter(user=user).filter(create_time__year=year,create_time__month=month)   # 當前站點的所有文章的日期對象
    else:
         article_list=Article.objects.filter(user=user)       #訪問的個人站點,顯示當前站點的所有文章
    return render(request,"homesite.html",locals())

homesite.html頁面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;                {#清除邊距#}
            padding: 0;
        }
        .header {
            width: 100%;
            height: 60px;
            background-color: #369;
            line-height: 60px;        {#文本居住#}
        }
        .header .title {
            font-size: 20px;
            font-weight: 100;
            color: white;
            margin-left: 20px;         {#向右偏移20px#}
        }
    </style>
    <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
    <script src="/static/js/jquery-3.2.1.min.js"></script>
    <script src="/static/bs/js/bootstrap.js"></script>
</head>
<body>
<div>
    <p>{{ blog.title }}</p>
</div>
<div>
    <div>
        <div>
            <div class="panel panel-warning">
                        <div>
                            <h3>我的分類</h3>
                        </div>
                        <div>
                            {% for cate in cate_list %}
                                <p><a href="/blog/{{ username }}/cate/{{ cate.0 }}">{{ cate.0 }}({{ cate.1 }})</a></p>   {#分類及對應的文章數#}
                            {% endfor %}
                        </div>
                    </div>
            <div class="panel panel-danger">
                <div>
                    <h3>文章標簽</h3>
                </div>
                <div>
                    {% for tag in tag_list %}
                        <p><a href="/blog/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>        {#標簽及對應的文章數#}
                    {% endfor %}
                </div>
            </div>
            <div class="panel panel-info">
                <div>
                    <h3>日期歸檔</h3>
                </div>
                <div>
                    {% for date in date_list %}
                        <p><a href="/blog/{{ username }}/achrive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p>
                    {% endfor %}
                </div>
            </div>
        </div>
        <div>
             <div>
                            {% for article in article_list %}
                                <div>
                                    <h5><a href="/blog/{{ username}}/articels/{{ article.pk }}">{{ article.title }}</a></h5>
                                    <div>
                                        <div>
                                            <div>
                                                <div>
                                                    {{ article.desc }}
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="small info pull-right">
                                        發布於
                                        <span>{{ article.create_time|date:'Y-m-d H:i' }}</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                        <span class="glyphicon glyphicon-comment"
                                              style="color: #1b6d85;vertical-align: -3px"></span>評論({{ article.comment_count }})&nbsp;&nbsp;
                                        <span class="glyphicon glyphicon-thumbs-up"
                                              style="color: #1b6d85;vertical-align: -3px"></span>點贊({{ article.up_count }})
                                    </div>
                                </div>
                                <hr>
                            {% endfor %}
                        </div>
            {% endblock %}
        </div>
    </div>
</div>
</body>
</html>

技術分享圖片

技術分享圖片

四、頁面繼承

個人站點和文章詳情頁面左側部分都一樣,可以用頁面繼承防止代碼重復


base.html頁面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .header {
            width: 100%;
            height: 60px;
            background-color: #369;
            line-height: 60px;
        }
        .header .title {
            font-size: 20px;
            font-weight: 100;
            color: white;
            margin-left: 20px;
        }
    </style>
    <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
    <script src="/static/js/jquery-3.2.1.min.js"></script>
    <script src="/static/bs/js/bootstrap.js"></script>
</head>
<body>
<div>
    <p>{{ blog.title }}</p>
</div>
<div>
    <div>
        <div>
            {% load my_tags %}
            
            {% get_query_data username %}
        </div>
        <div>
           {% block content %}
           
           {% endblock %}
        </div>
    </div>
</div>
</body>
</html>

menu.html頁面:

<div>
    <div class="panel panel-warning">
                <div>
                    <h3>我的分類</h3>
                </div>
                <div>
                    {% for cate in cate_list %}
                        <p><a href="/blog/{{ username }}/cate/{{ cate.0 }}">{{ cate.0 }}({{ cate.1 }})</a></p>
                    {% endfor %}
                </div>
            </div>
    <div class="panel panel-danger">
        <div>
            <h3>文章標簽</h3>
        </div>
        <div>
            {% for tag in tag_list %}
                <p><a href="/blog/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
            {% endfor %}
        </div>
    </div>
    <div class="panel panel-info">
        <div>
            <h3>日期歸檔</h3>
        </div>
        <div>
            {% for date in date_list %}
                <p><a href="/blog/{{ username }}/achrive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p>
            {% endfor %}
        </div>
    </div>
</div>

homesite.html頁面:

{%extends "base.html" %}

{% block content %}
 <div>
                {% for article in article_list %}
                    <div>
                        <h5><a href="/blog/{{ username}}/articels/{{ article.pk }}">{{ article.title }}</a></h5>
                        <div>
                            <div>
                                <div>
                                    <div>
                                        {{ article.desc }}
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="small info pull-right">
                            發布於
                            <span>{{ article.create_time|date:'Y-m-d H:i' }}</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <span class="glyphicon glyphicon-comment"
                                  style="color: #1b6d85;vertical-align: -3px"></span>評論({{ article.comment_count }})&nbsp;&nbsp;
                            <span class="glyphicon glyphicon-thumbs-up"
                                  style="color: #1b6d85;vertical-align: -3px"></span>點贊({{ article.up_count }})
                        </div>
                    </div>
                    <hr>
                {% endfor %}
            </div>
{% endblock %}

五、文章詳情

views.py文件添加article_detail函數

def article_detail(request,username,article_id):
    # 查當前站點的用戶對象
    user = UserInfo.objects.filter(username=username).first()
    #  查詢當前站點對象
    blog = user.blog
    article_obj=Article.objects.filter(pk=article_id).first()       #得到文章對象
    return render(request,"article_detail.html",locals())

article_detail.html頁面:

{% extends "base.html" %}

{% block content %}
     <h3>{{ article_obj.title }}</h3>        {#標題居住#}
    <div>
        {{ article_obj.articledetail.content|safe }}
    </div>
{% endblock %}

數據庫保存的是標簽,不加safe會顯示字符串,瀏覽器不能成功渲染,加上safe後就可以識別標簽,能夠渲染頁面,這樣就會執行可能存在的script等標簽,很不安全

所以我們必須加safe,但是要保證用戶存到數據庫的沒有script標簽,即將script標簽轉意或者過濾掉。

技術分享圖片




Django博客項目之個人站點