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使用PyGame模块播放声音的方法
May 20 Python
python re模块findall()函数实例解析
Jan 19 Python
Python之dict(或对象)与json之间的互相转化实例
Jun 05 Python
详解python中的装饰器
Jul 10 Python
python爬虫获取百度首页内容教学
Dec 23 Python
Django数据库连接丢失问题的解决方法
Dec 29 Python
python实现简单日期工具类
Apr 24 Python
Python中typing模块与类型注解的使用方法
Aug 05 Python
用Python将Excel数据导入到SQL Server的例子
Aug 24 Python
python-tornado的接口用swagger进行包装的实例
Aug 29 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
Apr 07 Python
python读取配置文件方式(ini、yaml、xml)
Apr 09 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
在PHP中使用Sockets 从Usenet中获取文件
2008/01/10 PHP
PHP 实例化类的一点摘记
2008/03/23 PHP
php md5下16位和32位的实现代码
2008/04/09 PHP
php中autoload的用法总结
2013/11/08 PHP
php制作文本式留言板
2015/03/18 PHP
PHP中的traits简单使用实例
2015/05/13 PHP
PHP微信开发之二维码生成类
2015/06/26 PHP
浅谈PHP各环境下的伪静态配置
2019/03/13 PHP
PHP生成随机码的思路与方法实例探索
2019/04/11 PHP
php面试实现反射注入的详细方法
2019/09/30 PHP
用dom+xhtml+css制作的一个相册效果代码打包下载
2008/01/24 Javascript
初学js 新节点的创建 删除 的步骤
2011/07/04 Javascript
关闭浏览器窗口弹出提示框并且可以控制其失效
2014/04/15 Javascript
使用text方法获取Html元素文本信息示例
2014/09/01 Javascript
在JavaScript的jQuery库中操作AJAX的方法讲解
2015/08/15 Javascript
Javascript字符串拼接小技巧(推荐)
2016/06/02 Javascript
微信小程序 教程之注册程序
2016/10/17 Javascript
d3.js入门教程之数据绑定详解
2017/04/28 Javascript
vux uploader 图片上传组件的安装使用方法
2018/05/15 Javascript
Vue中的Props(不可变状态)
2018/09/29 Javascript
nodejs对项目下所有空文件夹创建gitkeep的方法
2019/08/02 NodeJs
详解如何在Vue项目中发送jsonp请求
2019/10/25 Javascript
JS中比较两个Object数组是否相等方法实例
2019/11/11 Javascript
Vue如何基于es6导入外部js文件
2020/05/15 Javascript
Python 命令行参数sys.argv
2008/09/06 Python
python中如何使用正则表达式的集合字符示例
2017/10/09 Python
python实现excel公式格式化的示例代码
2020/12/23 Python
PyCharm 解决找不到新打开项目的窗口问题
2021/01/15 Python
Happy Plugs官网:瑞典无线耳机品牌
2020/07/16 全球购物
Python里面如何拷贝一个对象
2014/02/17 面试题
产品推广策划方案
2014/05/10 职场文书
主要领导对照检查材料
2014/08/26 职场文书
单位租房协议书范本
2014/12/04 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
Golang之sync.Pool使用详解
2021/05/06 Golang
教你如何让spark sql写mysql的时候支持update操作
2022/02/15 MySQL