django批量导入xml数据


Posted in Python onOctober 16, 2016

django后台批量导入数据

在生产环境中,往往数据不是几条或者几百条,那么举个例子,将公司所有员工员工号或者帐号密码导入进后台,那就不建议你去后台一条条记录去添加了

如何从xml中批量导入svn记录

第一步:

为数据建立模型

@python_2_unicode_compatible
class SVNLog(models.Model):

  vision = models.IntegerField(verbose_name=u"修订版本", blank=False, null=False,)
  author = models.CharField(verbose_name=u"作者", max_length=60, blank=True, null=True)
  date = models.DateTimeField(verbose_name=u"修订时间",null=True )
  msg = models.TextField(verbose_name=u"注释消息", blank=False, null=False, default=u"")
  paths = models.TextField(verbose_name=u"影响的文件", blank=False, null=False, default=u"")
  created_time = models.DateTimeField(verbose_name=u"创建时间", auto_now_add=True, )
  update_time = models.DateTimeField(verbose_name=u"修改时间", auto_now=True, )

  class Meta:
    ordering = ['revision']

  def __str__(self):
    return u'r%s' % (self.revision or u"", )

既然建立好了模型,那我们再去建立接受我们xml文件的models

@python_2_unicode_compatible
class ImportLogFile(models.Model):

  LogFile = models.FileField(upload_to='LogFile')
  FileName = models.CharField(max_length=50, verbose_name=u'文件名')

  class Meta:
    ordering = ['FileName']

  def __str__(self):
    return self.FileName

ok,以上代码我们定义好了数据和上传文件的model

同步数据库

python manage.py makemigrations
python manage.py migrate

接着我们去修改admin.py 让我们可以从后台上传文件,

class ImportLogAdmin(admin.ModelAdmin):

  list_display = ('LogFile','FileName',)
  list_filter = ['FileName',]

  def save_model(self, request, obj, form, change):

    re = super(YDImportLogAdmin,self).save_model(request, obj, form, change)
    update_svn_log(self, request, obj, change)
    return re

注意上面代码里的save_model,这里才是关键,在这里我重写了ModelAdmin里的save_model方法
因为我们要把上传文件,读取文件,解析文件,操作数据库合为一步来操作,大家可以打开debug,在上传文件的时候,返回参数的obj里包括了文件上传的路径,这个路径也是下一步我们操作解析文件的关键,好了我们在这个app文件夹下新建一个utils.py 用来操作我们操作文件和数据库的工具类,为了简单我写成了函数如下
先贴一下我们要测试的xml文件

<?xml version="1.0" encoding="UTF-8"?>
<log>
<logentry
  revision="2">
<author>qwert</author>
<date>2016-09-27T07:16:37.396449Z</date>
<paths>
<path
  action="A"
  prop-mods="false"
  text-mods="true"
  kind="file">/aaa/README
  </path>
</paths>
<msg>20160927 151630</msg>
</logentry>


<logentry
  revision="1">
<author>VisualSVN Server</author>
<date>2016-09-20T05:03:12.861315Z</date>
<paths>
<path
  action="A"
  prop-mods="false"
  text-mods="false"
  kind="dir">/branches</path>
<path
  action="A"
  prop-mods="false"
  text-mods="false"
  kind="dir">/tags</path>
<path
  action="A"
  prop-mods="false"
  text-mods="false"
  kind="dir">/trunk</path>
</paths>
<msg>hello word</msg>
</logentry>
</log>

输出结果格式

r2 | qwer | 2016-09-27 15:16:37 +0800 (二, 27 9 2016) | 1 line
Changed paths:
  A /xxx/README

20160927 151630
------------------------------------------------------------------------
r1 | VisualSVN Server | 2016-09-20 13:03:12 +0800 (二, 20 9 2016) | 1 line
Changed paths:
  A /branches
  A /tags
  A /trunk

Initial structure.
from .models import SVNLog
import xmltodict
def update_svn_log(self, request, obj, change):

  headers = ['r','a','d','m','p']
  filepath = obj.LogFile.path
  xmlfile = xmltodict.parse(open(filepath, 'r'))
  xml_logentry = xml.get('log').get('logentry')
  info_list = []
  pathlist = []
  sql_insert_list = []
  sql_update_list = []
  for j in xml:
    data_dict = {}
    # get path
    paths = j.get('paths').get('path')
    if isinstance(paths,list):
      for path in paths:
        action = path.get('@action')
        pathtext = path.get('#text')
        pathtext = action + ' ' + pathtext
        pathlist.append(pathtext)
        
      _filelist = u'\n'.join(pathlist)
      _paths = u"Changed paths:\n {}".format(_filelist)
      print _paths
    else:
      _filelist = paths.get('@action') + ' ' + paths.get('#text')
      _paths = u"Changed paths:\n {}".format(_filelist)
      print _paths
    # get revision
    vision = j.get('@vision')
    # get auth
    author = j.get('author')
    #get date
    date = j.get('date')
    #get msg
    msg = j.get('msg')

    data_dict[headers[0]] = int(vision)
    data_dict[headers[1]] = author
    data_dict[headers[2]] = date
    data_dict[headers[3]] = msg
    data_dict[headers[4]] = _paths
    info_list.append(data_dict)

  _svnlog = SVNLog.objects.filter().order_by('-vision').first()
  _last_version = _svnlog.vision if _svnlog else 0

  for value in info_list:
    vision = value['r']
    author = value['a']
    date = value['d']
    msg = value['m']
    paths = value['p']
    print vision,author
    _svnlog = YDSVNLog.objects.filter().order_by('-revision').first()
    _last_version = _svnlog.revision if _svnlog else 0
    if vision > _last_version:
      sql_insert_list.append(SVNLog(revision=revision, author=author, date=date, msg = msg, paths = paths))
    else:
      sql_update_list.append(SVNLog(revision=revision, author=author, date=date, msg = msg, paths = paths))

  SVNLog.objects.bulk_create(sql_insert_list)
  SVNLog.objects.bulk_create(sql_update_list)

