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基础教程之缩进介绍
Aug 29 Python
python图像常规操作
Nov 11 Python
Python import与from import使用及区别介绍
Sep 06 Python
python绘制规则网络图形实例
Dec 09 Python
Python函数式编程实例详解
Jan 17 Python
Python识别html主要文本框过程解析
Feb 18 Python
详解django使用include无法跳转的解决方法
Mar 19 Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
May 19 Python
Python迭代器协议及for循环工作机制详解
Jul 14 Python
python模拟点击在ios中实现的实例讲解
Nov 26 Python
详解Open Folder as PyCharm Project怎么添加的方法
Dec 29 Python
Sentry的安装、配置、使用教程(Sentry日志手机系统)
Jul 23 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 UBB 解析实现代码
2011/11/27 PHP
一款简单实用的php操作mysql数据库类
2014/12/08 PHP
PHP时间戳格式全部汇总 (获取时间、时间戳)
2016/06/13 PHP
PHP面向对象程序设计中的self、static、parent关键字用法分析
2019/08/14 PHP
Laravel 已登陆用户再次查看登陆页面的自动跳转设置方法
2019/09/30 PHP
javascript中关于break,continue的特殊用法与介绍
2012/05/24 Javascript
基于JavaScript代码实现pc与手机之间的跳转
2015/12/23 Javascript
JQuery ztree带筛选、异步加载实例讲解
2016/02/25 Javascript
js select实现省市区联动选择
2020/04/17 Javascript
详解nodejs 文本操作模块-fs模块(四)
2016/12/22 NodeJs
手机端js和html5刮刮卡效果
2020/09/29 Javascript
详解Angular2 之 结构型指令
2017/06/21 Javascript
浅谈JsonObject中的key-value数据解析排序问题
2017/12/06 Javascript
JavaScript读写二进制数据的方法详解
2018/09/09 Javascript
node 文件上传接口的转发的实现
2019/09/23 Javascript
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
[55:44]完美世界DOTA2联赛决赛 FTD vs Phoenix 第二场 11.08
2020/11/11 DOTA
Python数据结构与算法之图的广度优先与深度优先搜索算法示例
2017/12/14 Python
基于python 处理中文路径的终极解决方法
2018/04/12 Python
Python中整数的缓存机制讲解
2019/02/16 Python
python实现转圈打印矩阵
2019/03/02 Python
在Python中利用pickle保存变量的实例
2019/12/30 Python
PyTorch实现ResNet50、ResNet101和ResNet152示例
2020/01/14 Python
简述python Scrapy框架
2020/08/17 Python
La Redoute英国官网:法国时尚品牌
2017/04/27 全球购物
澳大利亚排名第一的在线酒类商店:MyBottleShop
2018/04/26 全球购物
Bibloo奥地利:购买女装、男装、童装、鞋和配件
2018/10/18 全球购物
幼儿园教师国培感言
2014/02/02 职场文书
2015年毕业生自我鉴定模板
2014/09/19 职场文书
2014年乡镇党建工作总结
2014/11/11 职场文书
2015年环保局工作总结
2015/05/22 职场文书
2015年教师节感言
2015/08/03 职场文书
工作服管理制度范本
2015/08/06 职场文书
学生会2016感恩节活动小结
2016/04/01 职场文书
Nginx反向代理学习实例教程
2021/10/24 Servers
MySQL数据管理操作示例讲解
2022/12/24 MySQL