最近楼主加班 喽, 好久没有更新我的博客了,哎,一言难尽,废话我就不说了,来开始上精华。

背景:目前市面上有很多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

这是数据库相关的,

 数据库配置相关的

 from sqlalchemy import  create_engine
from sqlalchemy.orm import scoped_session,sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine=create_engine('sqlite:///shebei.db',convert_unicode=True)
Base=declarative_base()
db_session=scoped_session(sessionmaker(bind=engine))
def create_all():
Base.metadata.create_all(engine)
def drop_all():
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的类,,进行了一些简单的自定义,然后后续可以用这个,

进过两周的开发,已经形成了成熟的,

python tornado 实现类禅道系统的更多相关文章

  1. 用python实现自动化登录禅道系统 设置定时器自动执行脚本

    由于各种原因,我想试下用python实现自动登录禅道系统,并且每天定时执行.(本人第一次接触自动化,在大佬眼中门槛都没摸到的类型) 首先缕清思路: 1.实现自动登录禅道系统,用selenium实现2. ...

  2. Linux下禅道系统的搭建

    说明: 禅道系统的搭建,分两大部分 1.xampp环境的搭建 2.禅道系统的搭建 *********************************************************** ...

  3. python数据统计之禅道bug统计

    背景 通过定期输出 每条产品的 BUG 情况,以此来反馈开发解决问题.测试跟进问题的情况:钉钉群推送提醒开发及时解决 以此我这边开始着手准备编写一个小工具,最终达到目的:自动定期发送统计报告,报告维度 ...

  4. windows系统搭建禅道系统(BUG管理工具)

    我也呆过三家公司了,用过的BUG管理工具也是五花八门的,常见的一般有禅道,bugzilla,jira等 个人比较推荐禅道,功能强大,主页的说明文档也是相当详细,最主要的是,用的人比较多,出现使用问题一 ...

  5. 腾讯云服务器ubuntu18.04部署禅道系统

    踩了不少坑,记录一下. 基于ubuntu18.04 一开始按照网上的攻略下载安装包 ZenTaoPMS.9.8.3.zbox_64.tar.gz,通过FileZilla传到linux的/opt下面,解 ...

  6. Jmeter跨线程组传递cookie,以禅道系统为例;BeanShell的存取数据的使用

    先看下脚本结构: 思路:将登陆请求放在setUp Thread Group中:把登陆后的cookie通过正则提取出来,然后存为全局变量,传递到下一个线程组中: 第一步:添加setUp Thread G ...

  7. 20181017 work - Inno Setup 禅道 xp系统 楷体字体 win10倒计时 nwjs chosen

    win10 闹钟和时钟 用个倒计时 Inno Setup 编译器 把应用程序打包成安装程序 nwjs-v0.14.7-win-ia32 XP专用 chrome用的49的版本 作用是把浏览器地址的程序打 ...

  8. 禅道 Rest API 开发

    在老的 PHP 系统中使用 PHP 5.3以后的库 所谓老的系统,是指没有使用PHP 5.3以上命名空间(namespace)特性编码的系统. 但是,只要你的系统运行在 PHP 5.3及以上的环境,在 ...

  9. 禅道PMS兼容redmine用户认证接口

    项目地址:https://github.com/web3d/zentao-redmine-userauth zentao-redmine-userauth 做了一个基本的用户认证接口,兼容redmin ...

随机推荐

  1. metasploit快速入门

    今天没上班,在小黑屋里看了一个一百多页的书<metasploit新手指南>,在此将笔记分享给大家.欢迎大家批评指正,共同学习进步.     metasploit新手指南 笔记 kali 0 ...

  2. Java常用文件操作-1

    在我们的实际工作中经常会用到的文件操作,再此,将工作中碰到的做一个记录,以便日后查看. 1.复制文件夹到新文件夹下 /** * 复制文件夹下所有文件到指定路径 *@param oldPath *@pa ...

  3. 关于Wifi室内定位应用中的一些问题:

    公司目前在办公室内布设了一套室内定位的实验环境,用的是华为路由器,采用的算法是基于信号强度的RSSI算法.公司目前希望能使用这套设备得到无线网络覆盖范围下的所有移动设备(对应每个人)的MAC地址,同时 ...

  4. java出现The type java.lang.Object cannot be resolved. It is indirectly referenced.....解决办法

    当你在Eclipse引用不同版本JDK工程时会发生该问题.由于你开发环境中应用了多个版 本的JDK 或JRE导致的.Eclipse会按照最初的开发环境默认选择对应的Jre.如Eclipse上有jdk1 ...

  5. TP3.2二级导航与高亮显示

    闲来无事,记记笔记 二级导航的实现,就是一个二级联动,嗯 先来看看数据库,我喜欢用一个表,表多了就不好玩了 二级代号取一级导航的代号就行了,做个简单的栗子: 代码部分: 看控制器,大头在这: < ...

  6. 【CPP】字符串和格式化输入输出

    前导:数组(array),字符串转换说明符%s,定义符号常量,,strlen()获取字符串长度,. [字符串] 没有专门的字符串类型,是吧他存储在字符型数组中,数组最后一个字符为空字符'\0',c用他 ...

  7. Lucene搜索引擎+HDFS+MR完成垂直搜索

    介于上一篇的java实现网络爬虫基础之上,这一篇的思想是将网络收集的数据保存到HDFS和数据库(Mysql)中:然后用MR对HDFS的数据进行索引处理,处理成倒排索引:搜索时先用HDFS建立好的索引来 ...

  8. 关于write()和fsync()

    --关于write()和fsync()   ----------------------------转载 write ssize_t write(int fd, const void *buf, si ...

  9. WTL--SDI框架分析

    创建SDI产生的基本类:CMainFrame,CAboutDlg和CWTLView(WTL为项目名). 由此可见,不同于MFC,WTL少了文档类,它的结构就只有简单的窗口类和视图类,而至于串行化(MF ...

  10. 禁止将http请求强制转换为https请求

    近期遇到一个问题,在谷歌浏览器里发起的http请求都会被转化为https请求,但在safari里面不会被转化,所以暂时只能用Safari浏览器进行调试,后来还查看了为什么http被强制转化为https ...