Heim  >  Artikel  >  Backend-Entwicklung  >  Django Batch importiert XML-Daten

Django Batch importiert XML-Daten

不言
不言Original
2018-05-23 11:04:501863Durchsuche

Django Hintergrund-Batch-Importdaten

In einer Produktionsumgebung gibt es oft nicht wenige oder Hunderte von Daten, also zum Beispiel die Mitarbeiternummer oder das Konto und Passwörter werden in das Backend importiert, daher wird nicht empfohlen, dass Sie zum Backend gehen, um Datensätze einzeln hinzuzufügen

So importieren Sie SVN-Datensätze stapelweise aus XML

Schritt eins:

Erstellen Sie ein Modell für die Daten

@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"", )

Nachdem das Modell erstellt wurde, Erstellen wir es so, dass es unsere XML-Dateimodelle akzeptiert

@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, im obigen Code haben wir die Daten definiert und Dateimodelle hochgeladen

Synchronisieren Sie die Datenbank

python manage.py makemigrations
python manage.py migrate

Dann ändern wir admin.py, damit wir Dateien von hochladen können der Hintergrund,

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

Achten Sie auf save_model im obigen Code. Dies ist der Schlüssel. Hier schreibe ich die save_model-Methode in ModelAdmin um Wir müssen Dateien hochladen und in einem Schritt lesen, die Datei analysieren und die Datenbank betreiben. Beim Hochladen der Datei enthält der Rückgabeparameter obj auch den Pfad Schlüssel zu unserem nächsten Schritt des Parsens der Datei. Okay, wir erstellen eine neue utils.py in diesem App-Ordner, um die Tool-Klasse zu betreiben, die wir zum Betreiben von Dateien und Datenbanken verwenden. Der Einfachheit halber habe ich die Funktion wie folgt geschrieben:
Zuerst einfügen die XML-Datei, die wir testen möchten

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

Ausgabeergebnisformat

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)

Die Drittanbieter-Bibliothek xmltodict, die wir zum Parsen von XML verwenden. Er analysiert den Inhalt in einen effizienten Orderdict-Typ, der ein sequenziertes Wörterbuch ist.

Das Kompliziertere in dieser XML ist der Pfad in Pfaden, da diese XML zwei enthält Elemente, und der Pfad des ersten Elements enthält nur einen Pfad. Die Pfade im zweiten Element enthalten drei Pfade, daher müssen wir beim Parsen und Erhalten

paths = j.get('paths').get('path')
if isinstance(paths,list):
  pass

Wir beurteilen diesen Pfad. Handelt es sich um einen Listentyp? Wenn nicht, verarbeiten wir ihn auf eine einzige Weise. Nachdem wir ihn erhalten haben, verarbeiten wir ihn entsprechend in das Ausgabeergebnisformat konvertieren und dann andere Inhalte abrufen

revision = j.get('@vision')
# get auth
author = j.get('author')
#get date
date = j.get('date')
#get msg
msg = j.get('msg')

Schließlich werden wir die erhaltenen Elemente im Wörterbuch speichern

Beurteilen Sie die aktuelle Versionsnummer und die Versionsnummer in der Datenbank in der Schleife,

Wenn sie verglichen wird Das Original ist klein, dann führen wir den Aktualisierungsvorgang durch und umgekehrt

Schließlich wird bulk_create zum Betreiben der Datenbank verwendet, was vermeidet die Verschwendung von Ressourcen, die jedes Mal in der Schleife durch Datenbankoperationen verursacht wird

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn