Skip to content

Instantly share code, notes, and snippets.

@DrMartiner
Last active October 22, 2017 13:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DrMartiner/c226c174cd6e367ee7e8b09af029c9e6 to your computer and use it in GitHub Desktop.
Save DrMartiner/c226c174cd6e367ee7e8b09af029c9e6 to your computer and use it in GitHub Desktop.
Command for backups all media files
import os
import tarfile
import progressbar
import django.apps
from datetime import datetime
from django.core.management.base import BaseCommand
from django.utils.encoding import smart_str
class Command(BaseCommand):
help = 'Backup item images'
def add_arguments(self, parser):
parser.add_argument(
'--show-bar',
action='store_true',
dest='show_bar',
default=False,
help='Show progressbar'
)
parser.add_argument(
'--print-paths',
action='store_true',
dest='print_paths',
default=False,
help='Print files paths'
)
def handle(self, *args, **options):
backuper = BackupFiles(
'project-name',
show_bar=options['show_bar'],
print_paths=options['print_paths']
)
archive_path = backuper.start()
print(archive_path)
class BackupFiles(object):
_media_folder_name = None
def __init__(self,
project_name,
archive_folder='/tmp',
default_media_folder_name='media',
show_bar=False,
print_paths=False):
self.show_bar = show_bar
self.print_paths = print_paths
self.project_name = project_name
self.archive_folder = archive_folder
self._default_media_folder_name = default_media_folder_name
def start(self):
archive_path = self._get_archive_path()
tar = tarfile.open(archive_path, 'w:gz')
files_path = []
models_list = django.apps.apps.get_models()
for model_class in models_list:
for instance in model_class.objects.all():
file_field_names = self._get_file_fields(instance)
for field_name in file_field_names:
cur_path = self._get_file_field(instance, field_name)
if cur_path:
files_path.append(cur_path)
if self.print_paths:
message = '{}.{} {} :: {}'.format(
model_class._meta.app_label,
model_class._meta.model_name,
field_name,
cur_path['full_path']
)
print(message)
bar = None
if self.show_bar:
bar = progressbar.ProgressBar(max_value=len(files_path)).start()
for i, cur_path in enumerate(files_path):
tar.add(
cur_path['full_path'],
arcname=cur_path['arc_name']
)
if bar:
bar.update(i + 1)
if bar:
bar.finish()
tar.close()
return archive_path
def _get_archive_path(self):
file_name = '{}-{}-{}.tar.gz'.format(
self.project_name,
self.media_folder_name,
datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
)
archive_path = '{}/{}'.format(
self.archive_folder,
file_name
)
return archive_path
@property
def media_folder_name(self):
if self._media_folder_name:
return self._media_folder_name
return self._default_media_folder_name
@media_folder_name.setter
def media_folder_name(self, value):
self._media_folder_name = value
@staticmethod
def _get_file_fields(instance):
names = []
for field in instance._meta.fields:
if field.get_internal_type() == 'FileField':
names.append(field.name)
return names
def _get_file_field(self, instance, field_name):
field = getattr(instance, field_name)
if not field:
return {}
full_path = smart_str(field.path)
arc_name = '{}/{}/{}'.format(
self.media_folder_name,
field.field.upload_to,
os.path.basename(full_path)
)
return {
'arc_name': arc_name,
'full_path': full_path,
}
progressbar2==3.34.3
Django==1.11.5
python-utils==2.2.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment