期末做品檢查

  1. 我的學期總結
  2. 總結Python+Flask+MysqL的web建設技術過程,標準以下:
    1. 便是對本身所學知識的梳理
    2. 也可做爲初學入門者的簡單教程
    3. 也可做爲本身之後複習的嚮導
    4. 也是一種向外展現能力的途徑

我的學期總結:javascript

    一開始接觸python咱們學的是簡單的輸出輸入交互和一些數字的計算,python語言優勢在於它的簡潔靈活,因此不少時候它都用到符號代替,接着咱們import turtle庫,並繪製出多種多樣的圖形,學習了字符串基本操做,凱撒密碼,自制九九乘法表,中英文詞頻統計等等,雖然語句都挺簡單,但這激發了咱們對學習python的興趣,並提高了咱們對編程語言的思惟能力,有助於下半學期咱們構建Flask框架製做網頁的學習。css

    學習初期第一方面,我認爲學習每一知識點的開始則是瞭解其知識點的概念及基礎。首先則是認識URL,觀察那些經常使用網站的網址,區分它們不一樣組成部分。而後,觀察web的瀏覽過程。最後,最爲重要的則是實操,瞭解HTML基礎並聯系使用標籤製做最簡單的頁面。自行了解各個標籤的用法以及總體標籤的規範。第二方面,認識div塊與form表單的做用,利用div塊與form表單製做登陸頁面。同時,練習使用各類列表,例以下拉列表選擇框、無序列表、有序列表以及定義列表。 觀察經常使用網頁的HTML元素,並在實操過程當中,用已學的標籤模仿製做。經過網絡搜索補充本身所想要的知識點,不要僅僅依賴於課堂。html

    Python語法簡潔清晰,特點之一是強制用空白符(white space)做爲語句縮進。Flask是一個面向簡單需求小型應用的「微框架(microframework)」,Flask選擇組件的額外工做給那些使用案例不適用標準ORM的開發者提供了更多的靈活性,一樣也給使用不一樣工做流和模版化系統的開發者們帶來了靈活性。MySQL是一個關係型數據庫管理系統MySQL 是最流行的關係型數據庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關係數據庫管理系統) 應用軟件。MySQL是一種關係數據庫管理系統,關係數據庫將數據保存在不一樣的表中,而不是將全部數據放在一個大倉庫內,這樣就增長了速度並提升了靈活性。MySQL所使用的 SQL 語言是用於訪問數據庫的最經常使用標準化語言。前端

      製做網頁初期,應制做一個有主題性的導航條。首先認識HTML頭部元素:<base>  定義了頁面連接標籤的默認連接地址;<style>  定義了HTML文檔的樣式文件;<link>  定義了一個文檔和外部資源之間的關係。其次練習樣式表:行內樣式表;內嵌樣式表;外部樣式表。最後分別練習定義三類選擇器:HTML 選擇器;CLASS 類選擇器;ID 選擇器。在進行鏈接時要用到url_for的語句,尤爲是在鏈接圖片時,像這個學期學到的調用兩個父模板,當調用到第二個父模板的時候就會出現圖片調用不過來,這是就要用到url_for的語句。java

      這個學期中的來講仍是蠻有收穫的,學習到了網頁如何製做,怎麼調用圖片,如何運用css來設計style,怎麼經過使用js來設置密碼,用戶名,等等,怎麼使用div,ul,li等等來完善網頁的內容和調整網頁的規模,如何進行模塊分離,如何讓多個數據庫錶鏈接等等。python雖然是一門使用語句比較少的一種程序語言,但咱們仍是亟需多加練習。python

1、使用工具mysql

主要工具備:pycharm64.exe + Python 3.6 64-bit + MySQL + Navicat for MySQL(輔助工具)web

      

 

實現此頁面全部的static文件、templates文件與py文件sql

  

2、頁面設計數據庫

1.導航條(父模板)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}父模板{% endblock %}</title>
    <script src="{{ url_for('static',filename='js/base.js') }}" type="text/javascript"></script>
    <link href="{{ url_for('static' ,filename='css/base.css') }}" rel="stylesheet" type="text/css">
    {% block head %}
    {% endblock %}
</head>
<body id="myBody">
<nav class="body">
    <div style="background-color: floralwhite;top: 0">
        <form action="{{ url_for('search') }}" method="get">
            <img id="imgs" src="{{ url_for('static',filename='images/touxiang.jpg') }}">&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
            <a class="s" href="{{ url_for('index') }}">首頁</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
            <a class="ss" href="{{ url_for('question') }}">發佈問答</a>&nbsp&nbsp&nbsp&nbsp
            <input id="sousuo" type="text" name="q" placeholder="請輸入搜索內容:">
            <button id="sou" type="submit">查找</button>

            {% if username %}
                <a class="login"
                   href="{{ url_for('usercenter',user_id = session.get('userid'),tag=1) }}">{{ session.get('user') }}</a>
                {#            <a class="login" href="#">{{ username }}</a>#}
                <a class="register" href="{{ url_for('logout') }}">註銷</a>
            {% else %}
                <a class="login" href="{{ url_for('login') }}">登陸</a>
                <a class="register" href="{{ url_for('register') }}">註冊</a>
            {% endif %}
            <img id="myOn_Off" onclick="mySwitch()" src="{{ url_for('static',filename='images/taiyang.png') }}" width="50" height="50">
        </form>
    </div>
</nav>
{% block main %}
{% endblock %}
<footer>
    <div class="footer_box">
        Copyright@2017-2027 Create by JZX
    </div>
</footer>
</body>
</html>

 

這裏的界面都爲繼承父模板後的界面.後面將會有相關介紹

2.登陸界面。完成登陸功能:與註冊同樣完成js文件,在主py文件定義函數,讀取表單數據查詢數據庫。當用戶名密碼正確時,記住用戶名並跳轉到首頁;當用戶名密碼不正確時,提示相應錯誤。同時,用session記住用戶名。

@app.route('/login/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(password):
                session['user'] = username
                session['userid'] = user.id
                session.permanent = True
                return redirect(url_for('base'))
            else:
                return 'password error.'
        else:
            return 'username is not existed.'

進入相關的頁面時要先登錄。

# 行動前須要登陸,定義裝飾器
def loginFirst(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if session.get('user'):
            return func(*args, **kwargs)
        else:
            return redirect(url_for('login'))

    return wrapper

3.註冊界面完成註冊功能。在主py文件定義函數,獲取form中的數據且判斷用戶名是否存在:存在報錯,若不存在則存進數據庫中,redirect重定向到登陸頁。

@app.route('/register/', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    else:
        usern = request.form.get('username')
        telep = request.form.get('telephone')
        passw = request.form.get('password')
        user = User.query.filter(User.username == usern).first()
        if user:
            return 'username existed.'
        else:
            user1 = User(username=usern, password=passw, telephone=telep)
            db.session.add(user1)  # 數據庫操做
            db.session.commit()
            return redirect(url_for('login'))

 

定義JavaScript 函數,設置登陸註冊頁面驗證用戶名與登陸密碼6-20位,註冊還需包括驗證用戶名首字母不能是數字,只能包含字母和數字,輸入的兩次密碼必須一致,並在各自html頁面的button標籤onclick調用這個函數。實現js文件,onclick函數return True時才提交表單,return False時不提交表單。

login.html:

{% extends'base.html' %}
{% block title %}
    登陸
{% endblock %}
{% block head %}
    <script src="{{ url_for('static',filename='js/login.js') }}"></script>
    <link rel="stylesheet" href="{{ url_for('static',filename='css/login.css') }}" type="text/css">
{% endblock %}

{% block main %}
    <body>
    <form action="{{ url_for('login') }}" method="post">
        <div class="box">
            <div>
                <a href="{{ url_for('login') }}">登陸</a>
                <a style="color: antiquewhite">*</a>
                <a href="{{ url_for('register') }}">註冊</a>
            </div>
            <br>
            <div class="name" align="center">
                <svg class="iconphone" width="20px" height="20px" viewBox="0 0 20 20">
                    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"
                       sketch:type="MSPage">
                        <g id="2-copy-2" sketch:type="MSArtboardGroup"
                           transform="translate(-505.000000, -357.000000)" fill="#666">
                            <path d="M517.388314,366.868305 C519.068314,366.001784 520.220053,364.252653 520.220053,362.231784 C520.220053,359.350479 517.883966,357.014392 515.002662,357.014392 C512.121357,357.014392 509.78527,359.350479 509.78527,362.231784 C509.78527,364.252653 510.936575,366.001784 512.616575,366.868305 C508.246575,367.938305 505.002662,371.879175 505.002662,376.57961 C505.002662,376.81961 505.197009,377.014392 505.437444,377.014392 C505.677444,377.014392 505.872227,376.81961 505.872227,376.57961 C505.872227,371.537001 509.960053,367.449175 515.002662,367.449175 C520.04527,367.449175 524.133096,371.537001 524.133096,376.57961 C524.133096,376.81961 524.327444,377.014392 524.567879,377.014392 C524.807879,377.014392 525.002662,376.81961 525.002662,376.57961 C525.002662,371.879175 521.758749,367.938305 517.388314,366.868305 L517.388314,366.868305 Z M510.654835,362.231784 C510.654835,359.830479 512.601357,357.883957 515.002662,357.883957 C517.403966,357.883957 519.350488,359.830479 519.350488,362.231784 C519.350488,364.632653 517.403966,366.57961 515.002662,366.57961 C512.601357,366.57961 510.654835,364.632653 510.654835,362.231784 L510.654835,362.231784 Z"
                                  id="id" sketch:type="MSShapeGroup"></path>
                        </g>
                    </g>
                </svg>
                <input
                        id="uname" type="text" placeholder="請輸入用戶名:" name="username">

            </div>
            <br>
            <div class="email" align="center">
                <svg class="iconphone" width="20px" height="20px" viewBox="0 0 20 20">
                    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"
                       sketch:type="MSPage">
                        <g id="2-copy-2" sketch:type="MSArtboardGroup"
                           transform="translate(-505.000000, -407.000000)" fill="#666">
                            <path d="M515,418.304324 C514.12782,418.304324 513.421091,418.888119 513.421091,419.608723 C513.421091,419.995004 513.624357,420.341947 513.947394,420.580774 L513.947394,421.782554 C513.947394,422.262857 514.418637,422.652187 515.00003,422.652187 C515.581302,422.652187 516.052667,422.262857 516.052667,421.782554 L516.052667,420.580774 C516.375703,420.341947 516.579,419.995004 516.579,419.608723 C516.57897,418.888119 515.87221,418.304324 515,418.304324 L515,418.304324 L515,418.304324 Z M522.368454,414.391327 L521.315788,414.391327 L521.315788,412.217421 C521.315788,409.335657 518.488418,407 515,407 C511.511582,407 508.684212,409.335657 508.684212,412.217421 L508.684212,414.391327 L507.631576,414.391327 C506.178003,414.391327 505,415.364503 505,416.565234 L505,424.826193 C505,426.026824 506.178003,427 507.631576,427 L522.368424,427 C523.821422,427 525,426.026899 525,424.826193 L525,416.565234 C525.00003,415.364478 523.821422,414.391327 522.368454,414.391327 L522.368454,414.391327 L522.368454,414.391327 Z M515,407.869583 C517.906571,407.869583 520.263152,409.816309 520.263152,412.217396 L520.263152,414.391302 L509.737544,414.391302 L509.737544,412.217396 L509.736848,412.217396 C509.736848,409.816309 512.093459,407.869583 515,407.869583 L515,407.869583 L515,407.869583 Z M523.947364,424.826093 C523.947364,425.546622 523.240604,426.130392 522.368454,426.130392 L507.631606,426.130392 C506.759396,426.130392 506.052667,425.546622 506.052667,424.826093 L506.052667,416.565234 C506.052667,415.84468 506.759426,415.260835 507.631606,415.260835 L522.368454,415.260835 C523.240635,415.260835 523.947364,415.844705 523.947364,416.565234 L523.947364,424.826093 L523.947364,424.826093 L523.947364,424.826093 Z"
                                  id="pw" sketch:type="MSShapeGroup"></path>
                        </g>
                    </g>
                </svg>
                <input
                        type="password" id="upass" placeholder="請輸入密碼:" name="password">

            </div>
            <br>

            <div>
                <div id="error_box"></div>
                <button id="login" onclick=" return myLogin()">登陸</button>

            </div>
            <br>

            <div>
                <input value="1" name="remember" id="remember" type="checkbox">
                <label for="remember" style="color: darkmagenta">保存登陸信息</label>&nbsp;&nbsp;&nbsp;&nbsp;
                <input value="2" name="remember" id="remember" type="checkbox">
                <label for="remember" style="color: darkmagenta">記住我</label>
            </div>

            <br>
            <a class="register-login" href="{{ url_for('register') }}">進入註冊界面</a>

            <div id="footer" style="background-color: transparent;clear:both;text-align:center;">版權 . duym@jzx</div>

        </div>
        <script>
            document.getElementById("demo").innerHTML = Date();
            document.write(Date())
        </script>
    </form>
    </body>
{% endblock %}

 

login.js:

function myLogin() {
    var oUname = document.getElementById("uname");
    var oUpass = document.getElementById("upass");
    var oError = document.getElementById("error_box");
    var isError = true;
    oError.innerHTML = "<br>";

    //uname
    if (oUname.value.length > 20 || oUname.value.length < 6) {
        oError.innerHTML = "用戶名:6至20位。";
        isError = false;
        return isError;
    } else if ((oUname.value.charCodeAt(0) >= 48) && (oUname.value.charCodeAt(0) <= 57)) {
        oError.innerHTML = "首字母不能爲數字。";
        isError = false;
        return isError;
    } else for (var i = 0; i < oUname.value.length; i++) {
        if ((oUname.value.charCodeAt(i) < 48 || oUname.value.charCodeAt(i) > 57) && (oUname.value.charCodeAt(i) < 97 || oUname.value.charCodeAt(i) > 122)) {
            oError.innerHTML = "只能是字母或者數字。";
            isError = false;
            return isError;
        }

    }
    //upass
    if (oUpass.value.length > 20 || oUpass.value.length < 6) {
        oError.innerHTML = "密碼爲6到20位。";
        isError = false;
        return isError;
    }
return isError;
    //window.alert("登陸成功!!");

}

register.html:

{% extends'base.html' %}
{% block title %}
    註冊
{% endblock %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/register.css') }}" type="text/css">
    <script src="{{url_for('static',filename='js/register.js') }}"></script>
{% endblock %}
{% block main %}

    <body>
    <form action="{{ url_for('register') }}" method="post">
    <div class="box">
        <div>
            <a href="{{ url_for('login') }}">登陸</a>
            <a style="color: antiquewhite">*</a>
            <a href="{{ url_for('register') }}">註冊</a>
        </div>
        <br>

        <div class="name" align="center">
            <input id="uname" type="text" placeholder="登陸帳號:" name="username">
        </div>
        <br>
        <div class="telephone" align="center">

            <input type="tel"
                   id="uuser"
                   placeholder="請輸入你的手機號:" name="telephone">
        </div>
        <br>

        <div class="email" align="center">
            <input
                    type="password" id="upass" placeholder="設置你的密碼:"name="password">
        </div>
        <br>
        <div class="email" align="center">
            <input
                    type="password" id="upass2" placeholder="請輸入你的密碼:"name="password">
        </div>
        <br>
        <div>
            <div id="error_box"></div>
            <div>
                <button id="register" onclick=" return myRegister()">註冊</button>

            </div>
            <a class="login-register" href="{{ url_for('login') }}">進入登陸界面</a>


            <div id="footer" style="background-color: transparent;clear:both;text-align:center;">版權 . duym@jzx</div>
        </div>
    </div>
    </form>
    </body>

{% endblock %}

 

register.js:

function myRegister() {
    var oUname = document.getElementById("uname");
    var oUpass = document.getElementById("upass");
    var oError = document.getElementById("error_box");
    var oUuser = document.getElementById("uuser");
    var oUpass2 = document.getElementById("upass2");
    var isError = true;

    oError.innerHTML = "<br>";
    //uname
    if (oUname.value.length > 20 || oUname.value.length < 6) {
        oError.innerHTML = "用戶名:6至20位。";
        isError = false;
        return isError;
    } else if ((oUname.value.charCodeAt(0) >= 48) && (oUname.value.charCodeAt(0) <= 57)) {
        oError.innerHTML = "首字母不能爲數字。";
        isError = false;
        return isError;
    } else for (var i = 0; i < oUname.value.length; i++) {
        if ((oUname.value.charCodeAt(i) < 48 || oUname.value.charCodeAt(i) > 57) && (oUname.value.charCodeAt(i) < 97 || oUname.value.charCodeAt(i) > 122)) {
            oError.innerHTML = "暱稱只能是字母或者數字。";
            isError = false;
            return isError;
        }
    }
    for (var i = 0; i < 12; i++) {
        if (((oUuser.value.charCodeAt(i) < 48) || (oUuser.value.charCodeAt(i) > 57)) || oUuser.value.length != 11) {
            oError.innerHTML = "請輸入正確手機號";
            isError = false;
            return isError;
        }
    }

    //upass
    if (oUpass.value.length > 20 || oUpass.value.length < 6) {
        document.getElementById('error_box').innerHTML = "密碼必須在6-20個字符之間";
        isError = false;
        return isError;
    }
    if (oUpass2.value != oUpass.value) {
        oError.innerHTML = "兩次輸入的密碼必須一致";
        isError = false;
        return isError;
    }
    return isError
    window.alert("註冊成功!!");

}

4.發佈問答界面

detail.html:

{% extends'base.html' %}
{% block title %}
    問答詳情
{% endblock %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/detail.css') }}" type="text/css">
{% endblock %}
{% block main %}
    <body id="myBody">
    <div class="total">
        <div class="page-header" style="text-align: left">
            <h3 style="font-family: 楷體;color: cornflowerblue;">{{ ques.title }}<br>
                <small>讀者:{{ ques.author.username }}&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<span
                        class="badge"
                        style="border: hidden;border-radius: 0px">{{ ques.creat_time }}</span>
                </small>
            </h3>
            <hr>
        </div>
        <p class="lead">{{ ques.detail }}</p>
        <hr>
        <form method="post" action="{{ url_for('comment') }}">
            <div class="form-group" style="text-align: left">
                <textarea name="new_comment" class="form-control" rows="3" placeholder="Write your comment"
                          id="new_comment"></textarea>
                <input name="question_id" type="hidden" value="{{ ques.id }}"/>
            </div>
            <button type="submit" class="btn btn-default" style="border-radius: inherit;font-family: 幼圓">發送</button>
        </form>


        <h3 style="text-align: left">評論:({{ ques.comments|length }})</h3>
        <ul class="list-group">
            {% for foo in ques.comments %}
                <li class="list-group-item">
                    <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
                    <br>
                    <a href="{{ url_for('usercenter',user_id = ques.author.id,tag=1) }}" style="font-family: 楷體;color: cornflowerblue;text-align: left">做者:{{ foo.author.username }}</a>&nbsp&nbsp&nbsp
                    <span class="badge"
                          style="font-family: 楷體;color: cornflowerblue;text-align: right">評論時間:{{ foo.creat_time }}</span>
                    <p style="text-align: left;font-family: 楷體;color: cornflowerblue">{{ foo.detail }}
                    </p>
                </li>
            {% endfor %}
        </ul>
    </div>
    </body>
    </html>
{% endblock %}

 

四、夜間模式的開啓與關閉。定義script開關切換函數,用onclick函數進行調用。

 

<img id="myOn_Off" onclick="mySwitch()" src="{{ url_for('static',filename='images/taiyang.png') }}" width="50" height="50">

 

function mySwitch() {
            var myele=document.getElementById("myOn_Off");
            if(myele.src.match("taiyang")){
                myele.src="../static/images/yuliang.jpg";
                document.getElementById("myBody").style.background="gray";
                document.getElementById("demo").style.color="white";
            }else {
                myele.src = "../static/images/taiyang.png";
                document.getElementById("myBody").style.background = "white";
                document.getElementById("demo").style.color = "gray" ;
            }
        }

 

 

五、實現登陸後更新導航:用上下文處理器app_context_processor定義函數,獲取session中保存的值,返回字典。在父模板中更新導航,插入登陸狀態判斷代碼。注意用{% ... %}表示指令、{{ }}表示變量。完成註銷功能:清除session並進行跳轉頁面。

@app.context_processor
def mycontext():
    usern = session.get('user')
    if usern:
        return {'username': usern}
    else:
        return {}


@app.route('/logout/')
def logout():
    session.clear()
    return redirect(url_for('base'))

六、編寫要求登陸的裝飾器,定義函數將其返回。應用裝飾器,要求在發佈前進行登陸,登陸後可發佈。創建發佈內容的對象關係映射,完成發佈函數。

 

七、在首頁添加顯示問答的列表,並定義好相應的CSS樣式。首頁列表顯示所有問答:將數據庫查詢結果傳遞到前端頁面,前端頁面循環顯示整個列表,進行問答排序。

 

{% extends'base.html' %}
{% block title %}
    首頁
{% endblock %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}" type="text/css">
{% endblock %}
{% block main %}
    <body id="myBody">
    <div class="indexone">
        {#    <img src="{{ url_for('static',filename = 'images/heben.jepg' }} alt='qa'">#}
        <ul class="list-group">
            {% for foo in questions %}
                <li class="list-group-item">
                    <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                    <a href="#" style="font-family: 幼圓;color: crimson">讀者:{{ foo.author.username }}</a><br>
                    <a href="{{ url_for('detail',question_id = foo.id) }}"
                       style="font-family: 幼圓;color: crimson">{{ foo.title }}</a><br>
                    <span class="badge" style="font-family: 幼圓;color: crimson">發佈時間:{{ foo.creat_time }}</span><br>
                    <p class="container" style="font-family: 幼圓;color: #002D54;">{{ foo.detail }}</p>
                    <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                    <a href="{{ url_for('usercenter',user_id = foo.author_id,tag=1) }}">{{ foo.author.username }}評論({{ foo.comments|length }})</a>
                    <div class="meta">
                        <a class="collection-tag">
                            <span style="font-family: 幼圓">社會熱點</span>
                        </a>
                        <a class="collection-tag">
                            <span style="font-family: 幼圓"> 瀏覽: </span><span
                                style="font-family: 幼圓;color: red"> 555 </span>
                        </a>
                        <a class="collection-tag">
                            <span style="font-family: 幼圓"> 評論: </span><span
                                style="font-family: 幼圓;color: red"> 890 </span>
                        </a>
                        <span style="font-family: 幼圓"> 點贊: </span><span
                            style="font-family: 幼圓;color: red"> 1234 </span>
                    </div>
                </li>
            {% endfor %}
        </ul>
    </div>

    </body>
    </html>
{% endblock %}

 

@app.route('/detail/<question_id>')
@loginFirst
def detail(question_id):
    quest = Question.query.filter(Question.id == question_id).first()
    return render_template('detail.html', ques=quest)

 

@app.route('/question/', methods=['GET', 'POST'])
@loginFirst  # 把loginFirst放在要登陸才能進入的界面中
def question():
    if request.method == 'GET':
        return render_template('question.html')
    else:
        title = request.form.get('title')
        detail = request.form.get('detail')
        author_id = User.query.filter(User.username == session.get('user')).first().id
        question = Question(title=title, detail=detail, author_id=author_id)
        db.session.add(question)  # 數據庫,添加操做
        db.session.commit()
    return redirect(url_for('base'))

 

八、主PY文件寫視圖函數,帶id參數。 首頁標題的標籤作帶參數的連接,在詳情頁將數據的顯示在恰當的位置。創建評論的對象關係映射,嘗試實現發佈評論。 

完成評論功能:定義評論的視圖函數,讀取前端頁面數據,保存到數據庫中 ,顯示評論次數,要求評論前登陸(調用登陸裝飾器),嘗試實現詳情頁面下的評論列表顯示。

 

{% extends'base.html' %}
{% block title %}
    問答詳情
{% endblock %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/detail.css') }}" type="text/css">
{% endblock %}
{% block main %}
    <body id="myBody">
    <div class="total">
        <div class="page-header" style="text-align: left">
            <h3 style="font-family: 楷體;color: cornflowerblue;"><a href="{{ url_for('usercenter',user_id=ques.author_id,tag=3) }}">{{ ques.title }}</a><br>
                <small><a href="{{ url_for('usercenter',user_id=ques.author_id,tag=3) }}">讀者:{{ ques.author.username }}&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<span
                        class="badge"
                        style="border: hidden;border-radius: 0px">{{ ques.creat_time }}</span>
                </a></small>
            </h3>
            <hr>
        </div>
        <p class="lead">{{ ques.detail }}</p>
        <hr>
        <form method="post" action="{{ url_for('comment') }}">
            <div class="form-group" style="text-align: left">
                <textarea name="new_comment" class="form-control" rows="3" placeholder="Write your comment"
                          id="new_comment"></textarea>
                <input name="question_id" type="hidden" value="{{ ques.id }}"/>
            </div>
            <button type="submit" class="btn btn-default" style="border-radius: inherit;font-family: 幼圓">發送</button>
        </form>


        <h3 style="text-align: left">評論:({{ ques.comments|length }})</h3>
        <ul class="list-group">
            {% for foo in ques.comments %}
                <li class="list-group-item">
                    <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
                    <br>
                    <a href="{{ url_for('usercenter',user_id = ques.author.id,tag=1) }}" style="font-family: 楷體;color: cornflowerblue;text-align: left">做者:{{ foo.author.username }}</a>&nbsp&nbsp&nbsp
                    <span class="badge"
                          style="font-family: 楷體;color: cornflowerblue;text-align: right">評論時間:{{ foo.creat_time }}</span>
                    <p style="text-align: left;font-family: 楷體;color: cornflowerblue">{{ foo.detail }}
                    </p>
                </li>
            {% endfor %}
        </ul>
    </div>
    </body>
    </html>
{% endblock %}

 

@app.route('/comment/', methods=['POST'])
@loginFirst  # 把loginFirst放在要登陸才能進入的界面中
def comment():
    comment = request.form.get('new_comment')
    ques_id = request.form.get('question_id')
    auth_id = User.query.filter(User.username == session.get('user')).first().id
    comm = Comment(author_id=auth_id, question_id=ques_id, detail=comment)
    db.session.add(comm)  # 數據庫,添加操做
    db.session.commit()
    return redirect(url_for('detail', question_id=ques_id))

九、實現評論列表顯示及排序。完成我的中心:我的中心的頁面佈局(html文件及相應的樣式文件),定義視圖函數向前端頁面傳遞參數,頁面顯示相應數據:發佈的所有問答、發佈的所有評論、我的信息;各個頁面連接到我的中心。

實現標籤頁導航:利用嵌套繼承,製做我的中心的三個子頁面,重寫userbase.html中定義的user塊,分別用於顯示問答、評論、我的信息。我的中心—視圖函數、導航標籤與HTML頁面連接增長tag參數。

@app.route('/usercenter/<user_id>/<tag>')
@loginFirst
def usercenter(user_id, tag):
    user = User.query.filter(User.id == user_id).first()
    mycontext = {
        'user': user,
    }
    if tag == '1':
        return render_template('user1.html', **mycontext)
    elif tag == '2':
        return render_template('user2.html', **mycontext)
    else:
        return render_template('user3.html', **mycontext)
{% extends'base.html' %}
{% block title %}
    我的中心
{% endblock %}

{% block head %}
{% endblock %}

{% block main %}
    <body id="myBody">
    <ul class="nav">
        <li role="presentation"><a href={{ url_for('usercenter',user_id=user.id,tag='1') }} >所有問答</a></li>
        <li role="presentation"><a href={{ url_for('usercenter',user_id=user.id,tag='2') }}>所有評論</a></li>
        <li role="presentation"><a href={{ url_for('usercenter',user_id=user.id,tag='3') }}>我的信息</a></li>
    </ul>
    {% block user %}

    {% endblock %}
    </body>
    </html>
{% endblock %}

 user1.html:

{% extends'userbase.html' %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/user.css') }}" type="text/css">
{% endblock %}
{% block user %}
    <body id="myBody">
    <div class="total">
        <div class="page-header" style="text-align: left">
            <h3 style="font-family: 楷體;color: cornflowerblue;width:100px"><span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>{{ username }}<br>
                <small>所有問答<span class="badge"></span></small>
            </h3>
            <ul class="list-group">
                {% for foo in user.question %}
                    <li class="list-group-item">
                        <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                        <a href="#" style="font-family: 幼圓;color: cornflowerblue">讀者:{{ foo.author.username }}</a><br>
                        <span class="badge"
                              style="font-family: 幼圓;color: cornflowerblue">發佈時間:{{ foo.creat_time }}</span><br>
                        <p style="font-family: 幼圓;color: #002D54;">{{ foo.detail }}</p>
                    </li>
                {% endfor %}
            </ul>

        </div>
    </div>
    </body>
{% endblock %}

 user2.html:

{% extends'userbase.html' %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/user.css') }}" type="text/css">
{% endblock %}
{% block user %}
    <body id="myBody">
    <div class="total">
        <div class="page-header" style="text-align: left">
            <h3 style="font-family: 楷體;color: cornflowerblue;width:100px"><span class="glyphicon glyphicon-leaf"
                                                              aria-hidden="true"></span>{{ username }}<br>
                <small>所有評論<span class="badge"></span></small>
            </h3>
            <ul class="list-group">
                {% for foo in user.comments %}
                    <li class="list-group-item">
                        <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                        <a href="#" style="font-family: 幼圓;color: cornflowerblue">讀者:{{ foo.author.username }}</a><br>
                        <span class="badge"
                              style="font-family: 幼圓;color: cornflowerblue">發佈時間:{{ foo.creat_time }}</span><br>
                        <p style="font-family: 幼圓;color: #002D54;">{{ foo.detail }}</p>
                    </li>
                {% endfor %}
            </ul>
        </div>
    </div>
    </body>
{% endblock %}

 user3.html:

{% extends'userbase.html' %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static',filename='css/user.css') }}" type="text/css">
{% endblock %}
{% block user %}
    <body id="myBody">
    <div class="total">
        <div class="page-header" style="text-align: left">
            <h3 style="font-family: 楷體;color: cornflowerblue;width:100px"><span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>{{ username }}<br>
                <small>我的信息<span class="badge"></span></small>
            </h3>
            <ul class="list-group" style="font-family: 幼圓;color: #002D54;">
                <li class="list-group-item">用戶:{{ user.username }}</li>
                <li class="list-group-item">編號:{{ user.id }}</li>
                <li class="list-group-item">文章篇:{{ user.question|length }}</li>
                <li class="list-group-item">評論數:{{ user.comments|length }}</li>
            </ul>
        </div>
    </div>
    </body>
{% endblock %}

十、實現搜索功能:準備視圖函數search(),修改父模版中搜索輸入框所在的;完成視圖函數獲取搜索關鍵字,條件查詢並加載查詢結果,實現組合條件查詢。

 

@app.route('/search/')
def search():
    qu = request.args.get('q')
    ques = Question.query.filter(
        or_(
            Question.title.contains(qu),
            Question.detail.contains(qu)
        )
    ).order_by('-creat_time')
    return render_template('index.html', questions=ques)

 十一、最後實現密碼保護功能。

    @property
    def password(self):#外部使用
        return self._password

    @password.setter
    def password(self,row_password):
        self._password = generate_password_hash(row_password)

    def check_password(self,row_password):
        result = check_password_hash(self._password,row_password)
        return result

配置連接數據庫信息,創建mysql和app的鏈接,建立用戶模型。經過用戶模型,學習對數據庫進行增刪改查操做。

import os
SECRET_KEY = os.urandom(24)
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/mis?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False

3、加載靜態文件,父模板與其餘界面的繼承

 1.登錄用url_for加載靜態文件

  1.<script src="{{ url_for('static',filename='js/login.js') }}"></script>

  2.flask 從static文件夾開始尋找

  3.可用於加載css, js, image文件

2.繼承和擴展

  1.把一些公共的代碼放在父模板中,避免每一個模板寫一樣的內容。base.html

  2.子模板繼承父模板 {% extends 'base.html’ %}

3.父模板提早定義好子模板能夠實現一些本身需求的位置及名稱。block

  1.<title>{% block title %}{% endblock %}-MIS問答平臺</title>

  2.{% block head %}{% endblock %}

  3.{% block main %}{% endblock %}

4.子模板中寫代碼實現本身的需求。block 

   {% block title %}登陸{% endblock %}

4、數據庫

一、數據庫工具:mysql

二、創建mysql和app的鏈接(模塊分離後的)

from datetime import datetime
from werkzeug.security import generate_password_hash,check_password_hash
from exts import db

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(20), nullable=False)
    _password = db.Column(db.String(200), nullable=False)#內部使用
    telephone = db.Column(db.String(11), nullable=False)


    @property
    def password(self):#外部使用
        return self._password

    @password.setter
    def password(self,row_password):
        self._password = generate_password_hash(row_password)

    def check_password(self,row_password):
        result = check_password_hash(self._password,row_password)
        return result

class Question(db.Model):
    __tablename__ = 'question'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    detail = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    author = db.relationship('User', backref=db.backref('question'))  # 這個不會在表單裏面出現,只是與user創建一個映射關係

class Comment(db.Model):
    __tablename__ = 'comment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    question_id = db.Column(db.Integer, db.ForeignKey('question.id'))
    detail = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)
    question = db.relationship('Question', backref=db.backref('comments'))
    author = db.relationship('User', backref=db.backref('comments'))

三、經過用戶模型,對數據庫進行增刪改查

增長數據

user=User(username = 'mis1234',password = '111111',telephone = '12345678900')
db.session.add(user)
db.session.commit()

查詢數據

user=User.query.filter(user.username == 'mis1234').first()
print(user.username,user.password)


修改數據
user=User.query.filter(user.username == 'mis1234').first()
user.password = '000000'
db.session.commit()

刪除數據
user=User.query.filter(user.username == 'mis1234').first()
db.session.delete(user)
db.session.commit()

以上就是這個學期完成的登陸、註冊、發佈問答等簡單功能的基本項目系統。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息