1. 程式人生 > >一個web應用的誕生(7)

一個web應用的誕生(7)

user 用戶名 版本 結構 reg tar rem 比較 ict

現在所有的Py代碼均寫在default.py文件中,很明顯這種方法下,一旦程序變的負責,那麽無論對於開發和維護來說,都會帶來很多問題。

Flask框架並不強制要求項目使用特定的組織結構,所以這裏使用的組織結構並不一定與其它項目中相同。

技術分享

根據default.py中的代碼,大體可分為三類:表單模型,數據模型,視圖方法,所以模型也網這類中來區分。所以按照其他語言(java)得來的經驗,每個類為一個py文件,放到相應的文件夾中

技術分享

在單個文件中,所有的配置都寫在單個的文件裏,而在進行多文件重構之後,還這樣做很明顯是不合適的,所以創建一個獨立的config文件很有必要:

class Config:
    SECRET_KEY="Niu_blog String"
    SQLALCHEMY_DATABASE_URI=‘mysql://root:[email protected]
/* *//cblog‘ SQLALCHEMY_COMMIT_ON_TEARDOWN=True LOGIN_PROTECTION="strong" LOGIN_VIEW="login"

然後是初始化文件(app/__init__.py):

from flask import Flask
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
import pymysql
pymysql.install_as_MySQLdb()
from config import Config

bootstrap = Bootstrap()
db = SQLAlchemy()
login_manager=LoginManager();

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    bootstrap.init_app(app)
    login_manager.init_app(app)
    login_manager.session_protection=Config.LOGIN_PROTECTION
    login_manager.login_view=Config.LOGIN_VIEW
    db.init_app(app)
    return app

進一步模塊化還要使用藍本,藍本的功能有些類似 asp.net mvc中的area,將不同模塊的視圖方法整合到一起,並通過url進行區分,首先入口即index頁面定義為main藍本,方法如下:

  1. 創建main文件夾
  2. 文件夾內新建藍本初始化文件__init__.py
  3. 創建視圖方法文件view.py
  4. 主藍本內創建錯誤頁視圖方法errors.py

初始化文件代碼如下:

from flask import Blueprint

main=Blueprint("main",__name__) # 創建藍本
from . import errors,views

目前,視圖方法文件只有一個index方法,代碼如下:

from flask import render_template
from . import main

@main.route("/")
def index():
    return render_template("index.html",site_name=‘myblog‘)

錯誤頁代碼略

主藍本的的URL不使用前綴

然後登陸註冊登出頁集中到權限藍本(auth),權限藍本初始化代碼如下:
from flask import Blueprint

auth=Blueprint("auth",__name__)
from . import views
    

視圖主要為之前已經完成的視圖遷移過來:

from . import auth
from .. import  db,login_manager
from ..forms.LoginForm import LoginForm(*)
from ..models.User import User (*)
from flask_login import login_user,logout_user
from flask import  render_template,flash,redirect,url_for

@auth.route("/login",methods=["GET","POST"])
def login():
    form = LoginForm()
    print(url_for("main.index"))
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        print(User)
        user = User.query.filter_by(username=username, password=password).first()
        if user is not None:
            login_user(user, form.remember_me.data)
            print(url_for("main.index"))
            return redirect(url_for("main.index"))
        else:
            flash("您輸入的用戶名或密碼錯誤")
            return render_template("/auth/login.html", form=form)  # 返回的仍為登錄頁
        return redirect(url_for("main.index"))
    return render_template("/auth/login.html",form=form)

@auth.route("/logout",methods=["GET","POST"])
def logout():
    logout_user()
    return redirect(url_for("main.index"))

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

註意打星號標記的兩行,一定要註意py文件和py對象,必須在文件內在import對象

其中LoginForm文件內的代碼如下:

from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,SubmitField,BooleanField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username=StringField("請輸入用戶名",validators=[DataRequired()])
    password=PasswordField("請輸入密碼")
    remember_me=BooleanField("記住我")
    submit=SubmitField("登錄")

User文件內的代碼如下:

from flask_login import UserMixin
from  ..  import db

class User(UserMixin,db.Model):
    __tablename__="users"
    id=db.Column(db.Integer,primary_key=True)
    username=db.Column(db.String(50),unique=True,index=True)
    password=db.Column(db.String(50))
    nickname=db.Column(db.String(50))
    email=db.Column(db.String(100))
    birthday=db.Column(db.DateTime)
    gender=db.Column(db.Integer)
    remark=db.Column(db.String(200))
    role_id=db.Column(db.Integer,db.ForeignKey("roles.id"))

註意一下flask插件的導入方式都由flask.ext.*改為新版本推薦的flask_*這種方式,在此感謝博友 治電小白菜的提醒。

當然,最終還要對藍本進行註冊,所以最終create_app方法的代碼為:

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    bootstrap.init_app(app)
    login_manager.init_app(app)
    login_manager.session_protection=Config.LOGIN_PROTECTION
    login_manager.login_view=Config.LOGIN_VIEW
    db.init_app(app)
    from .main import main as main_blueprint
    from .auth import auth as auth_blueprint
    app.register_blueprint(main_blueprint)                    #無url前綴
    app.register_blueprint(auth_blueprint,url_prefix="/auth") #url前綴為/auth
    return app

最後修改的是啟動運行的方式,新建一個manager.py文件,配置啟動代碼如下:

from app import create_app, db
from flask_script import Manager,Shell
from flask_migrate import Migrate,MigrateCommand
from app.models.User import User
from app.models.Role import Role
import pymysql
pymysql.install_as_MySQLdb()
app=create_app()
manager=Manager(app);
migrate = Migrate(app, db)


def make_shell_context():
    return dict(app=app,db=db,User=User,Role=Role) #註冊shell命令
manager.add_command("db", MigrateCommand) #新增db命令用於數據庫遷移
manager.add_command("shell" ,Shell(make_context=make_shell_context()))

if __name__ ==‘__main__‘:
    manager.run()

用最土的方式,跑跑運行一下,運行結果與之前僅有default.py的時候相同,此時系統目錄如下,僅供參考:

技術分享

此章並沒有多少新東西,主要是對之前的系統目錄,系統結構做一些調整,這周比較忙,要準備應聘,準備面試,緊趕慢趕總算至少完成了對自己的承諾,每周一篇blog,不過如果按照發布時間來說,貌似還是晚了一天,畢竟現在已經過了0點:(

一個web應用的誕生(7)