Flask框架项目实例:**租房网站(一)
生活随笔
收集整理的這篇文章主要介紹了
Flask框架项目实例:**租房网站(一)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
- Flask是一款MVC框架,主要是從模型、視圖、模板三個方面對Flask框架有一個全面的認(rèn)識,
- 通過完成作者-讀書功能,先來熟悉Flask框架的完整使用步驟。
- 操作步驟為:
- 1.創(chuàng)建項目
- 2.配置數(shù)據(jù)庫
- 3.定義模型類
- 4.定義視圖并配置URL
- 5.定義模板
- 前面說了創(chuàng)建項目的流程,今天主要從配置到用戶,主要根據(jù)思維導(dǎo)圖來說,先看思維導(dǎo)圖
-
主要有以下幾個方面: 1.配置文件: 設(shè)置:config.py 主文件:ihome.py 七牛云(圖片上傳):qinniuyun_sdk.py 短信發(fā)送:ytx_send.py 管理文件:manager.py 狀態(tài)文件:status_code.py 模型設(shè)置:models.py
2.視圖:user_views.py
主要根據(jù)思維導(dǎo)圖,代碼加注釋的方法來說明:
1.配置文件: 設(shè)置:config.py、數(shù)據(jù)庫、七牛云配置 # coding=utf-8 import hashlibimport redis class Config:DEBUG=FalseSQLALCHEMY_DATABASE_URI='mysql://root:mysql@127.0.0.1:3306/ihome_bj14'SQLALCHEMY_TRACK_MODIFICATIONS = True #PIL pillow#redis配置REDIS_HOST = "127.0.0.1"REDIS_PORT = 6379#session配置SECRET_KEY = "iHome"#將session存儲到redis中SESSION_TYPE = "redis"SESSION_USE_SIGNER = TrueSESSION_REDIS = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT)PERMANENT_SESSION_LIFETIME = 60*60*24*14#秒# 七牛云的訪問服務(wù)器QINIU_URL = 'http://ozyr1iz9u.bkt.clouddn.com/'# # 權(quán)限信息# TOKEN = hashlib.md5('ihome_bj14').hexdigest()class DevelopConfig(Config):DEBUG = True class ProductConfig(Config):pass
主文件:ihome.py #coding=utf-8#1.創(chuàng)建app對象 from manager import create_app from config import DevelopConfig app=create_app(DevelopConfig)#2.初始化數(shù)據(jù)庫 from models import db db.init_app(app)#3.創(chuàng)建管理對象 from flask_script import Manager manager=Manager(app)#4.添加遷移命令 from flask_migrate import Migrate,MigrateCommand Migrate(app,db) manager.add_command('db',MigrateCommand)#5.注冊藍(lán)圖 from html_views import html_blueprint app.register_blueprint(html_blueprint)from api_v1.user_views import user_blueprint app.register_blueprint(user_blueprint,url_prefix='/api/v1/user')from api_v1.house_views import house_blueprint app.register_blueprint(house_blueprint,url_prefix='/api/v1/house')from api_v1.order_views import order_blueprint app.register_blueprint(order_blueprint,url_predix='/api/v1/order')# # 鉤子,是否包含token # from flask import request,jsonify,current_app # from status_code import * # @app.before_request # def check_token(): # if request.path.startswith('/api'): # if 'token' not in request.args or request.args.get('token')!=current_app.config['TOKEN']: # return jsonify(code=RET.REQERR)if __name__ == '__main__':manager.run()
七牛云(圖片上傳):qinniuyun_sdk.py #coding=utf-8from qiniu import Auth,put_data import logging from flask import jsonify from status_code import RETdef put_qiniu(f1):access_key = '6vvGPJ08BsHRjN7RRGVU3sEd38502x1TS0_i0x7s'secret_key = 'wzgWlHpflABi9DGn9TIb8IBRwqsZTwNJ--KZhosy'# 空間名稱bucket_name = 'itpython'try:#構(gòu)建鑒權(quán)對象q = Auth(access_key,secret_key)#生成上傳Tokentoken = q.upload_token(bucket_name)#上傳文件數(shù)據(jù),ret是字典,鍵是hash/key,值是新文件名,info是response對象ret,info = put_data(token,None,f1.read())return ret.get('key')except:logging.ERROR(u'訪問七牛云出錯')return jsonify(code=RET.SERVERERR)
短信發(fā)送:ytx_send.py # coding=utf-8 from CCPRestSDK import REST # import ConfigParser# 主帳號 accountSid = '8a216da85fe1c856015fe83104160cc';# 主帳號Token accountToken = '5a1dc45a953a41cebb82b5654662568';# 應(yīng)用Id appId = '8a216da85fe1c856015fe8310471033';# 請求地址,格式如下,不需要寫http:// serverIP = 'app.cloopen.com';# 請求端口 serverPort = '8883';# REST版本號 softVersion = '2013-12-26';# 發(fā)送模板短信 # @param to 手機號碼 # @param datas 內(nèi)容數(shù)據(jù) 格式為數(shù)組 例如:{'12','34'},如不需替換請?zhí)?'' # @param $tempId 模板Id ''' to: 短信接收手機號碼集合,用英文逗號分開,如 '13810001000,13810011001',最多一次發(fā)送200個。 datas:內(nèi)容數(shù)據(jù),需定義成數(shù)組方式,如模板中有兩個參數(shù),定義方式為array['Marry','Alon']。 templateId: 模板Id,如使用測試模板,模板id為"1",如使用自己創(chuàng)建的模板,則使用自己創(chuàng)建的短信模板id即可。'''def sendTemplateSMS(to, datas, tempId):# 初始化REST SDKrest = REST(serverIP, serverPort, softVersion)rest.setAccount(accountSid, accountToken)rest.setAppId(appId)result = rest.sendTemplateSMS(to, datas, tempId)return result.get('statusCode')
管理文件:manager.py # coding=utf-8 from flask import Flask from redis import StrictRedis from werkzeug.routing import BaseConverter import os from flask_session import SessionBASE_DIR=os.path.dirname(os.path.abspath(__file__))class HTMLConverter(BaseConverter):regex = '.*'def create_app(config):app=Flask(__name__)app.config.from_object(config)app.url_map.converters['html']=HTMLConverter#session初始化,將session存儲到redis中Session(app)# 創(chuàng)建redis存儲對象redis_store = StrictRedis(host=config.REDIS_HOST, port=config.REDIS_PORT)app.redis = redis_store# 日志處理import loggingfrom logging.handlers import RotatingFileHandlerlogging.basicConfig(level=logging.DEBUG)file_log_handler = RotatingFileHandler(os.path.join(BASE_DIR, "logs/ihome.log"), maxBytes=1024 * 1024 * 100,backupCount=10)formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')file_log_handler.setFormatter(formatter)logging.getLogger().addHandler(file_log_handler)return app
狀態(tài)文件:status_code.py # coding=utf-8 class RET:OK = "0"DBERR = "4001"NODATA = "4002"DATAEXIST = "4003"DATAERR = "4004"SESSIONERR = "4101"LOGINERR = "4102"PARAMERR = "4103"USERERR = "4104"ROLEERR = "4105"PWDERR = "4106"REQERR = "4201"IPERR = "4202"THIRDERR = "4301"IOERR = "4302"SERVERERR = "4500"UNKOWNERR = "4501"ret_map = {RET.OK: u"成功",RET.DBERR: u"數(shù)據(jù)庫查詢錯誤",RET.NODATA: u"無數(shù)據(jù)",RET.DATAEXIST: u"數(shù)據(jù)已存在",RET.DATAERR: u"數(shù)據(jù)錯誤",RET.SESSIONERR: u"用戶未登錄",RET.LOGINERR: u"用戶登錄失敗",RET.PARAMERR: u"參數(shù)錯誤",RET.USERERR: u"用戶不存在或未激活",RET.ROLEERR: u"用戶身份錯誤",RET.PWDERR: u"密碼錯誤",RET.REQERR: u"非法請求或請求次數(shù)受限",RET.IPERR: u"IP受限",RET.THIRDERR: u"第三方系統(tǒng)錯誤",RET.IOERR: u"文件讀寫錯誤",RET.SERVERERR: u"內(nèi)部錯誤",RET.UNKOWNERR: u"未知錯誤", }
模型設(shè)置:models.py主要根據(jù)網(wǎng)頁來尋找設(shè)置對象 # coding=utf-8 from flask_sqlalchemy import SQLAlchemy from datetime import datetime from werkzeug.security import generate_password_hash,check_password_hash from flask import current_appdb=SQLAlchemy()class BaseModel(object):create_time=db.Column(db.DATETIME,default=datetime.now())update_time=db.Column(db.DATETIME,default=datetime.now(),onupdate=datetime.now())def add_update(self):db.session.add(self)db.session.commit()def delete(self):db.session.delete(self)db.session.commit()class User(BaseModel,db.Model):__tablename__='ihome_user'id=db.Column(db.INTEGER,primary_key=True)phone=db.Column(db.String(11),unique=True)pwd_hash=db.Column(db.String(200))name=db.Column(db.String(30),unique=True)avatar=db.Column(db.String(100))id_name=db.Column(db.String(30))id_card=db.Column(db.String(18),unique=True)houses=db.relationship('House',backref='user')orders=db.relationship('Order',backref='user')#讀@propertydef password(self):return ''#寫@password.setterdef password(self,pwd):self.pwd_hash=generate_password_hash(pwd)#對比def check_pwd(self,pwd):return check_password_hash(self.pwd_hash,pwd)def to_basic_dict(self):return {'id':self.id,'avatar':current_app.config['QINIU_URL']+self.avatar if self.avatar else '','name':self.name,'phone':self.phone}def to_auth_dict(self):return {'id_name':self.id_name,'id_card':self.id_card}ihome_house_facility = db.Table("ihome_house_facility",db.Column("house_id", db.Integer, db.ForeignKey("ihome_house.id"), primary_key=True), # 房屋編號db.Column("facility_id", db.Integer, db.ForeignKey("ihome_facility.id"), primary_key=True) # 設(shè)施編號 )class House(BaseModel, db.Model):"""房屋信息"""__tablename__ = "ihome_house"id = db.Column(db.Integer, primary_key=True) # 房屋編號# 房屋主人的用戶編號user_id = db.Column(db.Integer, db.ForeignKey("ihome_user.id"), nullable=False)# 歸屬地的區(qū)域編號area_id = db.Column(db.Integer, db.ForeignKey("ihome_area.id"), nullable=False)title = db.Column(db.String(64), nullable=False) # 標(biāo)題price = db.Column(db.Integer, default=0) # 單價,單位:分address = db.Column(db.String(512), default="") # 地址room_count = db.Column(db.Integer, default=1) # 房間數(shù)目acreage = db.Column(db.Integer, default=0) # 房屋面積unit = db.Column(db.String(32), default="") # 房屋單元, 如幾室?guī)讖dcapacity = db.Column(db.Integer, default=1) # 房屋容納的人數(shù)beds = db.Column(db.String(64), default="") # 房屋床鋪的配置deposit = db.Column(db.Integer, default=0) # 房屋押金min_days = db.Column(db.Integer, default=1) # 最少入住天數(shù)max_days = db.Column(db.Integer, default=0) # 最多入住天數(shù),0表示不限制order_count = db.Column(db.Integer, default=0) # 預(yù)訂完成的該房屋的訂單數(shù)index_image_url = db.Column(db.String(256), default="") # 房屋主圖片的路徑# 房屋的設(shè)施facilities = db.relationship("Facility", secondary=ihome_house_facility)images = db.relationship("HouseImage") # 房屋的圖片orders=db.relationship('Order',backref='house')def to_dict(self):return {'id':self.id,'title':self.title,'image':current_app.config['QINIU_URL']+self.index_image_url if self.index_image_url else '','area':self.area.name,'price':self.price,'create_time':self.create_time.strftime('%Y-%m-%d %H:%M:%S'),'avatar':current_app.config['QINIU_URL']+self.user.avatar if self.user.avatar else '','room':self.room_count,'order_count':self.order_count,'address':self.address}def to_full_dict(self):return {'id':self.id,'user_avatar':current_app.config['QINIU_URL']+self.user.avatar if self.user.avatar else '','user_name':self.user.name,'price':self.price,'address':self.area.name+self.address,'room_count':self.room_count,'acreage':self.acreage,'unit':self.unit,'capacity':self.capacity,'beds':self.beds,'deposit':self.deposit,'min_days':self.min_days,'max_days':self.max_days,'order_count':self.order_count,'images':[current_app.config['QINIU_URL']+image.url for image in self.images],'facilities':[facility.to_dict() for facility in self.facilities],}class HouseImage(BaseModel, db.Model):"""房屋圖片"""__tablename__ = "ihome_house_image"id = db.Column(db.Integer, primary_key=True)# 房屋編號house_id = db.Column(db.Integer, db.ForeignKey("ihome_house.id"), nullable=False)url = db.Column(db.String(256), nullable=False) # 圖片的路徑class Facility(BaseModel, db.Model):"""設(shè)施信息"""__tablename__ = "ihome_facility"id = db.Column(db.Integer, primary_key=True) # 設(shè)施編號name = db.Column(db.String(32), nullable=False) # 設(shè)施名字css = db.Column(db.String(30), nullable=False) # 設(shè)施展示的圖標(biāo)def to_dict(self):return {'id':self.id,'name':self.name,'css':self.css}def to_house_dict(self):return {'id':self.id}class Area(BaseModel, db.Model):"""城區(qū)"""__tablename__ = "ihome_area"id = db.Column(db.Integer, primary_key=True) # 區(qū)域編號name = db.Column(db.String(32), nullable=False) # 區(qū)域名字houses = db.relationship("House", backref="area") # 區(qū)域的房屋def to_dict(self):return {'id':self.id,'name':self.name}class Order(BaseModel,db.Model):__tablename__ = "ihome_order"id = db.Column(db.Integer, primary_key=True)user_id = db.Column(db.Integer, db.ForeignKey("ihome_user.id"), nullable=False)house_id = db.Column(db.Integer, db.ForeignKey("ihome_house.id"), nullable=False)begin_date = db.Column(db.DateTime, nullable=False)end_date = db.Column(db.DateTime, nullable=False)days = db.Column(db.Integer, nullable=False)house_price = db.Column(db.Integer, nullable=False)amount = db.Column(db.Integer, nullable=False)status = db.Column(db.Enum("WAIT_ACCEPT", # 待接單,"WAIT_PAYMENT", # 待支付"PAID", # 已支付"WAIT_COMMENT", # 待評價"COMPLETE", # 已完成"CANCELED", # 已取消"REJECTED" # 已拒單),default="WAIT_ACCEPT", index=True)comment = db.Column(db.Text)def to_dict(self):return {'order_id':self.id,'house_title':self.house.title,'image':current_app.config['QINIU_URL']+self.house.index_image_url if self.house.index_image_url else '','create_date':self.create_time.strftime('%Y-%m-%d'),'begin_date':self.begin_date.strftime('%Y-%m-%d'),'end_date':self.end_date.strftime('%Y-%m-%d'),'amount':self.amount,'days':self.days,'status':self.status,'comment':self.comment} 模型設(shè)定好之后,執(zhí)行數(shù)據(jù)庫遷移
2.視圖:user_views.py #coding=utf-8 import random import reimport logging from flask import Blueprint, jsonify from flask import current_app from flask import make_response from flask import request from flask import session from qiniu_sdk import put_qiniufrom captcha.captcha import captcha from models import User from status_code import RET, ret_map from ytx_sdk.ytx_send import sendTemplateSMS from my_decorators import is_loginuser_blueprint=Blueprint('user',__name__)#驗證碼 @user_blueprint.route('/yzm') def yzm():name,text,image=captcha.generate_captcha()session['image_yzm']=textresponse=make_response(image)response.headers['Content-Type']='image/jpeg'return response#短信發(fā)送設(shè)置 @user_blueprint.route('/send_sms') def send_sms():#接收請求的數(shù)據(jù)dict=request.argsmobile=dict.get('mobile')imageCode=dict.get('imageCode')#驗證參數(shù)是否存在if not all([mobile,imageCode]):return jsonify(code=RET.PARAMERR,msg=ret_map[RET.PARAMERR])#驗證手機號格式是否正確if not re.match(r'^1[345789]\d{9}$',mobile):return jsonify(code=RET.PARAMERR,msg=u'手機號格式不正確')#驗證手機號是否存在if User.query.filter_by(phone=mobile).count():return jsonify(code=RET.PARAMERR,msg=u'手機號已存在')#驗證圖片驗證碼if imageCode!=session['image_yzm']:return jsonify(code=RET.PARAMERR,msg=u'圖片驗證碼錯誤')#通過云通訊函數(shù)進(jìn)行短信發(fā)送sms_code=random.randint(1000,9999)session['sms_yzm']=sms_codeprint(sms_code)result='000000'# result=sendTemplateSMS(mobile,[sms_code,'5'],1)#根據(jù)云通訊返回的結(jié)果進(jìn)行相應(yīng)if result=='000000':return jsonify(code=RET.OK,msg=ret_map[RET.OK])else:return jsonify(code=RET.UNKOWNERR,msg=u'短信發(fā)送失敗')#用戶注冊 @user_blueprint.route('/',methods=["POST"]) def user_register():#接收參數(shù)dict=request.formmobile=dict.get('mobile')imagecode=dict.get('imagecode')phonecode=dict.get('phonecode')password=dict.get('password')password2=dict.get('password2')#驗證參數(shù)是否存在if not all([mobile,imagecode,phonecode,password,password2]):return jsonify(code=RET.PARAMERR,msg=ret_map[RET.PARAMERR])#驗證圖片驗證碼if imagecode!=session['image_yzm']:return jsonify(code=RET.PARAMERR,msg=u'圖片驗證碼錯誤')#驗證短信驗證碼if int(phonecode)!=session['sms_yzm']:return jsonify(code=RET.PARAMERR,msg=u'短信驗證碼錯誤')#驗證手機號格式是否正確if not re.match(r'^1[345789]\d{9}$',mobile):return jsonify(code=RET.PARAMERR,msg=u'手機格式錯誤')#驗證手機號是否存在if User.query.filter_by(phone=mobile).count():return jsonify(code=RET.PARAMERR,msg=u'手機號碼存在')#保存用戶對象user=User()user.phone=mobileuser.name=mobileuser.password=passwordtry:user.add_update()return jsonify(code=RET.OK,msg=ret_map[RET.OK])except:logging.ERROR(u'用戶注冊更新數(shù)據(jù)庫失敗,手機號:%s,密碼:%s'%(mobile,password))return jsonify(code=RET.DBERR,msg=ret_map[RET.DBERR])@is_login @user_blueprint.route('/',methods=['GET']) def user_my():#獲取當(dāng)前登錄的用戶user_id=session['user_id']#查詢當(dāng)前用戶的頭像/用戶名/手機號/并返回user=User.query.get(user_id)return jsonify(user=user.to_basic_dict())@is_login #個人信息獲取用戶名 @user_blueprint.route('/auth',methods=['GET']) def user_auth():#獲取當(dāng)前登錄用戶的編號user_id=session['user_id']#根據(jù)編號查詢當(dāng)前用戶user=User.query.get(user_id)#返回用戶的真實姓名,身份證號return jsonify(user.to_auth_dict())@is_login #上傳頭像 @user_blueprint.route('/',methods=['PUT']) def user_profile():dict=request.formif 'avatar1' in dict:try:#獲取頭像文件f1=request.files['avatar']# print(f1)# print(type(f1))# from werkzeug.datastructures import FileStorage#mime-type:國際規(guī)范,表示文件的類型,如text/html,text/xml,image/png,image/jpeg..if not re.match('image/.*',f1.mimetype):return jsonify(code=RET.PARAMERR)except:return jsonify(code=RET.PARAMERR)# 上傳到七牛云# access_key = 'H999S3riCJGPiJOity1GsyWufw3IyoMB6goojo5e'# secret_key = 'uOZfRdFtljIw7b8jr6iTG-cC6wY_-N19466PXUAb'# # 空間名稱# bucket_name = 'itcast20171104'url=put_qiniu(f1)#如果未出錯#保存用戶的頭像信息try:user=User.query.get(session['user_id'])user.avatar=urluser.add_update()except:logging.ERROR(u'數(shù)據(jù)庫訪問失敗')return jsonify(code=RET.DBERR)# 則返回圖片信息return jsonify(code=RET.OK,url=current_app.config['QINIU_URL'] + url)elif 'name' in dict:#修改用戶名name=dict.get('name')#判斷用戶名是否存在if User.query.filter_by(name=name).count():return jsonify(code=RET.DATAEXIST)else:user=User.query.get(session['user_id'])user.name=nameuser.add_update()return jsonify(code=RET.OK)else:return jsonify(code=RET.PARAMERR,msg=ret_map[RET.PARAMERR])@is_login #實名認(rèn)證 @user_blueprint.route('/auth',methods=['PUT']) def user_auth_set():#接受參數(shù)dict=request.formid_name=dict.get('id_name')id_card=dict.get('id_card')#驗證參數(shù)合法性if not all([id_name,id_card]):return jsonify(code=RET.PARAMERR,msg=ret_map[RET.SESSIONERR])#驗證身份合法性if not re.match(r'^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$', id_card):return jsonify(code=RET.PARAMERR, msg=ret_map[RET.PARAMERR])#判斷身份證號是否存在#修改數(shù)據(jù)對象try:user=User.query.get(session['user_id'])except:logging.ERROR(u'查詢用戶失敗')return jsonify(code=RET.DBERR)try:user.id_card=id_carduser.id_name=id_nameuser.add_update()except:logging.ERROR(u'修改用戶姓名/身份證號失敗')return jsonify(code=RET.DBERR)#返回數(shù)據(jù)return jsonify(code=RET.OK)#用戶注冊 @user_blueprint.route('/session',methods=['POST']) def user_login():#接收參數(shù)dict=request.formmobile=dict.get('mobile')password=dict.get('password')#驗證非空if not all([mobile,password]):return jsonify(code=RET.PARAMERR,msg=ret_map[RET.PARAMERR])#驗證手機號格式是否正確if not re.match(r'^1[345789]\d{9}$',mobile):return jsonify(code=RET.PARAMERR,msg=u'手機號格式錯誤')#數(shù)據(jù)處理try:user=User.query.filter_by(phone=mobile).first()except:logging.ERROR('用戶登錄--數(shù)據(jù)庫出錯')return jsonify(code=RET.DBERR,msg=ret_map[RET.DBERR])#判斷手機號是否存在if user:#判斷密碼是否正確if user.check_pwd(password):session['user_id']=user.idreturn jsonify(code=RET.OK,msg=u'ok')else:return jsonify(code=RET.PARAMERR,msg=u'密碼不正確')else:return jsonify(code=RET.PARAMERR,mag=u'手機號不存在')#用戶登錄 @user_blueprint.route('/session',methods=['GET']) def user_is_login():if 'user_id' in session:user=User.query.filter_by(id=session['user_id']).first()return jsonify(code=RET.OK,name=user.name)else:return jsonify(code=RET.DATAERR)#用戶退出 @user_blueprint.route('/session',methods=['DELETE']) def user_logout():session.clear()return jsonify(code=RET.OK)
總結(jié)
以上是生活随笔為你收集整理的Flask框架项目实例:**租房网站(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu 16.04系统中nvida
- 下一篇: 自动化运维Shell课堂笔记