视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
django批量导入xml数据
2020-11-27 14:27:35 责编:小采
文档


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文件

qwert2016-09-27T07:16:37.3949Z/aaa/README20160927 151630VisualSVN Server2016-09-20T05:03:12.861315Z/branches/tags/trunkhello word

输出结果格式

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'
'.join(pathlist)
 _paths = u"Changed paths:
 {}".format(_filelist)
 print _paths
 else:
 _filelist = paths.get('@action') + ' ' + paths.get('#text')
 _paths = u"Changed paths:
 {}".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来操作数据库,这样避免了循环中每次都进行数据库操作造成的资源浪费

下载本文
显示全文
专题