python tornado 實現類禪道系統

来源:http://www.cnblogs.com/leiziv5/archive/2017/09/16/7532344.html
-Advertisement-
Play Games

最近樓主加班 嘍, 好久沒有更新我的博客了,哎,一言難盡,廢話我就不說了,來開始上精華。 背景:目前市面上有很多bug管理工具,但是各有各的特點,最著名,最流行的就是禪道,一個偶然的機會接觸到了python ,學到tornado後,就想著去怎麼去用到實處,後來發現自己公司的除了禪道就記錄bug沒有什 ...


   最近樓主加班 嘍, 好久沒有更新我的博客了,哎,一言難盡,廢話我就不說了,來開始上精華。

背景:目前市面上有很多bug管理工具,但是各有各的特點,最著名,最流行的就是禪道,一個偶然的機會接觸到了python ,學到tornado後,就想著去怎麼去用到實處,後來發現自己公司的除了禪道就記錄bug沒有什麼可以用的工具了。

語言:python3 第三庫 :tornado,qiniu(用於雲存儲文件),資料庫用sqlite

why  use tornado?很多人其實會這麼問我,我感覺tornado可以實現非同步,雖然現在代碼還沒有用到非同步,我感覺還是很不錯的框架,值得學習,現在很多公司都在用,個人感覺這是一個不錯的,值得我們大家去學習的框架。

來看看我的需求文檔

大題是這麼的輪廓,那麼拿到這個的時候,我會進行需求分析,

需要什麼樣的資料庫, 數據模型之間的關係,雖然現在還是有很多地方是寫死的還沒有進行搜索功能的設置,但是我相信,有了現在這個demo

那麼我開始來設計下我主要會結構

handlsers 存放類似flask的views

models存資料庫相關的,

static存放靜態

template存放模板

untils存放公共庫

setting 配置文件

urls url地址映射

run 運行文件。

 那麼我來開始設計我的數據,其實我的數據模型也是一波三折的。

選擇用了sqlalchemy,之前用過flask的sqlalchemy感覺不錯

from models.dataconfig import db_session,Base,create_all
from sqlalchemy import  Column,Integer,DateTime,Boolean,String,ForeignKey,desc,asc,Text
from sqlalchemy.orm import  relationship,backref
from untils.common import encrypt
import datetime
class User(Base):
	__tablename__='users'
	id=Column(Integer(),primary_key=True)
	username=Column(String(64),unique=True,index=True)
	email=Column(String(64))
	password=Column(String(64))
	last_logtime=Column(DateTime())
	status=Column(Integer())
	leves=Column(Integer())
	iphone=Column(Integer())
	Projects=relationship('Project',backref='users')
	shebei=relationship('Shebei',backref='users')
	file=relationship('FilePan',backref='users')
	banben=relationship('BanbenWrite',backref='users')
	testresult=relationship('TestResult',backref='users')
	testcase=relationship('TestCase',backref='users')
	buglog=relationship('BugLog',backref='users')
	def __repr__(self):
		return self.username
	@classmethod
	def get_by_id(cls, id):
		item = db_session.query(User).filter(User.id==id).first()
		return item
	@classmethod
	def get_by_username(cls, username):
		item = db_session.query(User).filter(User.username== username).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(Shebei).count()
	@classmethod
	def add_new(cls,username,password,iphone,email,leves):
		new=User(username=username,iphone=iphone,email=email,leves=leves)
		new.password=encrypt(password)
		new.status=0
		db_session.add(new)
		try:
			db_session.commit()
		except:
			db_session.rollback()
class Shebei(Base):
	__tablename__='shebeis'
	id=Column(Integer(),primary_key=True)
	shebei_id=Column(String(32),unique=True)
	shebei_name=Column(String(64))
	shebei_xitong=Column(String(64))
	shebei_xinghao=Column(String(255))
	shebei_jiage=Column(Integer())
	shebei_fapiaobianhao=Column(String(64))
	shebei_quanxian=Column(Boolean())
	shebei_jie=Column(Boolean())
	shebei_shuyu=Column(String())
	shebei_date=Column(DateTime())
	shebei_user=Column(String())
	gou_date=Column(DateTime())
	shebei_status=Column(String(16))
	she_sta=Column(Integer(),default=0)
	ruku_user=Column(Integer(),ForeignKey('users.id'))
	def __repr__(self):
		return self.shebei_name
	@classmethod
	def get_by_name(cls,name):
		item=db_session.query(Shebei).filter(Shebei.shebei_name==name).first()
		return item
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(Shebei).filter(Shebei.id==id).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(Shebei).count()
class TestResult(Base):
	__tablename__='testresults'
	id=Column(Integer(),primary_key=True)
	porject_id=Column(Integer(),ForeignKey('projects.id'))
	creat_time=Column(DateTime())
	bug_first=Column(Integer())
	ceshirenyuan=Column(String(255))
	is_send=Column(Boolean(),default=True)
	filepath=Column(String(64))
	status=Column(Integer(),default=0)
	user_id=Column(Integer(),ForeignKey('users.id'))
	def __repr__(self):
		return self.porject_name
	@classmethod
	def get_by_name(cls,name):
		item=db_session.query(TestResult).filter(TestResult.porject_name==name).first()
		return item
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(TestResult).filter(TestResult.id==id).first()
		return item
	@classmethod
	def get_by_user_id(cls,user_id):
		item=db_session.query(TestResult).filter(TestResult.user_id==user_id).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(TestResult).count()
