1. 個人學期總結
第一次接觸Python,在不了解Python的情況下,基礎又差,望而生畏,一開始就給自己打了個叉。然而,通過前期turtle庫的學習,我發現這門語言似乎很有趣,用其他語言要寫好幾十行的代碼,用Python語言只要十幾二十行的代碼就能實現,它的turtle庫很簡單地用一些條件、循環、函數定義,就能畫出漂亮的圖案,像五角星、同心圓、太陽花、中國國旗這些圖案,我才發覺這是一門多么簡潔實用又功能強大的語言。有了開始的興趣,我也就沉下那顆從前就浮躁不安的心,在杜雲梅老師的帶領下,慢慢地一步一步地去熟悉了解python。
在前面的學習中,我了解turtle庫(海龜庫),利用條件、循環、函數定義畫出了五角星、同心圓、太陽花、中國國旗等;我學習了字符串的基本操作,輸出代碼計算后的結果,還有凱撒密碼、GDP格式化輸出、九九乘法表等簡單操作;利用python進行英文詞匯統計,組合數據類型練習,用文件形式實現完成的英文詞頻統計、中文詞頻統計;利用datetime處理日期和時間,將字符串轉化成imestamp與timedelta等等。在后面,我們使用了PyCharm學會了網頁的開發設計,第一次知道網頁設計也有前端、后台,還要連接數據庫。在這個學習的過程中,我遇到很多問題,有時候一些小小的錯誤都要找上老半天,但是看到自己的成果,還是會甘之如飴,有時甚至還會犯一些低級錯誤,例如mysql沒有開啟,代碼拼寫錯誤,相對應的功能代碼沒有放在對應的位置上,粗心導致我犯了不少錯誤,這告誡我們需要細心,更需要細心領會每一行代碼所代表的意思,要運用在那里。同時,在這門課程的學習中,我也得到了很多同學的幫助,相互幫忙有時候能夠更快找出錯誤在哪里,當然,自己也要更加努力。編程就像做數學題,一道數學題目可能有多種解法,但我們不必要像解數學題那樣講得很詳細,只要一目了然並能清晰簡潔的表達和實現功能即可,只有多去練習多去運用它,少用復制粘貼、投機取巧,我們才能在編程道路上越走越遠。第一次自己設計網站,諸多不足,但是在最后看到自己的作品,雖然還不是很完善,但是心里還是忍不住有點自豪。之后我會繼續努力學習Python語言,盡量吸取更多的知識,做出更加美觀實用的網站。
2. 使用工具:pycharm64.exe + Python 3.6 64-bit + Navicat for MySQL
Python下載地址:https://www.python.org/downloads/
MySQL下載地址:https://www.mysql.com/downloads/
Pycharm下載地址:https://www.jetbrains.com/pycharm/download/#section=windows
(安裝指南可以自己去網上查看教程,很容易就安裝好了,這里就不加贅述)
3. 網頁基本布局及基本功能的實現
1)加載靜態文件,父模板及其他頁面的繼承
a. 加載靜態文件(用 url_for 反轉鏈接相關文件)
<link rel="stylesheet" type="text/css" href="{{url_for('static',filename='css/base.css') }}"> <script src="{{ url_for('static',filename='js/base.js') }}"></script>
b. 父模板的設置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> {% block title %} {% endblock %} </title> {% block head %} {% endblock %} </head> <body> {% block aa %}{% endblock %} </body> </html>
c. 子模板繼承
{% extends 'base.html' %}
{% block title %}
首頁
{% endblock %}
{% block main %}
{% endblock %}
2)注冊頁面
主要代碼:HTML+JS
{% extends 'base.html' %} {% block title %} 歡迎開啟美食之旅 {% endblock %} {% block main %} <link href="../static/css/hh.css" rel="stylesheet" type="text/css"> <script src="../static/js/zc.js"></script> <div><h1>美食祭|注冊</h1></div><br><br><br> <form action="{{ url_for('zhuce') }}" method="post"> <div class="box"> <p class="input_box"> 賬戶: <input id="uname" type="text" placeholder="請輸入您的昵稱" name="username"> </p> <p class="input_box"> 密碼: <input id="upass" type="password" placeholder="請設置您的密碼" name="password"> </p> <p class="input_box"> 驗證: <input id="upass1" type="password" placeholder="請再次輸入密碼" name="password"> </p> <p class="input_box"> 郵箱: <input id="youxiang" type="password" placeholder="請輸入您的郵箱" name="email"> </p> <div id="error_box"><br></div> <div class="input_button"> <button type="submit" onclick="return fozhuce()">立即注冊</button> </div> </div> </form> {% endblock %}
function fozhuce() { var oUname = document.getElementById("uname"); var oError = document.getElementById("error_box"); var oUpass = document.getElementById("upass"); var oUpass1 = document.getElementById("upass1"); 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)<58)&&(oUname.value.charCodeAt(i)>97)){ oError.innerHTML="只能為數字和字母"; isError = false; return isError; } }if (oUpass.value.length < 6 || oUpass.value.length > 20) { oError.innerHTML = "密碼要6-20位"; isError = false; return isError; }else if(oUpass.value!=oUpass1.value) { oError.innerHTML = "設置密碼和驗證密碼不一致"; isError = false; return isError; } return ture; }
3)登錄頁面
主要代碼:HTML+JS
{% extends 'base.html' %} {% block title %} 登錄 {% endblock %} {% block main %} <link rel="stylesheet" type="text/css" href="../static/css/hh.css"> <script src="../static/js/dl.js"></script> <div><h1>美食祭|登錄</h1></div> <br><br><br> <body><div class="box"> <form action="{{ url_for('denglu') }}" method="post"> <p class="input_box"> 賬戶: <input id="uname" type="text" placeholder="敢問閣下大名"name="username"> </p> <p class="input_box"> 密碼: <input id="upass" type="password" placeholder="請輸入通關密碼" name="password"> </p> <div id="error_box"><br></div> <div class="input_box"> <button onclick="return fnLogin()">登錄</button> </div> </form> {% endblock %} </body>
function foLogin() { var oUname = document.getElementById("uname"); var oError = document.getElementById("error_box"); var oUpass = document.getElementById("upass"); var isError = true; oError.innerHTML = "<br>"; if (oUname.value.length < 6 || oUname.value.length > 12) { oError.innerHTML = "用戶名要6-12位"; isError = false; return; }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)<58)&&(oUname.value.charCodeAt(i)>97)){ oError.innerHTML="只能為數字和字母"; isError = false; return isError; } } if (oUpass.value.length < 6 || oUpass.value.length > 12) { oError.innerHTML = "密碼要6-20位"; isError = false; isError = false; return isError; } return ture; }
4)問答平台及問題詳情頁
{% extends 'base.html' %} {% block title %} 問答平台 {% endblock %} {% block main %} <link type="text/css" rel="stylesheet" href="{{ url_for('static',filename='css/hh.css') }}"> <form action="{{ url_for('wenda') }}" method="post"> <div class="box"> <h2 align="center">發布問答</h2> <div class="q"> <label for="questionDetail">問題</label><br> <textarea class="form-control" id="questionDetail" rows="2" style="width: 500px"name="title"></textarea></div><br> <div class="form-group"> <label for="result">詳情</label><br> <textarea class="form-control" id="result" rows="4" style="width: 500px" name="detail"></textarea></div><br> </div> <div id="error_box"><br></div> <div class="input-area"> <button type="submit" onclick="foLogin()">發布問答</button> </div> </div> </form> {% endblock %}
{% extends 'base.html' %} {% block title %} 問答詳情 {% endblock %} {% block main %} <link rel="stylesheet" type="text/css" href="../static/css/hh.css"> <div class="box"> <h3 href="#" >問題標題:{{ ques.title }}</h3> <small>發布者: {{ ques.author.username }}<span class="badge" style="margin-left: 75%">發布時間{{ ques.create_time }}</span></small> <hr> <p style="font-size: 18px;color: black;">問題詳情:{{ ques.detail }}</p> <hr> <form action="{{ url_for('comment') }}" method="post"> <div><textarea class="form-control" id="comment" rows="3" style="margin-left: 1%" name="new_comment" placeholder="write your comment"></textarea><br></div> <input type="hidden" name="question_id" value="{{ ques.id }}"> <button type="submit" >發送</button> </form> <h4>評論:({{ ques.comments|length }})</h4> <ul class="list-unstyled"> {% for foo in ques.comments %} <li class="list-group-item"> <a href="{{ url_for('usercenter',user_id = foo.author.id,tag='1') }}">{{ foo.author.username }}</a> <span class="badge pull-right">{{ foo.create_time }}</span> <p>{{ foo.detail }}</p> <br> </li> {% endfor %} </ul> </div> {% endblock %}
5)個人中心:個人中心父模板 + 全部評論 + 全部問答 + 個人信息
個人中心父模板
{% extends 'base.html' %} {% block title %} {% endblock %} {% block main %} <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"></div> <ul class="nav nav-pills"> <li><a href="{{ url_for('usercenter',user_id=user.id,tag = 1) }}">全部評論</a></li> <li><a href="{{ url_for('usercenter',user_id=user.id,tag = 2) }}">全部問答</a></li> <li><a href="{{ url_for('usercenter',user_id=user.id,tag = 3) }}">個人信息</a></li> </ul> {% block hh %}{% endblock %} {% endblock %}
{% extends 'userbase.html' %} {% block title %} 全部評論 {% endblock %} {% block hh %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"></div> <div class="col-md-8 column"> <ul class="list-unstyled" > {% for foo in comments %} <li class="list-group-item"> <img style="width: 30px" src="{{ url_for('static',filename='css/tx.jpg') }}" alt="64"> <a href="#">{{ username }}</a><br> <span class="badge pull-right">{{ foo.create_time }}</span> <a href="{{ url_for('detail',question_id=foo.id) }}">文章標題:{{ foo.question.title }}</a><br> <p style="align-content: center">評論內容:{{ foo.detail }}</p> <br> </li> {% endfor %} </ul> </div> <div class="col-md-2 column"> </div> </div> </div> {% endblock %}
{% extends 'userbase.html' %} {% block title %} 全部問答 {% endblock %} {% block hh %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"></div> <div class="col-md-8 column"> <ul class="list-unstyled"> {% for foo in questions %} <li class="list-group-item"> <img style="width: 30px" src="{{ url_for('static',filename='css/tx.jpg') }}" alt="64"> <a href="#">{{ username }}</a><br> <a href="{{ url_for('detail',question_id=foo.id) }}">問題:{{ foo.title }}</a><br> <p style="align-content: center">{{ foo.detail }}</p> <span>評論數: ({{ foo.comments|length }})</span> <span class="badge" style="margin-left: 60%">{{ foo.create_time }}</span> <p style="margin-left: 25%"></p><br> </li> {% endfor %} </ul> </div> <div class="col-md-2 column"> </div> </div> </div>{% endblock %}
{% extends 'userbase.html' %} {% block title %} 個人信息 {% endblock %} {% block hh %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"></div> <div class="col-md-8 column"> <ul class="list-unstyled"> <li class="list-group-item" > <img style="width: 30px" src="{{ url_for('static',filename='css/tx.jpg') }}" alt="64"> <small><a href="#">{{ username }}</a></small> <a>評論數: {{ comments|length }}</a><br> <a>文章篇數:{{ questions|length }}</a> <p style="margin-left: 25%"></p><br> </li> </ul> </div> <div class="col-md-2 column"> </div> </div> </div>{% endblock %}
6)密碼保護:
a. 更新User對象,設置對內的_password
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) #內部使用
b. 編寫對外的password
@property def password(selfs): #外部使用,取值 return self._password @password.setter def password(self,row_password): #外部使用,賦值 self._password=generate_password_hash(row_password)
c. 密碼驗證:
def check_password(self,row_password): result=check_password_hash(self._password,row_password) return result
d. 登錄驗證:
@app.route('/denglu/', methods=['GET', 'POST']) def denglu(): if request.method == 'GET': return render_template('dl.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 '密碼錯誤' else: return '此用戶不存在'
4.Flask應用程序及數據庫連接
1)Flask應用程序
所有的Flask應用程序都必須創建一個 應用程序實例 。使用web服務器網關接口協議將所有從客戶端接收的請求傳遞給這個對象處理。這個應用程序實例就是Flask類的一個對象,通常使用下面的方式創建:
from flask import Flask app = Flask(__name__) #構造函數的name參數,__name__變量是需要傳遞的值
客戶端(如web瀏覽器)發送請求給web服務,進而將它們發送給Flask應用程序實例。應用程序實例需要知道對於各個URL請求需要運行哪些代碼,所以需要給Python函數建立了一個URLs映射。這些在URL和函數之間建立聯系的操作被稱之為路由 。
在Flask應程序中定義路由的最便捷的方式是通過顯示定義在應用程序實例之上的app.route裝飾器,注冊被裝飾的函數來作為一個路由。裝飾器是Python語言的標准特性;它們可以以不同方式改變函數的行為。一個常見的模式是使用裝飾器來注冊函數作為一個事件處理程序。
# 使用裝飾器來申明一個路由 hello_world()為視圖函數 @app.route('/') def hello_world(): return render_template('base.html') @app.route('/zhuce/',methods=['GET','POST'])
項目所需導入的庫
2)數據庫連接:
建立mysql和app的連接,創建用戶模型,在py文件中創建表格
from flask import Flask from flask_sqlalchemy import SQLAlchemy import databases app = Flask(__name__) app.config.from_object(databases)#app連接數據庫 db = SQLAlchemy(app) class User(db.Model): #創建user表格 __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(100), nullable=False) _password = db.Column(db.String(500), 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) create_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')) create_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) question = db.relationship('Question',backref=db.backref('comments',order_by=create_time.desc)) author = db.relationship('User',backref=db.backref('comments')) #鏈接到user表,通過user.comments可以獲取到comment表中的內容 db.create_all() #數據庫創建表格語句
數據庫配置信息
import os DEBUG = True SECRET_KEY = os.urandom(24) SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:@localhost:3306/wlin?charset=utf8' SQLALCHEMY_TRACK_MODIFICATTONS = False
5.運行過程中可能會遇到的錯誤:
1)程序沒有指定Python運行
解決方案:進入設置——項目——project interpreter 選擇運行環境
2)連接不上數據庫,有以下三種情況:
a. 本機的數據庫沒有啟動
解決方案:在桌面找到這台電腦——右鍵選擇管理——在服務與運行程序中,選擇服務——找到數據庫啟動
b. 連接數據庫時沒有輸入數據庫密碼或者輸入密碼錯誤
解決方案:在root:后面添加或者修改密碼
c. 沒有在數據庫新建對應的數據庫
解決方案:在數據庫新建對應的數據庫