<s> import os . path <EOL> from django . core . management . base import BaseCommand <EOL> from django . apps import apps <EOL> from django . db import models <EOL> from django . utils import six <EOL> class Command ( BaseCommand ) : <EOL> def handle ( self , * args , ** options ) : <EOL> used_files = set ( ) <EOL> storages = set ( ) <EOL> for app_config in apps . get_app_configs ( ) : <EOL> for model in app_config . get_models ( ) : <EOL> file_fields = [ <EOL> field <EOL> for field in model . _meta . get_fields ( ) <EOL> if isinstance ( field , models . FileField ) ] <EOL> if not file_fields : <EOL> continue <EOL> storages |= set ( [ file_field . storage for file_field in file_fields ] ) <EOL> file_field_names = [ <EOL> field . name for field in file_fields <EOL> ] <EOL> values = model . objects . all ( ) . values_list ( * file_field_names , flat = True ) . distinct ( ) <EOL> used_files |= set ( [ val for val in values if val ] ) <EOL> def find_files ( storage , curdir ) : <EOL> try : <EOL> subdirs , files = storage . listdir ( curdir ) <EOL> except NotImplementedError : <EOL> pass <EOL> files = set ( [ <EOL> os . path . join ( curdir , f ) for f in files <EOL> ] ) <EOL> for subdir in subdirs : <EOL> files |= find_files ( storage , os . path . join ( curdir , subdir ) ) <EOL> return files <EOL> all_files = set ( ) <EOL> files_storage_map = dict ( ) <EOL> for storage in storages : <EOL> files = find_files ( storage , '<STR_LIT>' ) <EOL> for f in files : <EOL> files_storage_map [ f ] = storage <EOL> all_files |= files <EOL> unused_files = all_files - used_files <EOL> self . stdout . write ( "<STR_LIT>" % len ( all_files ) ) <EOL> self . stdout . write ( "<STR_LIT>" % len ( used_files ) ) <EOL> self . stdout . write ( "<STR_LIT>" % len ( unused_files ) ) <EOL> for f in unused_files : <EOL> self . stdout . write ( "<STR_LIT:%s>" % f ) <EOL> if unused_files : <EOL> answer = None <EOL> while not answer or answer not in "<STR_LIT>" : <EOL> answer = six . moves . input ( "<STR_LIT>" ) <EOL> if not answer : <EOL> answer = "<STR_LIT:n>" <EOL> break <EOL> else : <EOL> answer = answer [ <NUM_LIT:0> ] . lower ( ) <EOL> if answer != "<STR_LIT:y>" : <EOL> return <EOL> for f in unused_files : <EOL> storage = files_storage_map [ f ] <EOL> storage . delete ( f ) </s>