class BanbenWrite(Base):
	__tablename__='banbens'
	id=Column(Integer(),primary_key=True)
	porject_id=Column(Integer(),ForeignKey('projects.id'))
	creat_time=Column(DateTime(),default=datetime.datetime.now())
	banbenhao=Column(String(32))
	is_xian=Column(Boolean(),default=False)
	is_test=Column(Boolean(),default=False)
	status=Column(Integer())
	user_id=Column(Integer(),ForeignKey('users.id'))
	bugadmin=relationship('BugAdmin',backref='banbens')
	def __repr__(self):
		return self.banbenhao
	@classmethod
	def get_by_name(cls,name):
		item=db_session.query(BanbenWrite).filter(BanbenWrite.porject_name==name).first()
		return item
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(BanbenWrite).filter(BanbenWrite.id==id).first()
		return item
	@classmethod
	def get_by_user_id(cls,user_id):
		item=db_session.query(BanbenWrite).filter(BanbenWrite.user_id==user_id).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(BanbenWrite).count()
class FilePan(Base):
	__tablename__='files'
	id=Column(Integer(),primary_key=True)
	file_fenlei=Column(String(64))
	file_name=Column(String(64))
	down_count=Column(Integer(),default=0)
	creat_time=Column(DateTime(),default=datetime.datetime.now())
	status=Column(Integer(),default=0)
	down_url=Column(String(64))
	is_tui=Column(Boolean(),default=False)
	user_id=Column(Integer(),ForeignKey('users.id'))
	def __repr__(self):
		return self.file_name
	@classmethod
	def get_by_file_name(cls,name):
		item=db_session.query(FilePan).filter(FilePan.file_name==name).first()
		return item
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(FilePan).filter(FilePan.id==id).first()
		return item
	@classmethod
	def get_by_user_id(cls,user_id):
		item=db_session.query(FilePan).filter(FilePan.user_id==user_id).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(FilePan).count()
class BugAdmin(Base):
	__tablename__='bugadmins'
	id=Column(Integer(),primary_key=True)
	porject_id=Column(Integer(),ForeignKey('projects.id'))
	bugname=Column(String(64))
	bugdengji=Column(String(64))
	bugtime=Column(DateTime(),default=datetime.datetime.now())
	bug_miaoshu=Column(String(255))
	ban_id=Column(Integer(),ForeignKey('banbens.id'))
	fujian=Column(String(64))
	is_que=Column(Boolean())
	bug_status=Column(String(64))
	bug_jiejuefangan=Column(String(64))
	bug_send=Column(String(64))
	status=Column(Integer(),default=0)
	bug_log=relationship('BugLog',backref='bugadmins')
	user_id=Column(Integer(),ForeignKey('users.id'))
	def __repr__(self):
		return self.bugname
	@classmethod
	def get_by_bugname(cls,bugname):
		item=db_session.query(BugAdmin).filter(BugAdmin.bugname==bugname).first()
		return item
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(BugAdmin).filter(BugAdmin.id==id).first()
		return item
	@classmethod
	def get_by_porject_name(cls,porject_name):
		item=db_session.query(BugAdmin).filter(BugAdmin.porject_name==porject_name).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(BugAdmin).count()
class TestCase(Base):
	__tablename__='testcases'
	id=Column(Integer(),primary_key=True)
	porject_id=Column(Integer(),ForeignKey('projects.id'))
	casename=Column(String(64))
	case_qianzhi=Column(String())
	case_buzhou=Column(String())
	case_yuqi=Column(String())
	status=Column(Integer(),default=0)
	case_crea_time=Column(DateTime(),default=datetime.datetime.now())
	user_id=Column(Integer(),ForeignKey('users.id'))
	def __repr__(self):
		return self.casename
	@classmethod
	def get_by_project_name(Cls,project_name):
		item=db_session.query(TestCase).filter(TestCase.project_name==project_name).first()
		return item
	@classmethod
	def get_by_casename(Cls,casename):
		item=db_session.query(TestCase).filter(TestCase.casename==casename).first()
		return item
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(TestCase).filter(TestCase.id==id).first()
		return item
	@classmethod
	def get_count(cls):
		return db_session.query(TestCase).count()
