J'ai écrit un code qui émet une sélection dans une table qui stocke un grand nombre d'enregistrements, envoie le résultat au csv et le gzip, alors prenez note.
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)
Il y avait un modèle qui stockait les données qui suivaient le comportement des utilisateurs sur le site Web comme décrit ci-dessus, mais cette fois, je voulais créer une commande qui peut supprimer après avoir acquis des enregistrements Analytics pendant un mois et les stocker dans csv. .. Soit dit en passant, les données Analytics augmentent d'environ 100 000 en un jour, soit environ 3 millions en un mois. Donc, à la suite de diverses choses, le code suivant était un bon sentiment.
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))
#Sortie vers csv
filename_date = delete_start_date.strftime('%Y%m')
filename = filename_date + "_event.csv"
model = queryset.model
writer = csv.writer(open(filename, 'w'))
##Ecrire la partie en-tête de csv
headers = []
for field in model._meta.fields:
headers.append(field.name)
writer.writerow(headers)
##Ecrire l'enregistrement récupéré
for obj in queryset:
row = []
for field in headers:
val = getattr(obj, field)
if callable(val):
val = val()
row.append(val)
writer.writerow(row)
#Compresser csv avec 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()
Si vous définissez ./manage.py delete_analytics.py -target_date = 2017-06-01
dans le répertoire où se trouve manage.py, les données de juin 2017 seront générées dans 201706_event.csv, ensuite compressées avec gzip, puis , Supprimé.
Les parties suivantes ont été la clé cette fois.
python
queryset = Analytics.objects.select_related( 'tracking_user').filter(created__range=(delete_start_date, delete_end_date))
Si vous n'écrivez pas select_related ('tracking_user').
, La destination de la relation ira également à select, donc cela prendra du temps.
Quand je l'ai écrit, la commande s'est terminée en 5 minutes, mais si je ne l'ai pas écrite, il a fallu 50 minutes pour terminer.
Quand je l'ai exécuté sur le serveur, il est tombé en raison d'un manque de mémoire ... Réfléchissez à ce qu'il faut faire et réécrivez si vous pouvez le gérer
django recipe: dump your queryset out as a csv file . palewire
Recommended Posts