[PYTHON] [Django] Befehl zum Ausgeben von QuerySet an csv

Ich habe einen Code geschrieben, der die Auswahl in eine Tabelle ausgibt, in der eine große Anzahl von Datensätzen gespeichert ist, das Ergebnis an csv ausgibt und es komprimiert. Machen Sie sich also eine Notiz.

models.py


from logging import getLogger
from django.db import models
import uuid

logger = getLogger(__name__)


class Analytics(models.Model):

    hit_type = models.CharField(max_length=20)

    category = models.CharField(max_length=255, null=True, blank=True)
    action = models.CharField(max_length=255, null=True)
    label = models.CharField(max_length=255, null=True, blank=True)
    value = models.IntegerField(null=True)
    url = models.CharField(max_length=255, null=True)
    created = models.DateTimeField(auto_now_add=True, db_index=True)
    tracking_user = models.ForeignKey('app.TrackingUser', related_name='analytics')

    def __str__(self):
        return '%s - %s' % (self.category, self.tracking_user.uuid)


class TrackingUser(models.Model):

    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.uuid)

Es gab ein Modell, das Daten speichert, die das Benutzerverhalten auf der Website wie oben beschrieben verfolgen. Dieses Mal wollte ich jedoch einen Befehl erstellen, der gelöscht werden kann, nachdem Analytics-Datensätze einen Monat lang erfasst und in CSV gespeichert wurden. .. Übrigens steigen die Analytics-Daten an einem Tag um etwa 100.000, also um etwa 3 Millionen pro Monat. Aufgrund der verschiedenen Aktionen war der folgende Code ein gutes Gefühl.

delete_analytics.py


from datetime import datetime, timedelta, date
from api.models import Analytics
from pytz import timezone, utc
from django.core.management.base import BaseCommand
from django.db import transaction
from dateutil.relativedelta import relativedelta
import csv
import gzip
import shutil
import os

class Command(BaseCommand):
    def add_arguments(self, parser):
        # Named (optional) arguments
        parser.add_argument('--target_date', metavar='target_date', type=str, nargs=None,
                            help='target date')

    @transaction.atomic
    def handle(self, *args, **options):
        if options['target_date']:
            delete_start_date = datetime.strptime(options['target_date'], '%Y-%m-%d').replace(day=1)
        else:
            this_month = date.today().replace(day=1)
            delete_start_date = this_month - relativedelta(months=3)
        delete_end_date = delete_start_date + relativedelta(months=1)

        queryset = Analytics.objects.select_related('user', 'tracking_user').filter(created__range=(delete_start_date, delete_end_date))

        #Ausgabe an csv
        filename_date = delete_start_date.strftime('%Y%m')
        filename = filename_date + "_event.csv"

        model = queryset.model
        writer = csv.writer(open(filename, 'w'))

        ##Schreiben des Header-Teils von csv
        headers = []
        for field in model._meta.fields:
            headers.append(field.name)
        writer.writerow(headers)

        ##Schreiben Sie den abgerufenen Datensatz
        for obj in queryset:
            row = []
            for field in headers:
                val = getattr(obj, field)
                if callable(val):
                    val = val()
                row.append(val)
            writer.writerow(row)

        #Komprimiere csv mit gzip
        with open(filename, 'rb') as gzip_in:
            with gzip.open(filename + ".gz", 'wb') as gzip_out:
                shutil.copyfileobj(gzip_in, gzip_out)

        os.remove(filename)

        queryset.delete()

Wenn Sie in dem Verzeichnis, in dem sich manage.py befindet, "./manage.py delete_analytics.py -target_date = 2017-06-01" festlegen, werden die Daten für Juni 2017 in 201706_event.csv ausgegeben, mit gzip weiter komprimiert und dann , Gelöscht.
Die folgenden Teile waren diesmal der Schlüssel.

python


queryset = Analytics.objects.select_related( 'tracking_user').filter(created__range=(delete_start_date, delete_end_date))

Wenn Sie nicht "select_related" ("tracking_user") schreiben, wird auch das Beziehungsziel ausgewählt, sodass dies einige Zeit in Anspruch nimmt. Als ich es schrieb, endete der Befehl in 5 Minuten, aber wenn ich ihn nicht schrieb, dauerte es 50 Minuten, bis er fertig war.

Nachtrag

Als ich es auf dem Server ausführte, fiel es aufgrund von Speichermangel ... Überlegen Sie, was zu tun ist, und schreiben Sie erneut, wenn Sie damit umgehen können

Referenzlink

django recipe: dump your queryset out as a csv file . palewire

Recommended Posts

[Django] Befehl zum Ausgeben von QuerySet an csv
Ausgabe in eine CSV-Datei mit Python
[Django] Abfragesatz konvertieren, um Typliste zu diktieren
Python> Ausgaben von 1 bis 100, 501 bis 600> Für CSV
Benutzerinformationen usw. in das Django-Protokoll ausgeben
Django + Docker-Befehl
Konvertieren Sie XLSX in CSV in der Befehlszeile
PDF mit Django ausgeben
Markdown-Ausgabe mit Django
Django kann nicht importiert werden
[Python-pptx] Gibt PowerPoint-Schriftinformationen mit Python in CSV aus
Einstellungen für die Vervollständigung des Django-Befehls
Aktualisieren Sie die Django-Version 1.11.1 auf 2.2
Ich habe einen Befehl zum Generieren eines Kommentars für eine Tabelle in Django eingegeben
Ausgabe von Produktinformationen an csv mithilfe der Rakuten-Produktsuch-API [Python]
Einführung in Python Django (2) Win
Alternative zu Djangos Befehl dumpdata
Befehl zum Generieren von QR-Code
Ausgabe der Tabellenstruktur in Django
Shell zum Erstellen eines Django-Projekts
Schreiben Sie mit Python in csv
Konvertieren Sie SDF schnell in CSV
Ausgabe Debug-Ausgabe des Kelchbefehls
Übergeben Sie den Text an Django genericview
Stellen Sie das Django-Projekt für Heroku bereit
[Lernnotiz] Zusammenfassung des Django-Befehls
[systemd] Befehl zum Löschen des Dienstes
Einführung in den Befehl vi (Hinweis)
Dekorateur zum Stummschalten der Standardausgabe
Drücken Sie den Echo-Befehl im Mac-Terminal, um Hello World auszugeben
So geben Sie das Ausgabeergebnis des Linux-Befehls man in eine Datei aus