class BugLog(Base):
	__tablename__='buglogs'
	id=Column(Integer(),primary_key=True)
	bug_id=Column(Integer(),ForeignKey('bugadmins.id'))
	caozuo=Column(String())
	caozuo_time=Column(DateTime())
	user_id=Column(Integer(),ForeignKey('users.id'))
	def __repr__(self):
		return self.caozuo
	@classmethod
	def get_by_id(Cls,id):
		item=db_session.query(BugLog).filter(BugLog.id==id).first()
		return item
	@classmethod
	def get_by_user_id(Cls,user_id):
		item=db_session.query(BugLog).filter(BugLog.user_id==user_id).first()
		return item
	@classmethod
	def get_by_bug_id(Cls,bug_id):
		item=db_session.query(BugLog).filter(BugLog.bug_id==bug_id).first()
		return item
class Project(Base):
	__tablename__='projects'
	id=Column(Integer(),primary_key=True)
	name=Column(String(64))
	user_id=Column(Integer(),ForeignKey('users.id'))
	bug_log=relationship('BugAdmin',backref='projects')
	banben=relationship('BanbenWrite',backref='projects')
	testresult=relationship('TestResult',backref='projects')
	testcase=relationship('TestCase',backref='projects')
	def __repr__(self):
		return self.name
	@classmethod
	def get_by_id(cls,id):
		item=db_session.query(Project).filter(Project.id==id).first()
		return item 
	@classmethod
	def get_by_name(cls,name):
		item=db_session.query(Project).filter(Project.name==name).first()
		return item

 這是資料庫相關的,

 1 資料庫配置相關的
 2 
 3 from sqlalchemy import  create_engine
 4 from  sqlalchemy.orm import  scoped_session,sessionmaker
 5 from sqlalchemy.ext.declarative import  declarative_base
 6 engine=create_engine('sqlite:///shebei.db',convert_unicode=True)
 7 Base=declarative_base()
 8 db_session=scoped_session(sessionmaker(bind=engine))
 9 def create_all():
10     Base.metadata.create_all(engine)
11 def drop_all():
12     Base.metadata.drop_all(engine)

 

其實在開發的過程中,也遇到了很多阻力,比如下載一直實現不好,比如分頁,也是參照別人的實現的,

分頁公共模塊

class Pagination:
    def __init__(self, current_page, all_item):
        try:
            page = int(current_page)
        except:
            page = 1
        if page < 1:
            page = 1
        all_pager, c = divmod(all_item, 10)
        if int(c) > 0:
            all_pager += 1
        self.current_page = page
        self.all_pager = all_pager
    @property
    def start(self):
        return (self.current_page - 1) * 10
    @property
    def end(self):
        return self.current_page * 10
    def string_pager(self, base_url="/index/"):
        if self.current_page == 1:
            prev = '<li><a href="javascript:void(0);">上一頁</a></li>'
        else:
            prev = '<li><a href="%s%s">上一頁</a></li>' % (base_url, self.current_page - 1,)
        if self.current_page == self.all_pager:
            nex = '<li><a href="javascript:void(0);">下一頁</a></li>'
        else:
            nex = '<li><a href="%s%s">下一頁</a></li>' % (base_url, self.current_page + 1,)
        last = '<li><a href="%s%s">尾頁</a></li>' % (base_url, self.all_pager,)
        str_page = "".join((prev,nex,last))
        return str_page

 

在上傳文件的時候,原來存放在本地,結果呢,下載處理不好,於是乎選擇了七牛,需要到七牛的官網去註冊自己的賬號

from qiniu import Auth,put_file,etag,urlsafe_base64_encode
import qiniu.config
access_key='uVxowDUcYx641ivtUb111WBEI4112L3D117JHNM_AOtskRh4'
secret_key='PdXU9XrXTLtp1N21bhU1Frm1FDZqE1qhjkEaE9d1xVLZ5C'
def sendfile(key,file):
    q=Auth(access_key,secret_key)
    bucket_name='leilei22'
    token = q.upload_token(bucket_name, key)
    ret, info = put_file(token, key, file)
    me= ret['hash']
    f=etag(file)
    if me==f:
        assert_t=True
    else:
        assert_t=False
    return assert_t

 解析Excel,主要用於上傳測試用例

import xlrd,xlwt
from xlutils.copy import copy
def datacel(filepath):
    file=xlrd.open_workbook(filepath)
    me=file.sheets()[0]
    nrows=me.nrows
    porject_id_list=[]
    casename_list=[]
    case_qianzhi_list=[]
    case_buzhou_list=[]
    case_yuqi_list=[]
    for i in range(1,nrows):
        porject_id_list.append(me.cell(i,0).value)
        casename_list.append(me.cell(i,2).value)
        case_qianzhi_list.append(me.cell(i,3).value)
        case_buzhou_list.append(me.cell(i,4).value)
        case_yuqi_list.append(me.cell(i,1).value)
    return porject_id_list,casename_list,case_qianzhi_list,case_buzhou_list,case_yuqi_list

