1、我的學期總結javascript
這學期剛開始接觸到python,python的簡潔,以及豐富的模塊,廣闊的應用領域吸引了我。學習python以來,以爲python仍是比較簡單,容易上手的,就基本語法而言,可是有些高級特性掌握起來仍是有些難度,須要時間去消化。python給我最大的印象就是語法簡潔,就像寫僞代碼同樣,不少其餘語言要用不少行才能實現的操做python可能幾行就搞定了,這讓人擺脫了繁雜的語法而專一於問題自己,這也正是我爲何不太喜歡Java的緣由之一,雖然它很強大。css
剛開始學習不少疑惑,到底該如何學python,該從何下手?我回想了一下,根據本身的我的經驗,總結了一下。首先,學習一門語言,語言基礎很重要,咱們須要瞭解該語言的特性,以及全部的語法規則,關鍵詞等內容,因此,咱們須要先把python基礎過一遍,我建議去菜鳥教程去過一遍,這裏不是廣告,只是本人通常都在菜鳥官方看各類語言的編程入門。在基礎學習的過程當中,我建議快速的過一遍,把能理解的理解消化掉,比較難理解的不要浪費太多的時間去揣摩,由於有些語法或者特性在基礎學習中根本不能很好的展現,沒有實際操做單靠文字描述,是很難理解,死記硬背下來的東西不利於長期記憶和使用,因此快速瀏覽一遍,真正的學習放到後面的模塊學習和項目實戰,在模塊學習和實戰操做中能看到實實在在的執行效果,更利於理解。html
總的來講,這個學期學習到了這麼有趣的網頁製做,不過如今本人的經驗仍是匱乏,只是學習到簡單的基礎知識,還應該繼續增強學習,讓本身的網頁佈局更加美化。在這裏還要感謝老師這一學期的指導,讓咱們瞭解到python的奧妙。前端
2、總結Python+Flask+MysqL的web建設技術過程java
(1)主py 文件所需庫python
from flask import Flask,render_template,request,redirect,url_for,session from flask_sqlalchemy import SQLAlchemy from datetime import datetime from functools import wraps import config from sqlalchemy import or_ from werkzeug.security import generate_password_hash,check_password_hash
(2)建立數據庫mysql
A、數據庫鏈接,建立數據庫,配置連接數據庫信息,創建mysql和app的鏈接。web
import os SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/mis_db?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False SECRET_KEY = os.urandom(24)
app = Flask(__name__) app.config.from_object(config) db = SQLAlchemy(app)
B、建立用戶模型。sql
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) nickname = db.Column(db.String(20)) @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): __table__name = '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')) 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')) #db.create_all()
C、經過用戶模型,學習對數據庫進行增刪改查操做。數據庫
#增 user = User(username='su0001',password='123456') db.session.add(user) db.session.commit() #改 user=User.query.filter(User.username=='su0002').first() user.password='1234567' db.session.commit() #刪 user=User.query.filter(User.username=='su0002').first() db.session.delete(user) db.session.commit() #查 user=User.query.filter(User.username=='su0001').first() print(user.id,user.password)
#增、改
#刪、查
D、實現密碼保護功能
(3)頁面設計
A、網站父模板統一佈局:頭部導航條、底部圖片導航、中間主顯示區域佈局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}Title</title> <link rel="stylesheet"type="text/css"href="{{ url_for('static',filename='css/base.css') }}"> <script src="{{ url_for('static',filename='js/base.js') }}"></script> <base target="_blank" /> {% block head %}{% endblock %} </head> <body background="http://p0.so.qhimgs1.com/t01d2e82c8c8f2be36c.jpg" id="myBody"> <nav class="nav"> <ul> <li><a href="{{ url_for('index') }}"><img src="../static/images/img1.png">首頁</a></li> <li><a href=""><img src="../static/images/img2.png">下載</a></li> <li><a href="{{ url_for('question') }}"><img src="../static/images/img5.png">發佈問答</a></li> <div> {% if user %} <li><a href="{{ url_for('userbase',user_id = session.get('userid'),tag = 1) }}"><img src="../static/images/img3.png">{{ session.get('user') }}</a></li> <li><a href="{{ url_for('logout') }}"><img src="../static/images/img4.png">註銷</a></li> {% else %} <li><a href="{{ url_for('login') }}"><img src="../static/images/img3.png">登陸</a></li> <li><a href="{{ url_for('regist') }}"><img src="../static/images/img4.png">註冊</a></li> {% endif %} </div> <form action="{{ url_for('search') }}" method="get" class="navbar-form navbar-left"> <img class="on_off" id="on_off" onclick="mySwitch()" src="../static/images/pic_bulbon.gif" width="50px"> <button style="float: right;margin: 5px auto;border-radius: 5px;height: 26px" type="submit"><span class="glyphicon glyphicon-search" aria-hidden="true"></span>搜索</button> <input style="float: right;margin: 5px auto;border-radius: 8px;width: 200px;height: 20px;" type="text"name="q" placeholder="輸入請關鍵字"> </form> </ul> </nav> <div id="bottom"> <a href="">關於咱們</a> <a href="">意見反饋</a> <a href="">安全保障</a> </div> <div class="copyright"> <p>Copyright © 2017. Created by <a href="#" target="_blank">suxihong</a></p> </div> {% block main %}{% endblock %} </body> </html>
夜間模式的開啓與關閉。定義script開關切換函數,用onclick函數進行調用。
B、註冊、登陸、註銷py文件:
註冊界面完成註冊功能。在主py文件定義函數,獲取form中的數據且判斷用戶名是否存在:存在報錯,若不存在則存進數據庫中,redirect重定向到登陸頁。
登陸界面。完成登陸功能:與註冊同樣完成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') password1 = request.form.get('password') user = User.query.filter(User.username == username).first() if user: if user.check_password(password1): session['user'] = username session['userid'] = user.id session.permanent = True return redirect(url_for('index')) else: return 'password error' else: return 'username error' #註冊函數 @app.route('/regist/',methods=['GET','POST']) def regist(): if request.method == 'GET': return render_template('regist.html') else: username = request.form.get('username') nickname = request.form.get('nickname') password = request.form.get('password') user = User.query.filter(User.username == username).first() if user: return 'username existed.' else: user = User(username=username,password=password,nickname=nickname) db.session.add(user) db.session.commit() return redirect(url_for('login')) #註銷函數 @app.route('/logout') def logout(): session.clear() return redirect(url_for('index')) # 行動前須要登陸,定義裝飾器 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
定義JavaScript 函數,設置登陸註冊頁面驗證用戶名與登陸密碼6-20位,註冊還需包括驗證用戶名首字母不能是數字,只能包含字母和數字,輸入的兩次密碼必須一致,並在各自html頁面的button標籤onclick調用這個函數。實現js文件,onclick函數return True時才提交表單,return False時不提交表單。
1)regist.html
{% extends 'base.html' %} {% block title %}Regist{% endblock %} {% block head %} <link href="{{ url_for('static',filename='css/js31.css') }}" rel="stylesheet" type="text/css"> <script src="{{ url_for('static',filename='js/regist.js') }}"></script> {% endblock %} {% block main %} <div class="box"> <h2>註冊頁面</h2> <form action="{{ url_for('regist') }}" method="post"> <div class="input_box"> 輸入用戶名: <input id="uname" type="text" placeholder="請輸入用戶名" name="username"></div> <div class="input_box"> 暱稱:<input id="unickname" type="text" placeholder="暱稱" name="nickname"> </div> <div class="input_box"> 輸入密碼: <input id="upass" type="password" placeholder="請輸入密碼" name="password"></div> <div class="input_box"> 確認密碼: <input id="checkpass" type="password" placeholder="請確認密碼"> </div> <div id="error_box"><br></div> <div class="input_box"> <button onclick="fnRegist()">註冊</button> <button onclick=window.alert("此頁面詢問您是否要離開:您輸入的數據可能不會被保存")>取消</button></div> </form> </div> {% endblock %}
rejist.js
function fnRegist() { var oPass=document.getElementById("upass").value; var oPass1=document.getElementById("checkpass").value; if(oPass!=oPass1){ document.getElementById("error_box").innerHTML="兩次密碼不一致!"; return false; } return true; }
2)login.html
{% extends 'base.html' %} {% block title %}歡迎您的登陸{% endblock %} {% block head %} <link href="{{ url_for('static',filename='css/js31.css') }}" rel="stylesheet" type="text/css"> <script src="{{ url_for('static',filename='js/login.js') }}"></script> {% endblock %} {% block main %} <div class="box"> <h2>登陸頁面</h2> <form action="{{ url_for('login') }}" method="post"> <div class="input_box"> 用戶名: <input id="uname" name="username" type="text" placeholder="請輸入用戶名"> </div> <div class="input_box"> 密碼: <input id="upass" name="password" type="password" placeholder="請輸入密碼"> </div> <div id="error_box"><br></div> <div class="input_box"> <button onclick="return fnLogin()">登陸</button> <button onclick=window.alert("此頁面詢問您是否要離開:您輸入的數據可能不會被保存")>取消</button></div> </form> </div> {% endblock %}
login.js
function fnLogin() { var oUname=document.getElementById("uname"); var oUpass=document.getElementById("upass"); var oError=document.getElementById("error_box"); var isError=true; oError.innerHTML="<br>"; if(oUname.value.length<6||oUname.value.length>20){ 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 = "只能包含字母或數字。"; isNotError = false; return isError; } } } if (oUpass.value.length<6||oUpass.value.length>20){ oError.innerHTML="密碼的長度:6-20位"; isError=false; return isError; } return isError; }
實現登陸後更新導航:用上下文處理器app_context_processor定義函數,獲取session中保存的值,返回字典。在父模板中更新導航,插入登陸狀態判斷代碼。注意用{% ... %}表示指令、{{ }}表示變量。完成註銷功能:清除session並進行跳轉頁面。
@app.context_processor def mycontext(): user = session.get('user') if user: return {'user': user} else: return {}
C、發佈、列表顯示
1)發佈問答界面、編寫要求登陸的裝飾器,定義函數將其返回。應用裝飾器,要求在發佈前進行登陸,登陸後可發佈。創建發佈內容的對象關係映射,完成發佈函數。
@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') user = User.query.filter(User.username == session.get('user')).first() author_id = user.id question = Question.query.filter(Question.title == title).first() if question: return 'question existed.' else: question = Question(title=title, detail=detail, author_id=author_id) question.author = user db.session.add(question) # 數據庫,添加操做 db.session.commit() return redirect(url_for('index'))
question.html
{% extends 'base.html' %} {% block title %}發佈問答{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/question.css')}}"> {% endblock %} {% block main %} <div class="question"> <p class="name">歡迎你,{{ user }}</p> <h3>發佈問答</h3> <form class="box" action="{{ url_for('question') }}" method="post" > <div class="form-group"> <label for="questionTitle">標題</label> <input type="text" name="title" class="form-control" id="questionTitle" placeholder="輸入標題"> </div> <div class="form-group"> <label for="questionDetail">詳情</label> <textarea name="detail" class="form-control" rows="5" id="questionDetail" placeholder="輸入內容"></textarea> </div> <div class="checkbox"> <label> <input type="checkbox">Check me out </label> </div> <button type="submit" class="btn-default">發佈</button> </form> </div> {% endblock %}
2)在首頁添加顯示問答的列表,並定義好相應的CSS樣式。首頁列表顯示所有問答:將數據庫查詢結果傳遞到前端頁面,前端頁面循環顯示整個列表,進行問答排序。
@app.route('/') def index(): context = { 'question': Question.query.order_by('-creat_time').all() } return render_template('index.html',**context)
index.html
{% 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 %} <p>{{ user }}歡迎您來到首頁!</p> <div class="list-container"> <div id="content"> <ul class="note-list" style="list-style: none"> {% for foo in question %} <li class="note-list-item"> <span class="glyphion glyphion-leaf" aria-hidden="true"></span> <a href="{{ url_for('detail',question_id = foo.id)}}">{{ foo.title }}</a> <p style="width: 450px;"> 詳情 {{ foo.detail }}</p> <span class="glyphion glyphion-user" aria-hidden="true"></span> <a href="{{ url_for('userbase',user_id = foo.author_id,tag = 1)}}">{{ foo.author.username }} 評論:({{ foo.comments|length }})</a> <span class="badge">{{ foo.creat_time }}</span> </li> {% endfor %} </ul> </div> </div> {% endblock %}
3)主PY文件寫視圖函數,帶id參數。 首頁標題的標籤作帶參數的連接,在詳情頁將數據的顯示在恰當的位置。創建評論的對象關係映射,嘗試實現發佈評論。
完成評論功能:定義評論的視圖函數,讀取前端頁面數據,保存到數據庫中 ,顯示評論次數,要求評論前登陸(調用登陸裝飾器),嘗試實現詳情頁面下的評論列表顯示。
@app.route('/detail/<question_id>') def detail(question_id): quest = Question.query.filter(Question.id == question_id).first() return render_template('detail.html',ques = quest) @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))
detail.html
{% extends 'base.html' %} {% block title %}問答詳情{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/detail.css')}}"> {% endblock %} {% block main %} <div class="detail"> <h3 >{{ ques.title }} <small>{{ ques.author.username }} <span class="badge">{{ ques.creat_time }}</span> </small> </h3> <p class="lead" >詳情 {{ ques.detail }}</p> <hr> <form action="{{ url_for('comment') }}" method="post" class="box"> <div class="form-group"> <textarea name="new_comment" class="form-control" rows="5" id="new_comment" placeholder="write your comment"></textarea> <input name="question_id" type="hidden" value="{{ ques.id }}" /> </div> <button type="submit" class="btn-default">發送</button> <br> <hr> <div class="form-group"> <h4>評論:({{ ques.comments|length }})</h4> <ul class="list-group" style="list-style: none"> {% for foo in ques.comments %} <li class="list-group-item"> <span class="glyphion glyphion-heart-empty" aria-hidden="true"></span> <a href="{{ url_for('userbase',user_id = foo.author.id,tag = 1)}}">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p style="width: 450px;"> 詳情 {{ foo.detail }}</p> </li> {% endfor %} </ul> </div> </form> </div> {% endblock %}
D、我的中心:實現評論列表顯示及排序。完成我的中心:我的中心的頁面佈局(html文件及相應的樣式文件),定義視圖函數向前端頁面傳遞參數,頁面顯示相應數據:發佈的所有問答、發佈的所有評論、我的信息;各個頁面連接到我的中心。
實現標籤頁導航:利用嵌套繼承,製做我的中心的三個子頁面,重寫userbase.html中定義的user塊,分別用於顯示問答、評論、我的信息。我的中心—視圖函數、導航標籤與HTML頁面連接增長tag參數。
@app.route('/userbase/<user_id>/<tag>') @loginFirst def userbase(user_id,tag): user = User.query.filter(User.id == user_id).first() mycontext = { 'user': user, #'user_name': user.username, #'questions': user.question, #'comments': user.comments } 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)
userbase.html
{% extends 'base.html' %} {% block title %}我的中心{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css')}}"> {% endblock %} {% block main %} <div id="content"> <ul class="nav_ul" style="list-style:none;float:left"> <li role="presentation"><a href="{{ url_for('userbase',user_id = user.id,tag = '1') }}">所有問答</a></li> <li role="presentation"><a href="{{ url_for('userbase',user_id = user.id,tag = '2') }}">所有評論</a></li> <li role="presentation"><a href="{{ url_for('userbase',user_id = user.id,tag = '3') }}">我的信息</a></li> </ul> </div> {% block user %}{% endblock %} {% endblock %}
use1.html
{% extends 'userbase.html' %} {% block title %}所有問答{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css')}}"> {% endblock %} {% block user %} <div class="list-container"> <ul class="note-list" style="list-style: none"> {% for foo in user.question %} <li class="note-list-item"> <span class="glyphion glyphion-leaf" aria-hidden="true"></span> <a href="{{ url_for('detail',question_id = foo.id)}}">{{ foo.title }}</a> <p style="font-family: 幼圓;color: black;"> 詳情 {{ foo.detail }}</p> <span class="glyphion glyphion-user" aria-hidden="true"></span> <a href="{{ url_for('userbase',user_id = foo.author_id,tag = 1)}}">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> </li> {% endfor %} </ul> </div> {% endblock %}
user2.html
{% extends 'userbase.html' %} {% block title %}所有評論{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css')}}"> {% endblock %} {% block user %} <div class="list-container"> <h3 style="font-family:幼圓 ;color:black;width:100px"><span class="glyphion glyphion-user" aria-hidden="true"></span>{{ username }} <br><small>所有評論 <span class="badge"></span></small> </h3> <ul class="list-group" style="margin: 10px;list-style: none"> {% for foo in user.comments %} <li class="note-list-item"> <span class="glyphion glyphion-haert-empty" aria-hidden="true"></span> <a href="#">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p style="font-family: 幼圓;color: black;"> 詳情 {{ foo.detail }}</p> </li> {% endfor %} </ul> </div> {% endblock %}
user3.html
{% extends 'userbase.html' %} {% block title %}我的信息{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css')}}"> {% endblock %} {% block user %} <div class="list-container"> <h3><span class="glyphion glyphion-user" aria-hidden="true"></span>{{ username }} <br><small>我的信息 <span class="badge"></span></small> </h3> <ul class="list-group" style="margin: 10px;list-style: nonefont-family: 幼圓;color:black;"> <li class="list-group-item">用戶:{{ user.username}}</li> <li class="list-group-item">編號:{{ user.id }}</li> <li class="list-group-item">暱稱:{{ user.nickname}}</li> <li class="list-group-item">文章篇數:{{ user.question|length }}</li> <li class="list-group-item">評論數:{{ user.comments|length }}</li> </ul> </div> {% endblock %}
E、搜索,條件組合搜索:實現搜索功能:準備視圖函數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',question = ques)