生產環境中常需批量導入大量歷史數據(如員工賬號、SVN 提交記錄等)。手動逐條錄入效率極低,本文介紹基於 Django Admin 的 XML 文件批量導入方案,實現文件上傳、解析、入庫一體化流程。
@python_2_unicode_compatible
class SVNLog(models.Model):
revision = models.IntegerField(verbose_name="修訂版本", blank=False, null=False)
author = models.CharField(verbose_name="作者", max_length=60, blank=True, null=True)
date = models.DateTimeField(verbose_name="修訂時間", null=True)
msg = models.TextField(verbose_name="正文信息", blank=False, null=False, default="")
paths = models.TextField(verbose_name="影響的文件", blank=False, null=False, default="")
created_time = models.DateTimeField(verbose_name="創建時間", auto_now_add=True)
update_time = models.DateTimeField(verbose_name="修改時間", auto_now=True)
class Meta:
ordering = ['revision']
def __str__(self):
return 'r%s' % (self.revision or "")
@python_2_unicode_compatible
class ImportLogFile(models.Model):
log_file = models.FileField(upload_to='LogFile')
file_name = models.CharField(max_length=50, verbose_name='文件名')
class Meta:
ordering = ['file_name']
def __str__(self):
return self.file_name
python manage.py makemigrations
python manage.py migrate
class ImportLogAdmin(admin.ModelAdmin):
list_display = ('log_file', 'file_name')
list_filter = ['file_name']
def save_model(self, request, obj, form, change):
# 先保存文件記錄
re = super(ImportLogAdmin, self).save_model(request, obj, form, change)
# 解析並入庫
update_svn_log(self, request, obj, change)
return re
關鍵點:重寫 save_model 方法,在文件保存後自動觸發解析邏輯,obj.log_file.path 可獲取上傳文件的服務器路徑。
<?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>
from .models import SVNLog
import xmltodict
def update_svn_log(self, request, obj, change):
filepath = obj.log_file.path
xmlfile = xmltodict.parse(open(filepath, 'r'))
xml_logentry = xmlfile.get('log').get('logentry')
# 兼容單個/多個 path 元素
for entry in xml_logentry:
paths = entry.get('paths', {}).get('path', [])
if not isinstance(paths, list):
paths = [paths]
path_list = []
for path in paths:
action = path.get('@action', '')
path_text = path.get('#text', '')
path_list.append(f"{action} {path_text}")
paths_str = "Changed paths:\n " + "\n ".join(path_list)
revision = int(entry.get('@revision', 0))
author = entry.get('author', '')
date_str = entry.get('date', '')
msg = entry.get('msg', '')
# 判斷是新增還是更新
last_revision = SVNLog.objects.order_by('-revision').first()
last_version = last_revision.revision if last_revision else 0
if revision > last_version:
SVNLog.objects.create(
revision=revision,
author=author,
date=date_str,
msg=msg,
paths=paths_str
)
else:
SVNLog.objects.filter(revision=revision).update(
author=author,
date=date_str,
msg=msg,
paths=paths_str
)
isinstance(paths, list) 兼容單個/多個 path 元素bulk_create/bulk_update 減少數據庫交互通過 Django Admin 重寫 save_model 結合 xmltodict 解析庫,實現了 SVN 日誌 XML 文件的批量自動化導入。此模式可推廣到各類結構化文件的後台導入場景,關鍵在於模型設計、解析邏輯封裝與批量操作優化。