其實這麼現在公共模塊完畢了,其實現在可以著手去開始寫我們的代碼了,主要的代碼,還有靜態界面,因為前後端都是我自己,我的前端其實還是從網上找來的模板,

學習的道路是痛苦的,但是我相信我是可以成功的,

from tornado.web import RequestHandler
from models.model_py import User
class BaseHandler(RequestHandler):
	@property
	def db(self):
		return self.application.db
	def get_current_user(self):
		user_id = self.get_secure_cookie('user_id')
		if not user_id:
			return None
		return User.get_by_id(int(user_id))

 基礎的類集成了RequestHandler的類,,進行了一些簡單的自定義,然後後續可以用這個,

進過兩周的開發,已經形成了成熟的,

源碼已經開源道github

https://github.com/liwanlei/tornado_guanli

 

另外本人提供vip指導,python自動化,python學習上面,python做測試開發上面,我都會提供指導,vip終身有效,現價700,聯繫qq:952943386,稍後會更新qq群,喜歡的朋友可以來,本人也是從一個不懂啥是python到現在能做東西,從15的2k到17的10k+都是辛酸淚,可以與大家一起共勉,提供思路,能夠讓你走的更遠,我也是從白紙一張一步步走來,如果你是新畢業的學生這個也適合你,可以給你指導,但是我能做的就是帶你,但是我不是培訓班,沒有提供就業的機會,我只會在有機會的時候給你推薦,學無止境,此時可能我只能教你一些測試,提供職業指導,我可能以後會帶給你更多。

我是一個大專生,也是一個人奮鬥到今天。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡介 網路無處不在,移動互聯時代也早已到來,單機版程式慢慢的已沒有生命力,所有的程式都要能夠訪問網路,比如 QQ 網路聊天程式、迅雷下載程式等,這些程式都要同網路打交道,本次將與各位小伙伴們分享的就是 Java 中的網路編程—— Socket 通信。 網路基礎知識 兩台電腦要通過網路進行通信,必須 ...
  • 一、添加 devtools 依賴 當配置了 devtools 後,我們在classpath修改任何文件項目都將會自動重啟。 (1)某些資源在更改時不一定需要觸發重新啟動。例如, Thymeleaf 模板可以就地進行編輯。預設情況下更改資源路徑包括了:/META-INF/maven, /META-IN ...
  • 最近做了幾道關於二分法的題目,覺得比較典型,因此拿出來說一說。 首先,先把題目分享一下。 題目描述:上題中講了一個故事,故事大意不用過多關註,有用部分為:某地主有一個大糧倉,這個糧倉容量為 n 個單位,但這個糧倉有個小口,每天會有一部分麻雀過來偷吃糧食,同時地主每天也會從別的地方運來糧食填補。開始的 ...
  • 我是一名建築學的學生,第一次瞭解到Python這門課是選課的時候。說實話,學c語言的時候我學的就並不好,感覺自己並沒有天分。我只是按照我的人才培養方案看課的時候才第一次看到這門課。起初並不知道這門課意味著什麼,就給軟工的朋友打電話咨詢。然後又上百度搜索,感覺還挺有用,就選了這門課。 一個建築生,平時 ...
  • 自己以前從來沒有寫博客的想法,但是學Python,裡面的老師也說了,寫博客可以加深自己的記憶,也能回顧內容。還能給別人參考。挺值的。2017-09-16 一、 Python介紹 python的創始人為吉多·範羅蘇姆(Guido van Rossum)。1989年的聖誕節期間,吉多·範羅蘇姆為了在阿姆 ...
  • 首先分析第一個比較重要的方法 put 方法,源碼如下 分析上面的源碼,我們可以得到下麵的結論: 當我們試圖將一個key-value 調用put方法放入HashMap的時候,首先會調用key的hashCode方法算出該Entry存放的位置,若兩個key的hashCode相同則在table中的存儲位置相 ...
  • 本文通過開發一個應用來學習Android基本概念及構成應用的UI組件。 開發的應用名叫GeoQuiz,它能給出一道道地理知識問題。用戶點擊true或false按鈕回答問題,應用即時做出反饋 第一步請先自行創建一個新項目,目錄如下 1. 用戶界面設計 在XML文件(activity_quiz.xml) ...
  • 基於http://www.cnblogs.com/HAOZHE/p/5276763.html改編寫的關於隨機生成四則運算的小程式 github源碼和工程文件地址:https://github.com/HuChengLing/- 基本要求: 除了整數以外,還能支持真分數的四則運算。 對實現的功能進行描 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...