Last active
October 22, 2017 13:01
-
-
Save DrMartiner/c226c174cd6e367ee7e8b09af029c9e6 to your computer and use it in GitHub Desktop.
Command for backups all media files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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