前言
? Flask是一個使用Python編寫的輕量級 Web 應用框架,對于像我這種想偷懶,不想自己從頭學后端的人來說是再合適不過了,為了使用Flask,我在十一月份就已經開始了學習Flask必備的Python知識。
明確目標
? 首先要明確目標,我要做的是在客戶端輸入用戶名密碼,然后選擇登錄還是注冊,在服務器端進行檢驗,并存儲數據到服務器端的數據庫(為了簡便使用SQLite),并且返回Response消息回客戶端,客戶端再根據返回的Response消息進行相應的動作。由于在大一的時候用C語言做過一個京東購物管理系統,里面涉及了在本地登錄,所以我對登錄頁面的邏輯還算是輕車熟路了。
首先寫Android端邏輯
? 首先需要在APP端構造一個簡單的登錄界面,只需要兩個EditText和兩個按鈕就行了。如圖所示
? 然后寫代碼從兩個輸入框中將用戶輸入的用戶名和密碼提取出來。
@Override
public void onClick(View v)
{
String userName = userNameEdit.getText().toString();
String passWord = passWordEdit.getText().toString();
if(userName.equals("")||passWord.equals(""))
{
showWarnSweetDialog("賬號密碼不能為空");
return;
}
switch (v.getId())
{
case R.id.log_Button:
String url = "http://192.168.253.1:5000/user";/*在此處改變你的服務器地址*/
getCheckFromServer(url,userName,passWord);
break;
case R.id.Sign_Button:
String url2 = "http://192.168.253.1:5000/register";/*在此處改變你的服務器地址*/
registeNameWordToServer(url2,userName,passWord);
break;
}
}
? 有一點重要的是要判斷不為空,由于這個應用不牽涉到大規模使用,所以不對密碼安全性進行限制。
? 接下來先寫注冊模塊,注冊模塊由registeNameWordToServer()函數來實現,這個模塊功能就是將用戶名密碼發送到url對應的服務器地址。在網絡方面為了簡便,使用了一個OKHttp的開源網絡框架。
private void registeNameWordToServer(String url,final String userName,String passWord)
{
OkHttpClient client = new OkHttpClient();
FormBody.Builder formBuilder = new FormBody.Builder();
formBuilder.add("username", userName);
formBuilder.add("password", passWord);
Request request = new Request.Builder().url(url).post(formBuilder.build()).build();
Call call = client.newCall(request);
call.enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
showWarnSweetDialog("服務器錯誤");
}
});
}
@Override
public void onResponse(Call call, final Response response) throws IOException
{
final String res = response.body().string();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
if (res.equals("0"))
{
showWarnSweetDialog("該用戶名已被注冊");
}
else
{
showSuccessSweetDialog(res);
sharedPreferences = getSharedPreferences("UserIDAndPassword", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", userName);
editor.apply();
}
}
});
}
});
}
只需要調用Request的post方法就能夠進行post動作。在Call里收到服務器的返回消息,重寫CallBack接口,寫出成功響應和失敗響應的邏輯。在接口中由于OkHttp已經封裝了子線程操作,所以這是在子線程中的動作,如果需要彈出對話框需要返回UI線程。
接下來的登錄模塊跟注冊模塊大同小異。
服務器端邏輯
? 服務器端要用到Flask,所以當然首先創建一個Flask項目,由于我用的IDE是JetBrain的PyCharm,創建Flask項目非常方便。本來我以為服務器端會很難,還專門買了一本Flask的書,結果還沒看幾頁的知識就完全夠用了。先上代碼:
from flask import Flask
from flask import make_response
from flask import request
from flask.ext.script import Manager
import os
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
basedir=os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///'+os.path.join(basedir,'userConfigBase.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
userdb=SQLAlchemy(app)
manager=Manager(app)
@app.route('/')
def test():
return '服務器正常運行'
class userInfoTable(userdb.Model):
__tablename__='userInfo'
id=userdb.Column(userdb.Integer,primary_key=True)
username=userdb.Column(userdb.String,unique=True)
password=userdb.Column(userdb.String)
def __repr__(self):
return 'table name is '+self.username
#此方法處理用戶登錄 返回碼為0無注冊 返回碼為1密碼錯誤
@app.route('/user',methods=['POST'])
def check_user():
haveregisted = userInfoTable.query.filter_by(username=request.form['username']).all()
if haveregisted.__len__() is not 0: # 判斷是否已被注冊
passwordRight = userInfoTable.query.filter_by(username=request.form['username'],password=request.form['password']).all()
if passwordRight.__len__() is not 0:
return '登錄成功'
else:
return '1'
else:
return '0'
#此方法處理用戶注冊
@app.route('/register',methods=['POST'])
def register():
userdb.create_all()
haveregisted = userInfoTable.query.filter_by(username=request.form['username']).all()
if haveregisted.__len__() is not 0: # 判斷是否已被注冊
return '0'
userInfo=userInfoTable(username=request.form['username'],password=request.form['password'])
userdb.session.add(userInfo)
userdb.session.commit()
return '注冊成功'
if __name__ == '__main__':
manager.run()
class userInfoTable(userdb.Model):
__tablename__='userInfo'
id=userdb.Column(userdb.Integer,primary_key=True)
username=userdb.Column(userdb.String,unique=True)
password=userdb.Column(userdb.String)
def __repr__(self):
return 'table name is '+self.username
? @app.route('/')為裝飾器,起作用就是在客戶端訪問“服務器地址/”是可以調用相應的函數。比如@app.route('/register',methods=['POST'])就是當訪問 "服務器地址/register"時調用的。
? Python使用SQLAlchemy操作數據庫很方便,幾句代碼就創建完畢了,一看就懂,當創建表時就要注意了,需要自己寫一個類來實現這個表里所需的列。這個類需要繼承自你的數據庫.Model,userdb.Column(userdb.String,unique=True)就相當于創建了一個String類型的不可重復的列,用來儲存用戶名在合適不過了。
? 接下來就要在函數里處理登錄注冊的邏輯,注冊邏輯是這樣的:取出Request中的username,將其作為關鍵字放進數據庫中搜索,若沒有,則將其用戶名和密碼都儲存下來,若已經存在了,則返回一個錯誤信號通知客戶端已經存在了。
? 登陸邏輯就更簡單了,只需要取出Request中的username,若數據庫中不存在,就通知用戶請先注冊,若存在但密碼不正確,則通知用戶密碼錯誤,若密碼正確,則返回正常信息。
總結
? 通過這次Flask的后端實踐,我深刻明白了一個道理,往往你認為難的東西,你真正去做了,往往會發現并沒有這么難。以前我總是把搭建服務器和Android網絡編程想的很難,其實真正去做了,并不是很難。而那些你認為很簡單那的東西,如果不考慮周到,往往會出岔子。