Improved admin model registration options: you can now register using register(Model, **options) and even register(Model, ModelAdmin, **options). This isn't documented yet -- a much expanded version of docs/admin.txt is on the way.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8063 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jacob Kaplan-Moss 2008-07-23 18:58:06 +00:00
parent 508016c0f4
commit 7b3cf13d32
3 changed files with 86 additions and 7 deletions

View File

@ -1,6 +1,7 @@
from django import http, template
from django.contrib.admin import ModelAdmin
from django.contrib.auth import authenticate, login
from django.core.exceptions import ImproperlyConfigured
from django.db.models.base import ModelBase
from django.shortcuts import render_to_response
from django.utils.safestring import mark_safe
@ -66,19 +67,33 @@ class AdminSite(object):
If a model is already registered, this will raise AlreadyRegistered.
"""
do_validate = admin_class and settings.DEBUG
if do_validate:
# don't import the humongous validation code unless required
# Don't import the humongous validation code unless required
if admin_class and settings.DEBUG:
from django.contrib.admin.validation import validate
admin_class = admin_class or ModelAdmin
# TODO: Handle options
else:
validate = lambda model, adminclass: None
if not admin_class:
admin_class = ModelAdmin
if isinstance(model_or_iterable, ModelBase):
model_or_iterable = [model_or_iterable]
for model in model_or_iterable:
if model in self._registry:
raise AlreadyRegistered('The model %s is already registered' % model.__name__)
if do_validate:
validate(admin_class, model)
# If we got **options then dynamically construct a subclass of
# admin_class with those **options.
if options:
# For reasons I don't quite understand, without a __module__
# the created class appears to "live" in the wrong place,
# which causes issues later on.
options['__module__'] = __name__
admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)
# Validate (which might be a no-op)
validate(admin_class, model)
# Instantiate the admin class to save in the registry
self._registry[model] = admin_class(model, self)
def unregister(self, model_or_iterable):

View File

@ -0,0 +1,64 @@
"""
Tests for various ways of registering models with the admin site.
"""
from django.db import models
from django.contrib import admin
class Person(models.Model):
name = models.CharField(max_length=200)
class Place(models.Model):
name = models.CharField(max_length=200)
__test__ = {'API_TESTS':"""
# Bare registration
>>> site = admin.AdminSite()
>>> site.register(Person)
>>> site._registry[Person]
<django.contrib.admin.options.ModelAdmin object at ...>
# Registration with a ModelAdmin
>>> site = admin.AdminSite()
>>> class NameAdmin(admin.ModelAdmin):
... list_display = ['name']
... save_on_top = True
>>> site.register(Person, NameAdmin)
>>> site._registry[Person]
<regressiontests.admin_registration.models.NameAdmin object at ...>
# You can't register the same model twice
>>> site.register(Person)
Traceback (most recent call last):
...
AlreadyRegistered: The model Person is already registered
# Registration using **options
>>> site = admin.AdminSite()
>>> site.register(Person, search_fields=['name'])
>>> site._registry[Person].search_fields
['name']
# With both admin_class and **options the **options override the fields in
# the admin class.
>>> site = admin.AdminSite()
>>> site.register(Person, NameAdmin, search_fields=["name"], list_display=['__str__'])
>>> site._registry[Person].search_fields
['name']
>>> site._registry[Person].list_display
['__str__']
>>> site._registry[Person].save_on_top
True
# You can also register iterables instead of single classes -- a nice shortcut
>>> site = admin.AdminSite()
>>> site.register([Person, Place], search_fields=['name'])
>>> site._registry[Person]
<django.contrib.admin.sites.PersonAdmin object at ...>
>>> site._registry[Place]
<django.contrib.admin.sites.PlaceAdmin object at ...>
"""}