Permalink
Browse files

Fixed #19414 -- Added admin registration decorator

Thanks stavros for the suggestion.
  • Loading branch information...
BHold authored and timgraham committed Dec 18, 2012
1 parent d1c9802 commit 98514849dce07acfaa224a90a784bba9d97249e5
@@ -1,5 +1,6 @@
# ACTION_CHECKBOX_NAME is unused, but should stay since its import from here
# has been referenced in documentation.
from django.contrib.admin.decorators import register
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
from django.contrib.admin.options import ModelAdmin, HORIZONTAL, VERTICAL
from django.contrib.admin.options import StackedInline, TabularInline
@@ -0,0 +1,28 @@
def register(*models, **kwargs):
"""
Registers the given model(s) classes and wrapped ModelAdmin class with
admin site:
@register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass
A kwarg of `site` can be passed as the admin site, otherwise the default
admin site will be used.
"""
from django.contrib.admin import ModelAdmin
from django.contrib.admin.sites import site, AdminSite
def _model_admin_wrapper(admin_class):
admin_site = kwargs.pop('site', site)
if not isinstance(admin_site, AdminSite):
raise ValueError('site must subclass AdminSite')
if not issubclass(admin_class, ModelAdmin):
raise ValueError('Wrapped class must sublcass ModelAdmin.')

This comment has been minimized.

@uruz

uruz Sep 19, 2013

Contributor

Typo: sublcass instead of subclass

admin_site.register(models, admin_class=admin_class)
return admin_class
return _model_admin_wrapper
@@ -101,6 +101,34 @@ Other topics
admin.site.register(Author)
The register decorator
----------------------
.. function:: register(*models, [site=django.admin.sites.site])
.. versionadded:: 1.7
There is also a decorator for registering your ``ModelAdmin`` classes::
from django.contrib import admin
from .models import Author
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass
It is given one or more model classes to register with the ``ModelAdmin``
and an optional keyword argument ``site`` if you are not using the default
``AdminSite``::
from django.contrib import admin
from .models import Author, Reader, Editor
from myproject.admin_site import custom_admin_site
@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
pass
``ModelAdmin`` options
----------------------
@@ -135,6 +135,10 @@ Minor features
customize the value of :attr:`ModelAdmin.fields
<django.contrib.admin.ModelAdmin.fields>`.
* In addition to the existing ``admin.site.register`` syntax, you can use the
new :func:`~django.contrib.admin.register` decorator to register a
:class:`~django.contrib.admin.ModelAdmin`.
:mod:`django.contrib.auth`
^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,9 +8,15 @@
class Person(models.Model):
name = models.CharField(max_length=200)
class Traveler(Person):
pass
class Location(models.Model):
class Meta:
abstract = True
class Place(Location):
name = models.CharField(max_length=200)
@@ -1,16 +1,23 @@
from __future__ import unicode_literals
from django.contrib import admin
from django.contrib.admin.decorators import register
from django.contrib.admin.sites import site
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
from .models import Person, Place, Location
from .models import Person, Place, Location, Traveler
class NameAdmin(admin.ModelAdmin):
list_display = ['name']
save_on_top = True
class CustomSite(admin.AdminSite):
pass
class TestRegistration(TestCase):
def setUp(self):
self.site = admin.AdminSite()
@@ -62,3 +69,55 @@ def test_abstract_model(self):
Refs #12004.
"""
self.assertRaises(ImproperlyConfigured, self.site.register, Location)
class TestRegistrationDecorator(TestCase):
"""
Tests the register decorator in admin.decorators
For clarity:
@register(Person)
class AuthorAdmin(ModelAdmin):
pass
is functionally equal to (the way it is written in these tests):
AuthorAdmin = register(Person)(AuthorAdmin)
"""
def setUp(self):
self.default_site = site
self.custom_site = CustomSite()
def test_basic_registration(self):
register(Person)(NameAdmin)
self.assertTrue(
isinstance(self.default_site._registry[Person],
admin.options.ModelAdmin)
)
def test_custom_site_registration(self):
register(Person, site=self.custom_site)(NameAdmin)
self.assertTrue(
isinstance(self.custom_site._registry[Person],
admin.options.ModelAdmin)
)
def test_multiple_registration(self):
register(Traveler, Place)(NameAdmin)
self.assertTrue(
isinstance(self.default_site._registry[Traveler],
admin.options.ModelAdmin)
)
self.assertTrue(
isinstance(self.default_site._registry[Place],
admin.options.ModelAdmin)
)
def test_wrapped_class_not_a_model_admin(self):
self.assertRaisesMessage(ValueError, 'Wrapped class must sublcass ModelAdmin.',
register(Person), CustomSite)
def test_custom_site_not_an_admin_site(self):
self.assertRaisesMessage(ValueError, 'site must subclass AdminSite',
register(Person, site=Traveler), NameAdmin)

0 comments on commit 9851484

Please sign in to comment.