Day07 後臺管理與發佈文章

Day07 後臺管理與發佈文章

源代碼: https://github.com/LToddy/blog

技術交流羣:630398887(歡迎一起吹牛)

寫在前面的話:如果你實在不會寫頁面,複製粘貼你會吧.

https://getbootstrap.com/docs/3.3/examples/theme/

這個頁面是,bootstrap樣式表的例樣,

http://getbootstrap.com/docs/4.0/examples/

這個頁面是,你進去看那個頁面合適,你點進去,然後右鍵查看網頁源代碼,複製就好了,順便說一下,別忘了把CSS也複製了.

我們來定義下我們的文章模型,文章內容放到數據庫裏面,然後通過查詢文章標題來,在主頁建立文章鏈接。

app/models.py

class Article(db.Model):
    __tablename__ = 'articles'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    content = db.Column(db.Text)

文章模型很簡單,一個id,一個文章標題,一個文章的內容這三個字段。
content = db.Column(db.Text),這裏,回顧一下或者百度一下SQLAlchemy的列模型。

因爲我們文章內容可不是幾個字,而是很多上千上萬字說不定,所以就不能再用簡單的db.String來處理了。
我們使用db.Text這個,他對長文本做了優化.

當我們有了這個數據庫的文章模型之後,爲了給數據庫添加數據,那麼我們還需要相對應的表單:

app/admin/forms.py

class PostForm(FlaskForm):
    title = StringField('文章標題:', validators=[Required()])
    content = TextAreaField('文章內容', validators=[Required()])
    submit = SubmitField('發佈')

你看注意看變量的名字,我們最可能的讓表單和文章模型中的變量去相同的名字,這樣方便。

OK,繼續。我們有了表單,要在頁面中呈現出來。

app/admin/views.py

from ..models import Article

@admin.route('/', methods=['GET', 'POST'])
def index():
    form = PostForm()
    if not current_user.is_authenticated:
        return redirect(url_for('admin.login'))
    if form.validate_on_submit():
        try:
            article = Article(title=form.title.data, content=form.content.data)
            db.session.add(article)
            form.title.data = ''
            form.content.data = ''
            flash('發佈成功')
        except:
            flash('文章標題有重複')
    return render_template('admin/index.html', form=form)

這段代碼也沒什麼難度,先去創建一個表單form,然後判斷一下你是否登錄了,沒登錄的話就會重定向到登錄界面。
繼續往下,讓你提交表單的時候,這裏用到了一個try - catch語句,其實這裏原因是,我最初想把那個數據庫文章模型中title字段設置成unique的,title = db.Column(db.String(64),unique=True),後來想想算了,所不定有相同標題的文章呢。然後就是從表單中獲取數據,來構件新的文章,然後存到數據庫裏面。
flash就是用來做一個提示,方便你自己知道你都幹了啥事。

OK,把我們的HTML頁面也說一下。

{% extends 'admin/base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}

{% block navbar %}
    <nav class="navbar navbar-inverse">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Just for fun</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/">Home</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#" data-toggle="dropdown" class="dropdown-toggle">當前用戶名爲:{{ current_user.username }} <b
                            class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="{{ url_for('admin.logout') }}">退出當前賬戶</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
{% endblock %}

{% block page_content %}
    <div class="page-header">
        {{ wtf.quick_form(form) }}
    </div>
{% endblock %}

唯一做出了更改的地方就是 {% block page_content %}這裏,裏面加入了一個表單.
OK,啓動一下我們的項目看看效果。

當然你可能會出現一個SQLAlchemy的異常,如何解決:

$ python3 manage.py shell
>>> from manage import * 
>>> db.drop_all()
>>> db.create_all()
>>> exit()

更新一下我們的數據庫結構,畢竟我們更改了數據庫模型,添加了文章這個模型。
注意哦,每當我們更改了app/models.py這個文件,我們最好都要重新設置一下數據庫.

我們現在已經可以把文章放到數據庫了,現在我們要把數據庫的文章顯示出來。
在這裏,我修改了一下templates/base.html頁面:

{% extends 'bootstrap/base.html' %}

{% block title %}Just for fun{% endblock %}

{% block navbar %}
    <nav class="navbar navbar-inverse" id="top">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Just for fun</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/">Home</a></li>
                </ul>
            </div>
        </div>
    </nav>
{% endblock %}

{% block content %}
    {% for message in get_flashed_messages() %}
        <div class="alert alert-info">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ message }}
        </div>
    {% endfor %}
    <div class="container">
        <div class="col-sm-8">
            {% block page_content %}{% endblock %}
        </div>
        <div class="col-sm-3 col-sm-offset-1">
            {% block slider %}{% endblock %}
        </div>
    </div>
{% endblock %}

只更改了最後,我把

,切成了兩個塊,第一個塊來放文章的內容,第二個塊來放文章目錄。

改完templates/base.html,我們在改一下templates/index.html,這是我們的主頁,總顯示一句話不好看,所以我們改一改。

