#!/usr/bin/env python # -*- coding: UTF-8 -*- """ Title: Port to newforms-admin Project: Developer tools Author: Will Hardy (http://willhardy.com.au) Date: June 2008 Usage: ./manage.py port2nfa > admin.py To do: * inline classes * prepopulate_from """ import sys from django.db import models from django.core.management.base import BaseCommand from django import utils from django.contrib import admin # Redefine repr to be able to handle proxy objects within lists, tuples and dicts _python_repr = repr def repr(obj): if isinstance(obj, list): return u"[%s]" % ", ".join([ repr(item) for item in obj ]) elif isinstance(obj, tuple): return u"(%s, )" % ", ".join([ repr(item) for item in obj ]) elif isinstance(obj, dict): items = [] for key, value in obj.items(): items.append(u"%s: %s" % (repr(key), repr(value))) return "{%s}" % ", ".join(items) elif obj.__class__.__name__ == "__proxy__": return "_(%s)" % repr(unicode(obj)) return _python_repr(obj) class Command(BaseCommand): help = 'Generates a python script to define the admin site from an oldforms admin definition..' args = '[appname ...]' def handle(self, *app_labels, **options): from django.db.models import get_app, get_apps, get_models if len(app_labels) == 0: app_list = get_apps() else: app_list = [get_app(app_label) for app_label in app_labels] # Get a list of all the relevant models models = [] for app in app_list: models += get_models(app) # A dictionary to store required imports imports = {} # process the models to create a list of entries, and update the imports dictionary entries = get_entries(models, imports) # Structure the full output lines = Lines() lines += 'from django.contrib import admin' lines += 'from django.utils.translation import ugettext_lazy as _' lines += get_import_lines(imports) lines.add_empty_line() lines += entries lines += "site = admin.AdminSite()" lines += [ "site.register(%s, %sAdmin)" % (model, model) for model in imports.keys() ] print lines def get_entries(models, imports): entries = [] for model in models: entry = "\n".join(get_model_lines(model)) if entry: if model.__name__ in imports: sys.stderr.write("A model with this name has already been processed! Skipping %s" % model.__name__) else: entries.append(entry) imports[model.__name__] = model.__module__ return entries def get_model_lines(model): " Returns a newforms-admin definition and registration for this model. " lines = Lines() admin_attributes = hasattr(model, "Admin") and model.Admin or model._meta.admin if admin_attributes: lines += "class %sAdmin(admin.ModelAdmin):" % model.__name__ lines += get_basic_fields(model, admin_attributes) lines += get_prepopulated_fields(model) if len(lines) == 1: lines += ' pass' lines.add_empty_line() return lines def get_basic_fields(model, admin_attributes): lines = Lines() if hasattr(model, "Admin") and model.Admin: for key,value in model.Admin.__dict__.items(): if not key.startswith("__"): lines += " %s = %s" % (key, repr(value)) if model._meta.admin: from django.db.models.options import AdminOptions default_object = AdminOptions() for key,value in model._meta.admin.__dict__.items(): if value and key not in ('manager', ) and value != getattr(default_object, key): lines += " %s = %s" % (key, repr(value)) return lines def get_prepopulated_fields(model): fields = {} for field in model._meta.fields: if hasattr(field, 'prepopulate_from') and field.prepopulate_from: fields[field.name] = field.prepopulate_from if fields: return "prepopulated_fields = %s" % repr(fields) def get_import_lines(imports): " Takes a dictionary of imports and formats them nicely. " # Create a dictionary to combine imported objects from the same module imports_dict = {} for key,value in imports.items(): if value in imports_dict: imports_dict[value].append(key) else: imports_dict[value] = [key] # Generate the final formatted output return [ 'from %s import %s' % (mod, ", ".join(obj)) for mod,obj in imports_dict.items() ] # HELPER CLASSES ################################################################################ class Lines(list): def add_empty_line(self): self.append("") def add_line(self, value): self.append(value) def __unicode__(self): return u"\n".join(self) def __str__(self): return "\n".join(self) def __iadd__(self, value): if isinstance(value, basestring): value = [ value ] if value: return super(Lines, self).__iadd__(value) else: return self