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实现简单的获取图片爬虫功能示例
Jul 12 Python
Python实现的rsa加密算法详解
Jan 24 Python
python 读取.csv文件数据到数组(矩阵)的实例讲解
Jun 14 Python
Tornado Web Server框架编写简易Python服务器
Jul 28 Python
对pytorch网络层结构的数组化详解
Dec 08 Python
Python设计模式之策略模式实例详解
Jan 21 Python
django中ORM模型常用的字段的使用方法
Mar 05 Python
Python3.5内置模块之shelve模块、xml模块、configparser模块、hashlib、hmac模块用法分析
Apr 27 Python
pytorch 实现在预训练模型的 input上增减通道
Jan 06 Python
Python递归函数特点及原理解析
Mar 04 Python
python机器学习创建基于规则聊天机器人过程示例详解
Nov 02 Python
python井字棋游戏实现人机对战
Apr 28 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实现将上传word文件转为html的方法
2015/06/03 PHP
浅析JQuery获取和设置Select选项的常用方法总结
2013/07/04 Javascript
Jquery利用mouseenter和mouseleave实现鼠标经过弹出层且可以点击
2014/02/12 Javascript
深入理解javascript的执行顺序
2014/04/04 Javascript
3种js实现string的substring方法
2015/11/09 Javascript
浅析JavaScript中的变量复制、参数传递和作用域链
2016/01/13 Javascript
javascript中不易分清的slice,splice和split三个函数
2016/03/29 Javascript
jQuery中Find选择器用法示例
2016/09/21 Javascript
Ionic+AngularJS实现登录和注册带验证功能
2017/02/09 Javascript
js实现横向拖拽导航条功能
2017/02/17 Javascript
深究AngularJS中ng-drag、ng-drop的用法
2017/06/12 Javascript
详解在vue-cli中引用jQuery、bootstrap以及使用sass、less编写css
2017/11/08 jQuery
Vue-cli中为单独页面设置背景色的实现方法
2018/02/11 Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
2018/05/02 Javascript
基于vue展开收起动画的示例代码
2018/07/05 Javascript
详解Vue CLI3配置解析之css.extract
2018/09/14 Javascript
js+canvas实现画板功能
2020/09/13 Javascript
[01:03:54]Liquid vs IG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python判断字符串与大小写转换
2015/06/08 Python
python3+PyQt5+Qt Designer实现扩展对话框
2018/04/20 Python
Python实现在某个数组中查找一个值的算法示例
2018/06/27 Python
解决python3 安装完Pycurl在import pycurl时报错的问题
2018/10/15 Python
利用Django提供的ModelForm增删改数据的方法
2019/01/06 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
python按修改时间顺序排列文件的实例代码
2019/07/25 Python
python编写猜数字小游戏
2019/10/06 Python
python 扩展print打印文件路径和当前时间信息的实例代码
2019/10/11 Python
python3.6、opencv安装环境搭建过程(图文教程)
2019/11/05 Python
html5小技巧之通过document.head获取head元素
2014/06/04 HTML / CSS
澳大利亚游乐场设备品牌:Lifespan Kids
2019/05/24 全球购物
澳大利亚家居用品零售商:Harris Scarfe
2020/10/10 全球购物
2019广播稿怎么写
2019/04/17 职场文书
Mac环境Nginx配置和访问本地静态资源的实现
2021/03/31 Servers
python 破解加密zip文件的密码
2021/04/22 Python
聊聊Python中关于a=[[]]*3的反思
2021/06/02 Python
对象析构函数__del__在Python中何时使用
2022/03/22 Python