父模板的製做 html
父模版導航欄web
<nav class="navbar navbar-expand-lg bg-light "> <a class="navbar-brand" href="#"></a> <div class="collapse navbar-collapse " id="navbarNav"> <ul class="nav navbar-nav navbar-right"> <li class="nav-item "> <a class="nav-link " href="{{ url_for("shouye")}}">首頁 <span class="sr-only">(current)</span></a> </li> <li class="nav-item "> <a class="nav-link disabled " href="#">動畫</a> </li> <li class="nav-item"> <a class="nav-link disabled" href="#">音樂</a> </li> <li class="nav-item"> <a class="nav-link disabled" href="">遊戲</a> </li> </ul> <form class="form-inline" action="{{ url_for("search") }}" method="get"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="q"> <button class="btn btn-secondary" type="submit">搜索</button> </form> </div> <div style="float: right;width: 10%"> {% if username%} <a class="navbar-link disabled"href="">{{ username }}</a> <a class="navbar-link disabled" href="{{ url_for("logout") }}">註銷</a> {% else %} <a class="navbar-link disabled"href="{{ url_for("denglu") }}">登錄</a> <a class="navbar-link disabled" href="{{ url_for("zhuce") }}">註冊</a> {% endif %} </div> </nav>
2首頁、登陸頁、註冊頁數據庫
登陸頁:denglu.html 繼承父模版 text.html flask
{% extends "text.html" %}
{% block denglu %}{% endblock %}
<form id="b" method="post" action="{{ url_for('denglu') }}"> <div class="container-fluid " id="denglu"> <div class="mt-5 pt-5" > <div class="card border-primary mb-3 m-auto" style="max-width: 20rem;"> <div class="card-header text-center">wgd</div> <div class="card-body text-primary"> <h4 class="card-title">用戶登陸</h4> <div class="input-group mb-2 mr-sm-2 mb-sm-0"> <div class="input-group-addon"><i class="fa fa-user"></i></div> <input type="text" class="form-control" placeholder="Username" id="uname" required="true" name="username"> </div> <p id="errorbox1" class="m-0 p-0 text-danger">  </p> <div class="input-group mb-2 mr-sm-2 mb-sm-0"> <div class="input-group-addon"><i class="fa fa-lock"></i></div> <input type="password" class="form-control" placeholder="Password" id="upass" name="password"> </div> <p id="errorbox2" class="m-0 p-0 text-danger">  </p> <div class="row"> <div class="col-3"> <button class="btn btn-outline-primary" onclick=" MyLogin()" >登陸</button> </div>
JS文件Mylogin.jsp中的 Mylogin()函數對登陸行爲進行檢驗。安全
function MyLogin() { var oUname=document.getElementById("uname"); var oUpass=document.getElementById("upass"); var oError1=document.getElementById("errorbox1"); var oError2=document.getElementById("errorbox2"); oError1.innerHTML="<br>"; oError2.innerHTML="<br>"; if(oUname.value.length<6 ||oUname.value.length>20){ oError1.innerHTML='Usename必須屬於6-20位'; return false; }else if((oUname.value.charCodeAt(0)>=48)&&(oUname.value.charCodeAt(0)<=57)){ oError1.innerHTML='Useman不得以數字開頭'; return false; }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)){ oError1.innerHTML='用戶名必須由數字或字母組成' return false; } } if(oUpass.value.length<6||oUpass.value.length>20) { oError2.innerHTML = "Password必須屬於6-20位"; return false; }else { oError2.innerHTML=" " return true; } }
後臺 denglu()函數控制登陸。session
@app.route('/denglu',methods=['GET','POST']) def denglu(): if request.method == 'GET': return render_template('denglu.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['id'] = user.id session.permanent = True return redirect(url_for('shouye')) else: return 'password error' else: return 'username is not existed'
註冊功能 zhuce.htmlapp
<form id='a' action="{{ url_for("zhuce") }}" method="post"> <div class="container-fluid"> <div class="mt-5 pt-5"> <div class="card border-primary mb-3 m-auto" style="max-width: 20rem;"> <div class="card-header text-center">wgd</div> <div class="card-body text-primary"> <h4 class="card-title" align="center">註冊</h4> <div class="input-group mb-2 mr-sm-2 mb-sm-0"> <div class="input-group-addon"><i class="fa fa-user"></i></div> <input type="text" class="form-control" placeholder="Username" id="uname" required name="username"> </div> <p id="errorbox1" class="m-0 p-0 text-danger">  </p> <div class="input-group mb-2 mr-sm-2 mb-sm-0"> <div class="input-group-addon"><i class="fa fa-lock"></i></div> <input type="text" class="form-control" placeholder="nickname" id="nickname" required name="nickname"> </div> <br> <div class="input-group mb-2 mr-sm-2 mb-sm-0"> <div class="input-group-addon"><i class="fa fa-lock"></i></div> <input type="password" class="form-control" placeholder="Password" id="upass" required name="password"> </div> <p id="errorbox2" class="m-0 p-0 text-danger">  </p> <div class="input-group mb-2 mr-sm-2 mb-sm-0"> <div class="input-group-addon"><i class="fa fa-lock"></i></div> <input type="password" class="form-control" placeholder="Password_check" id="upass_check" required onblur="check()"/> </div> <span id="warning"> </span> <div class="row"> <div class="col-3"> <button class="btn btn-outline-primary" onclick= "MyLogin()">註冊</button> </div>
JS文件Mylogin.jsp中的 check()函數對登陸行爲進行檢驗。jsp
function check(){ var password1=document.getElementById("upass").value; var password2=document.getElementById("upass_check").value; if(password1!==password2) { document.getElementById("warning").innerHTML=" 兩次密碼的輸入不一致"; return ; } document.getElementById('a').submit(); }
後臺 denglu()函數控制登陸。函數
@app.route('/zhuce',methods=['GET','POST']) def zhuce(): if request.method == 'GET': return render_template('zhuce.html') else: username = request.form.get('username') password = request.form.get('password') nickname = request.form.get('nickname') user1 = User.query.filter(User.username == username).first() if user1: return 'username existed' else: user1 = User(username=username, password=password, nickname=nickname) db.session.add(user1) db.session.commit() return redirect(url_for('denglu'))
控制內容發佈頁 函數:def fankui(): 發佈的內容存儲在數據庫wgd的表question 中post
@app.route('/neirong',methods=['GET','POST']) @log def fankui(): if request.method=='GET': return render_template('fankui.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('shouye'))
驗證只有登陸狀態才能進行內容的發佈 def log(func)
def log(func): @wraps(func) def wrapper(*args,**kwargs): if session.get('user'): return func(*args,**kwargs) else: return render_template('denglu.html') return wrapper
內容發佈後顯示在首頁 def shouye():
@app.route('/') def shouye(): context={ 'question':Question.query.all() } return render_template('shouye.html',**context)
for循環遍歷數據庫wgd中question表中的每一條內容。
{% for foo in question %} <div class="card w-57"></div> <li class="list-group-item rounded m-1" style="height: 10ch"> <span> <a href="{{ url_for("pre",user_id=foo.author.id,tag='1') }}">{{ foo.author.username }}</a> <span class="">{{ foo.creat_time }}</span><br> <a href="{{ url_for("pinglun",question_id=foo.id) }}">{{ foo.title }}</a> <p>{{ foo.detail }}</p> </span> </li>{% endfor %}
點擊文章標題進入內容頁進行評論。
@app.route('/commemt/',methods=['GET','POST'])
@log
def comment():
if request.method=='GET':
return render_template(url_for('pinglun'))
else:
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
comment=Comment(author_id=auth_id,question_id=ques_id,detail=comment)
db.session.add(comment)
db.session.commit()
return redirect(url_for('pinglun',question_id=ques_id))
@app.route('/pinglun<question_id>')
def pinglun(question_id):
quest = Question.query.filter(Question.id==question_id).first()
return render_template('pinglun.html',ques=quest)
經過
{{ ques.author.username }}
{{ ques.detail }}
等語句調用數據庫user 和comment表的用戶信息 和發佈的內容
<div class="card" style="width: 65rem;margin-top:2% ; margin-left: 23%;"> <div style= > <h2 class="card-header" style="margin-bottom: 0" >{{ ques.title }}</h2> </div> <div class="card-body"style="padding-bottom: 1%"> <h4 class="card-title"><a href="{{ url_for('pre',user_id=ques.id,tag='1') }}"> {{ ques.author.username }} </a><small> {{ ques.creat_time }}</small></h4> <hr> <h5>{{ ques.detail }}</h5> <hr> <form action="{{ url_for('comment') }}" method="post"> <div style="width: 50rem;margin-left:6%;margin-top: 3%"> <textarea name="new_comment" class="form-control" rows="10" placeholder="請寫下評論" ></textarea><br> <input name="question_id" type="hidden" value="{{ ques.id }}"/> <button type="submit" class="btn btn-outline-primary ">提交評論</button> </div> </form> </div>
發表評論 經過循環語句遍歷出每一條存儲與數據庫庫中的評論。
<h5 style="margin-left: 3.5%">評論:<p>內容篇幅:{{ ques.detail|length }}</p></h5> <div class="" style="width:58rem;margin-left: 4%;height: auto;margin-top: 0.5% "> {% for com in ques.comment %} <a href="#" >{{ com.author.username }}</a> <small>{{ com.creat_time }}</small> <p class="">{{ com.detail }}</p> {% endfor %} </div>
點擊 用戶名能夠進入當點登陸的用戶的我的信息頁。
userbase.html繼承父模板並做爲我的信息頁面的父模板。 寫入我的信息頁的導航欄。
<div align="center"> <ol style="font-size: large;list-style-type: none;" > <li role="presentation" class="breadcrumb-item " aria-current="page"><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> 所有問答</a></li> <li role="presentation" class="breadcrumb-item active" aria-current="page"><a href="{{ url_for('pre',user_id=user.id,tag='2') }}">所有評論</a></li> <li role="presentation" class="breadcrumb-item active" aria-current="page"><a href="{{ url_for('pre',user_id=user.id,tag='3') }}">我的資料</a></li> </ol></div><br>
@app.route('/presonal_message/<user_id>/<tag>') @log def pre(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ 'user':user } if tag =='1': return render_template('usercenter1.html',**context) elif tag=='2': return render_template('usercenter2.html',**context) else: return render_template('usercenter3.html',**context)
usercenter1.html usercenter2.html usercenter3.html 繼承userbase.html
usercenter1.html
<body background="/static/img/WeChat%20Image_20171027161942.png" style="background-attachment: fixed;background-size: 100% 100%"> <div style="margin-left: 28%;margin-top: 1.5%"> <div class="card" style="width: 60rem;height:auto"> <div class="card-header"> <h2><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a></h2> </div> <div class="card-body"> <ul style="font-size: large;list-style-type: none;"> <p class="text-info"style="font-size: 30px">全部問答</p> {% for foo in user.question %} <div> <li> <a href="{{ url_for('pre',user_id=user.id,tag='3') }}">{{ foo.author.username }}</a> <span class="">{{ foo.creat_time }}</span><br> <a href="{{ url_for("pinglun",question_id=foo.id) }}">{{ foo.title }}</a> <p>{{ foo.detail }}</p> </li></div>
usercenter2.html
{% block usercenter %} <div style="margin-left: 28%;margin-top: 1.5%"> <div class="card" style="width: 60rem;height:auto"> <div class="card-header"> <h2><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a></h2> </div> <div class="card text-left" style="width: 60rem;height: auto"> <div class="card-body"> <ul style="font-size: large;list-style-type: none"> <p class="text-info"style="font-size: 30px">全部評論</p> {% for foo in user.comment %} <li> <a href="#">{{ foo.author.username }}</a> <span>{{ foo.creat_time }}</span><br> <p>{{ foo.detail }}</p> </li> {% endfor %}
usercenter3.html
<div style="margin-left: 28%;margin-top: 1.5%"> <div class="card" style="width: 60rem;height:auto"> <div class="card-header"> <h2><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a></h2> </div> <div class="card text-left" style="width: 60rem;height: auto"> <div class="card-body"> <ul style="font-size: large;list-style-type: none"> <p class="text-info"style="font-size: 30px">我的信息</p> <li><p>用戶名:{{ user.username }}</p></li> <li><p>Id:{{ user.id }}</p></li> <li><p>內容篇幅:{{ user.question|length }}</p></li> </ul> </div>
<a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a>
讓用戶名變成連接,點擊用戶名跳轉到我的中心。
導航欄上的用戶名先
if user.check_password(password): session['user'] = username session['id'] = user.id session.permanent = True return redirect(url_for('shouye'))
session獲取'id'屬性賦值給user.id
父模板調用
href="{{ url_for('pre',user_id=session.get('id'),tag='1') }} 實現連接到我的中心。
實現登陸 註冊和用戶名 註銷的變換。
{% if username%} <a class="navbar-link disabled"href="{{ url_for('pre',user_id=session.get('id'),tag='1') }}">{{ username }}</a> <a class="navbar-link disabled" href="{{ url_for("logout") }}">註銷</a> {% else %} <a class="navbar-link disabled"href="{{ url_for("denglu") }}">登錄</a> <a class="navbar-link disabled" href="{{ url_for("zhuce") }}">註冊</a> {% endif %}
搜索功能。
無搜索條件時:顯示全部問答內容
輸入搜索條件(模糊查詢) 問答標題(如:你好),篩選出相關問答
搜索框的的name設置爲'q'
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="q">
request請求'q'獲取屬性獲取搜索的內容
進行條件查詢
Question.(數據庫屬性名).contains(qu)
@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('shouye.html',question=ques)
提升數據庫存儲的密碼的安全性。
1.更新User對象,設置對內的_password
_password = db.Column(db.String(200), nullable=False)
2.編寫對外的password
3.密碼驗證的方法:
@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
4.登陸驗證:
@app.route('/denglu',methods=['GET','POST']) def denglu(): if request.method == 'GET': return render_template('denglu.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['id'] = user.id session.permanent = True return redirect(url_for('shouye')) else: return 'password error' else: return 'username is not existed'
我的心得:
通過一學期的Python+flask+html的學習,對於開發一個Flask項目有了初步的接觸和初步的瞭解,學習註冊、登陸、發佈內容的相關知識。
但在這個粗糙的項目中還有不少不少的不足,功能上缺乏文件上傳,修改功能等一系列的基本功能,須要繼續加工。