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

背景:目前市面上有很多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. Java位操作

    无论说是在哪一门计算机语言,位操作运算对于计算机来说肯定是最高效的,因为计算机的底层是按就是二进制,而位操作就是为了节省开销,加快程序的执行速度,以及真正的实现对数的二进制操作.      使用位操作 ...

  2. 【我的漫漫跨考路】数据结构之单链表线性存储实现 Beta

    正文之前 昨天晚上阶段性的完成了一部分数学的复习,所以今天打算撸一撸代码,然后发现提电脑忘指针.所以自己磕磕盼盼,对照了一下网上的代码,总算把线性存储单链表的数据类型实现,给自己写出来了. 废话不多说 ...

  3. BFS:noi6044鸣人与佐助

    PS:一道XX到我心态崩溃的好(傻逼)题. 先粘题目: 佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢? 已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置.地图上的每个位置都可以走到,只不过 ...

  4. 从JSON数据源导入数据(未完)

  5. laravel 中使用ajax和vue总结

    最近写一个项目是基于laravel框架的,这个框架传言是为艺术而创作的优雅框架,简洁分明的风格,很吸引我,所以最近研究比较多.本次就是基于该框架然后将Vue插件加入实现一定的功能,vue插件本身强大, ...

  6. 正则表达式(即:匹配模式Pattern)

    通过学习<正则表达式-Regular-Expression-Tutorial.pdf>这份文档,对正则表达式有了很好的了解,原因只有1个--这份文档写得太好了. 它的下载地址是:http: ...

  7. IPython使用学习笔记

    学习<利用python进行数据分析>第三章 IPython:一种交互式计算和开发环境的笔记,共享给大家,同时为自己作为备忘用. 安装ipython用pip即可.ps.博主用的是win7系统 ...

  8. MATLAB批量读入图片

    %% import pictures, and save into images{img_num} function [images, img_num, vertical_border] = impo ...

  9. CSS3自定义滚动条样式

    原文地址:→传送门 写在前面 滚动条是个很常见的东东,不过某些浏览器自带的滚动条确实不太好看啊,下面可以作为学习,探讨下自定义滚动条的实现,这样你的滚动条就可以美美的啦.但是,也只能玩玩,因为只针对w ...

  10. eclipse中配置spring环境

    初识Spring框架 1.简单使用 eclipse中配置Spring环境,如果是初学的话,只需要在eclipse中引入几个jar包就可以用了, 在普通java project项目目录下,建一个lib文 ...