{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block page_content %}
    <h1>歡迎來到我的blog</h1>
    <p>技術交流羣:630398887</p>
    <hr>
    <div class="row">
        <h2>如下內容湊的字數</h2>
        <hr>
        <h3>登鸛雀樓</h3>
        <p>白日依山盡,黃河入海流。</p>
        <p>欲窮千里目,更上一層樓。</p>
        <hr>
        <h2>論語</h2>
        <p>子謂公冶長:“可妻也,雖在縲紲之中,非其罪也!”以其子妻之。</p>
        <p>子謂南容:“邦有道不廢;邦無道免於刑戮。”以其兄之子妻之。</p>
        <p>子謂子賤:“君子哉若人!魯無君子者,斯焉取斯?”</p>
        <p>子貢問曰:“賜也何如?”子曰:“女器也。”曰:“何器也?”曰:“瑚璉也。”</p>
        <p>或曰:“雍也仁而不佞。”子曰:“焉用佞?御人以口給,屢憎於人。不知其仁,焉用佞?”</p>
        <p>子使漆雕開仕,對曰:“吾斯之未能信。”子說。</p>
        <p>子曰:“道不行,乘桴浮於海,從我者其由與?”子路聞之喜,子曰:“由也好勇過我,無所取材。”</p>
        <p>
            孟武伯問:“子路仁乎?”子曰:“不知也。”又問,子曰:“由也,千乘之國,可使治其賦也,不知其仁也。”“求也何如?”子曰:“求也,千室之邑、百乘之家,可使爲之宰也,不知其仁也。”“赤也何如?”子曰:“赤也,束帶立於朝,可使與賓客言也,不知其仁也。”</p>
        <p>子謂子貢曰:“女與回也孰愈?”對曰:“賜也何敢望回?回也聞一以知十,賜也聞一以知二。”子曰:“弗如也,吾與女弗如也!”</p>
        <p> 宰予晝寢,子曰:“朽木不可雕也,糞土之牆不可杇也,於予與何誅?”子曰:“始吾於人也,聽其言而信其行;今吾於人也,聽其言而觀其行。於予與改是。”</p>
        <p> 子曰:“吾未見剛者。”或對曰:“申棖。”子曰:“棖也欲,焉得剛。”</p>
        <p> 子貢曰:“我不欲人之加諸我也,吾亦欲無加諸人。”子曰:“賜也,非爾所及也。”</p>
        <p> 子貢曰:“夫子之文章,可得而聞也;夫子之言性與天道,不可得而聞也。”</p>
        <p> 子路有聞,未之能行,唯恐有聞。</p>
        <p> 子貢問曰:“孔文子何以謂之文也?”子曰:“敏而好學,不恥下問,是以謂之文也。”</p>
        <p> 子謂子產:“有君子之道四焉:其行己也恭,其事上也敬,其養民也惠,其使民也義。”</p>
        <p> 子曰:“晏平仲善與人交,久而敬之。”</p>
        <p>
            子張問曰:“令尹子文三仕爲令尹,無喜色,三已之無慍色,舊令尹之政必以告新令尹,何如?”子曰:“忠矣。”曰:“仁矣乎?”曰:“未知,焉得仁?”“崔子弒齊君,陳文子有馬十乘,棄而違之。至於他邦,則曰:‘猶吾大夫崔子也。’違之。之一邦,則又曰:‘猶吾大夫崔子也。’違之,何如?”子曰:“清矣。”曰:“仁矣乎?”曰:“未知,焉得仁?”</p>
    </div>
{% endblock %}
{% block slider %}
    <ol class="list-unstyled">
        <li><h2>文章列表</h2></li>
        {% for article in articles %}
            <li><a href="admin/article/{{ article.title }}">{{ article.title }}</a></li>
        {% endfor %}
    </ol>
{% endblock %}

當然,大部分內容去百度複製粘貼的,不過這裏你要看一下這一段代碼。

{% block slider %}
    <ol class="list-unstyled">
        <li><h2>文章列表</h2></li>
        {% for article in articles %}
            <li><a href="admin/article/{{ article.title }}">{{ article.title }}</a></li>
        {% endfor %}
    </ol>
{% endblock %}

我們利用一個for循環,通過視圖函數傳過來的參數,做了一個文章列表,效果如下:

爲了把效果實現出來,我們需要在視圖函數中把參數傳進來,然後讓Jinja2引擎渲染一下。
還記得之前提到Jinja2引擎的時候,它可以想在python裏面一樣可以解析複雜的數據類型,比如咱這個article。

from ..models import Article


@main.route('/', methods=['GET', 'POST'])
def index():
    articles = Article.query.all()
    return render_template('index.html', articles=articles)

也很簡單拉,把所有文章從數據庫獲取一下,傳進去就好了。

能顯示文章列表了,我們需要單獨把文章顯示出來。

<li><a href="admin/article/{{ article.title }}">{{ article.title }}</a></li>

其實阿,這段代碼,是我已經把代碼都寫好了的,因爲這個時候你可能還沒有把相關的html頁面寫好。所以說那個
a標籤中的href屬性可以先不寫,然後等會在寫就好。

app/templates/article.html

{% extends 'base.html' %}

{% block page_content %}
    <div class="page-header"><h1>{{ title }}</h1></div>
    <div class="well">{{ content }}</div>
{% endblock %}

文章的頁面也很簡單,一個標題,一個內容。兩個變量。

再看一下視圖函數:

@main.route('/article/<title>')
def article(title):
    article = Article.query.filter_by(title=title).first()
    return render_template('article.html', title=title, content=article.content)

你看這裏,還記得動態路由麼,這裏用到了動態路由,通過文章的標題來從數據庫把這篇文章數據獲取出來。
然後把標題和文章內容傳參到HTML頁面就可以了。

這個時候,你就可以把app/templates/index.html頁面中那個文章列表的a標籤的href屬性補全了。

這裏說一下,你看啊,我們的功能在不斷的增加,可是基本上都沒有大幅度改動我們的原先的代碼,而是爲新功能寫好代碼,添加進去。這是一個非常好的表現,增加新功能而又不與原先代碼有衝突。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章