from django.core.management.base import BaseCommand from django.apps import apps from django.db.models import Q, CharField, TextField """Completely written by https://gemini.google.com/ 2.5 """ def get_all_project_models(): """ Returns a list of all concrete model.Model classes in the Django project. It ignores abstract models and models from third-party apps that aren't part of the project's own apps. """ # You can customize this list to include/exclude specific apps # For example: installed_apps = settings.INSTALLED_APPS all_models = [] # This gathers all models from all installed apps. for app_config in apps.get_app_configs(): all_models.extend(list(app_config.get_models())) return all_models def find_empty_or_null_fields(model_class): """ Takes a model class and checks every field. Returns a list of field names for which all database entries are either NULL or an empty string. """ completely_empty_fields = [] # Get the total number of records for this model. total_records = model_class.objects.count() # If there are no records, all fields are technically "empty". # We return an empty list to avoid reporting every field from an empty table. if total_records == 0: return [] # Iterate over all concrete fields of the model. for field in model_class._meta.get_fields(): # We only want to check actual database columns, not relations. if not hasattr(field, 'column'): continue field_name = field.name # Build a query to find records that have a meaningful value. # This is more efficient than counting all null/empty records. # We exclude records that are NULL. query_has_value = model_class.objects.exclude(Q(**{f'{field_name}__isnull': True})) # For text-based fields, we also exclude empty strings. if isinstance(field, (CharField, TextField)): query_has_value = query_has_value.exclude(Q(**{f'{field_name}': ''})) # If the query for records WITH a value returns FALSE (no such records exist), # it means all records for this field are empty or null. if not query_has_value.exists(): completely_empty_fields.append(field_name) return completely_empty_fields class Command(BaseCommand): help = "Scans all project models to find fields where all entries are empty or null." def handle(self, *args, **options): self.stdout.write(self.style.SUCCESS("šŸš€ Starting scan for empty or null fields across all models...")) all_models = get_all_project_models() found_any = False for model in all_models: total_records = model.objects.count() model_name = f"{model._meta.app_label}.{model._meta.object_name}" self.stdout.write(f"\nšŸ” Checking model: {self.style.HTTP_INFO(model_name)} ({total_records} instances found)") empty_fields = find_empty_or_null_fields(model) if empty_fields: found_any = True for field_name in empty_fields: self.stdout.write( self.style.WARNING(f" -> Field '{field_name}' is completely empty or null.") ) else: self.stdout.write(self.style.SUCCESS(" āœ… All fields contain data.")) if not found_any: self.stdout.write(self.style.SUCCESS("\nšŸŽ‰ Scan complete. No fields were found to be universally empty or null.")) """ ### How to Run the Command After saving the file, you can run your new command from your project's root directory (where `manage.py` is located): bash uv run manage.py find_empty_fields ### Example Output The output in your terminal will look something like this: ``` šŸš€ Starting scan for empty or null fields across all models... šŸ” Checking model: auth.Group āœ… All fields contain data. šŸ” Checking model: auth.User -> Field 'last_name' is completely empty or null. -> Field 'first_name' is completely empty or null. šŸ” Checking model: products.Product -> Field 'notes' is completely empty or null. -> Field 'discount_code' is completely empty or null. šŸ” Checking model: products.Category āœ… All fields contain data. """