我们使用的xmltodict这个第三方库来解析xml,他把内容解析成了高效率的orderdict类型,就是有序列的字典
这个xml中比较复杂的是那个paths里的path,因为这个xml中包含两个元素,第一个元素的path只含有一个path,第二个元素中的paths包含有三个path,因此我们在解析获取的时候需要判断一下

paths = j.get('paths').get('path')
if isinstance(paths,list):
  pass

我们判断这个path是不是一个list类型的,如果是,那我们就按照list的方式来处理,如果不是,那我们就按单个的方式来处理,获取之后按照输出结果格式处理下结果然后获取其他内容

revision = j.get('@vision')
# get auth
author = j.get('author')
#get date
date = j.get('date')
#get msg
msg = j.get('msg')

最后我们将获取到的元素存在字典里
在循环中判断当前的版本号和数据库中的版本号,
如果比原来的小,那么我们执行更新操作,反之执行插入操作

最后使用了bulk_create来操作数据库,这样避免了循环中每次都进行数据库操作造成的资源浪费

Python 相关文章推荐
python 解析XML python模块xml.dom解析xml实例代码
Feb 07 Python
Python 通过URL打开图片实例详解
Jun 01 Python
python绘制中国大陆人口热力图
Nov 07 Python
使用python来调用CAN通讯的DLL实现方法
Jul 03 Python
Python使用matplotlib实现交换式图形显示功能示例
Sep 06 Python
python通过移动端访问查看电脑界面
Jan 06 Python
Python+Dlib+Opencv实现人脸采集并表情判别功能的代码
Jul 01 Python
Python实现爬取网页中动态加载的数据
Aug 17 Python
如何基于Django实现上下文章跳转
Sep 16 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
Sep 30 Python
用python修改excel表某一列内容的操作方法
Jun 11 Python
Python实现Matplotlib,Seaborn动态数据图
May 06 Python
python中os模块详解
Oct 14 #Python
python append、extend与insert的区别
Oct 13 #Python
CentOS6.5设置Django开发环境
Oct 13 #Python
Python判断某个用户对某个文件的权限
Oct 13 #Python
python使用str &amp; repr转换字符串
Oct 13 #Python
PYTHON 中使用 GLOBAL引发的一系列问题
Oct 12 #Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
Oct 12 #Python
You might like
ubuntu下编译安装xcache for php5.3 的具体操作步骤
2013/06/18 PHP
php+webSoket实现聊天室示例代码(附源码)
2017/02/17 PHP
PHP 实现页面静态化的几种方法
2017/07/23 PHP
浅谈php://filter的妙用
2019/03/05 PHP
laravel通过a标签从视图向控制器实现传值
2019/10/15 PHP
Apache+PHP+MySQL搭建PHP开发环境图文教程
2020/08/06 PHP
新闻内页-JS分页
2006/06/07 Javascript
JavaScript中去掉数组中的重复值的实现方法
2011/08/03 Javascript
使用jQuery+HttpHandler+xml模拟一个三级联动的例子
2011/08/09 Javascript
jQuery-serialize()输出序列化form表单值的方法
2012/12/26 Javascript
JQuery入门—编写一个简单的JQuery应用案例
2013/01/03 Javascript
js如何取消事件冒泡
2013/09/23 Javascript
js格式化时间和js格式化时间戳示例
2014/02/10 Javascript
用js读、写、删除Cookie代码续篇
2014/12/03 Javascript
深入理解JavaScript系列(35):设计模式之迭代器模式详解
2015/03/03 Javascript
jQuery实现仿腾讯视频列表分页效果的方法
2015/08/07 Javascript
javascript中去除数组重复元素的实现方法【实例】
2016/04/12 Javascript
jQuery获取当前点击的对象元素(实现代码)
2016/05/19 Javascript
关于Bootstrap按钮组件消除黄框的方法
2017/05/19 Javascript
vue实现点击当前标签高亮效果【推荐】
2018/06/22 Javascript
基于Angularjs-router动态改变Title值的问题
2018/08/30 Javascript
Vue商品控件与购物车联动效果的实例代码
2019/07/21 Javascript
jquery向后台提交数组的代码分析
2020/02/20 jQuery
[03:07]完美世界DOTA2联赛PWL DAY10 决赛集锦
2020/11/11 DOTA
Python常用小技巧总结
2015/06/01 Python
详细整理python 字符串(str)与列表(list)以及数组(array)之间的转换方法
2019/08/30 Python
一款纯css3实现的圆形旋转分享按钮旋转角度可自己调整
2014/09/02 HTML / CSS
html5通过canvas实现刮刮卡效果示例分享
2014/01/27 HTML / CSS
德国家具、照明、家居用品网上商店:Wayfair.de
2020/02/13 全球购物
人事部经理岗位职责
2014/03/07 职场文书
党的群众路线教育实践方案
2014/05/11 职场文书
法人委托书范本
2014/09/15 职场文书
开国大典观后感
2015/06/04 职场文书
英文投诉信格式
2015/07/03 职场文书
使用JS实现简易计算器
2021/06/14 Javascript
OpenCV实现常见的四种图像几何变换
2022/04/01 Python