Login

Automatically generate admin

Author:
WoLpH
Posted:
December 11, 2012
Language:
Python
Version:
Not specified
Score:
0 (after 0 ratings)

A management command to automatically generate a fully specified admin for the models in a specific app.

It automatically generates raw_id_fields, search_fields, list_filter and more. It bases this on date fields, fields named as "name" or slug.

Usage: ./manage admin_autogen <model>

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import re
import sys
from django.core.management.base import BaseCommand
from django.db.models.loading import get_models
from django.db import models

LIST_FILTER = (
    models.DateField,
    models.DateTimeField,
    models.ForeignKey,
    models.BooleanField,
)

SEARCH_FIELD = (
    'name',
    'slug',
)

DATE_HIERARCHY = (
    'created_at',
    'updated_at',
    'joined_at',
)

PREPOPULATED_FIELDS = {
    'slug': ('name',)
}

LIST_FILTER_TRESHOLD = 25
RAW_ID_THRESHOLD = 100

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        self.model_res = []

        installed_apps = dict((a.__name__.rsplit('.', 1)[0], a)
            for a in models.get_apps())

        if not args:
            print >>sys.stderr, 'This command requires a (list of) app(s)'
            for app in sorted(installed_apps):
                print >>sys.stderr, '\t%r' % app
            return

        args = list(args)
        app = installed_apps.get(args.pop(0))
        for arg in args:
            self.model_res.append(re.compile(arg, re.IGNORECASE))

        self.handle_app(app, **kwargs)

    def handle_app(self, app, **options):
        models_dict = {}

        for model in get_models(app):
            name = model.__name__
            field_names = []

            if self.model_res:
                for model_re in self.model_res:
                    if model_re.search(name):
                        break
                else:
                    continue

            models_dict[name] = model_dict = {
                'list_display': [],
                'list_filter': [],
                'raw_id_fields': [],
                'search_fields': [],
                'prepopulated_fields': {},
                'date_hierarchy': None,
            }

            parent_fields = model._meta.parents.values()

            for field in model._meta.local_many_to_many:
                if(field.related.parent_model.objects.all()[:100].count()
                        <= 100):
                    model_dict['raw_id_fields'].append(field.name)

            for field in model._meta.fields:
                if field in parent_fields:
                    continue

                field_names.append(field.name)
                model_dict['list_display'].append(field.name)

                if isinstance(field, LIST_FILTER):
                    if isinstance(field, models.ForeignKey):
                        related_count = (field.related.parent_model.objects
                            .all()
                            [:max(LIST_FILTER_TRESHOLD, RAW_ID_THRESHOLD)]
                            .count()
                        )

                        if related_count >= RAW_ID_THRESHOLD:
                            model_dict['raw_id_fields'].append(field.name)

                        if related_count <= LIST_FILTER_TRESHOLD:
                            model_dict['list_filter'].append(field.name)
                    else:
                        model_dict['list_filter'].append(field.name)

                if field.name in SEARCH_FIELD:
                    model_dict['search_fields'].append(field.name)

            for field_name in DATE_HIERARCHY:
                if field_name in field_names \
                        and not model_dict['date_hierarchy']:
                    model_dict['date_hierarchy'] = field_name

            for k, vs in sorted(PREPOPULATED_FIELDS.iteritems()):
                if field_name in field_names \
                        and not model_dict['date_hierarchy']:
                    model_dict['date_hierarchy'] = field_name

                if k in field_names:
                    incomplete = False
                    for v in vs:
                        if v not in field_names:
                            incomplete = True
                            break

                    if not incomplete:
                        model_dict['prepopulated_fields'][k] = vs

        print 'import models'
        print 'from django.contrib import admin'
        print

        for name, model in sorted(models_dict.iteritems()):
            print '\n\nclass %sAdmin(admin.ModelAdmin):' % name
            for k, v in sorted(model.iteritems()):
                if v:
                    if isinstance(v, (list, set)):
                        v = tuple(v)

                    row = '    %s = %r' % (k, v)
                    row_parts = []
                    while len(row) > 78:
                        pos = row.rfind(' ', 0, 78)
                        row_parts.append(row[:pos])
                        row = '        ' + row[pos:]

                    row_parts.append(row)

                    print '\n'.join(row_parts)

        print '\n\n'
        for name in sorted(models_dict):
            print 'admin.site.register(models.%s, %sAdmin)' % (name, name)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

Please login first before commenting.