class TestCflatpagesAdmin(TestCase): def setUp(self): self.site = AdminSite() def test_category_admin(self): """ Category admin """ self.assertIsNone( self.site.register(models.Category, admin.CategoryAdmin)) def test_page_admin(self): """ Page admin """ self.assertIsNone( self.site.register(models.CFlatPage, admin.CategorizedFlatPageAdmin)) @override_settings() def test_page_settings_admin(self): """ Page admin """ settings.INSTALLED_APPS = settings.INSTALLED_APPS + [ "ckeditor", ] self.assertIsNone( self.site.register(models.CFlatPage, admin.CategorizedFlatPageAdmin)) def tearDown(self): pass
class TestCflatpagesAdmin(TestCase): def setUp(self): self.site = AdminSite() def test_category_admin(self): """ Category admin """ self.assertIsNone(self.site.register(models.Category, admin.CategoryAdmin)) def test_page_admin(self): """ Page admin """ self.assertIsNone(self.site.register(models.CFlatPage, admin.CategorizedFlatPageAdmin)) @override_settings() def test_page_settings_admin(self): """ Page admin """ settings.INSTALLED_APPS = settings.INSTALLED_APPS + ["ckeditor"] self.assertIsNone(self.site.register(models.CFlatPage, admin.CategorizedFlatPageAdmin)) def tearDown(self): pass
def test_autocomplete_is_onetoone(self): class UserAdmin(ModelAdmin): search_fields = ('name', ) class Admin(ModelAdmin): autocomplete_fields = ('best_friend', ) site = AdminSite() site.register(User, UserAdmin) self.assertIsValid(Admin, ValidationTestModel, admin_site=site)
def test_autocomplete_is_valid(self): class SearchFieldsAdmin(ModelAdmin): search_fields = 'name' class AutocompleteAdmin(ModelAdmin): autocomplete_fields = ('featuring',) site = AdminSite() site.register(Band, SearchFieldsAdmin) self.assertIsValid(AutocompleteAdmin, Song, admin_site=site)
def test_autocomplete_is_onetoone(self): class UserAdmin(ModelAdmin): search_fields = ('name',) class Admin(ModelAdmin): autocomplete_fields = ('best_friend',) site = AdminSite() site.register(User, UserAdmin) self.assertIsValid(Admin, ValidationTestModel, admin_site=site)
def test_autocomplete_is_valid(self): class SearchFieldsAdmin(ModelAdmin): search_fields = 'name' class AutocompleteAdmin(ModelAdmin): autocomplete_fields = ('featuring', ) site = AdminSite() site.register(Band, SearchFieldsAdmin) self.assertIsValid(AutocompleteAdmin, Song, admin_site=site)
def test_autocomplete_e040(self): class NoSearchFieldsAdmin(ModelAdmin): pass class AutocompleteAdmin(ModelAdmin): autocomplete_fields = ('featuring', ) site = AdminSite() site.register(Band, NoSearchFieldsAdmin) self.assertIsInvalid( AutocompleteAdmin, Song, msg=('NoSearchFieldsAdmin must define "search_fields", because ' 'it\'s referenced by AutocompleteAdmin.autocomplete_fields.'), id='admin.E040', invalid_obj=AutocompleteAdmin, admin_site=site, )
def test_validation_only_runs_in_debug(self): # Ensure validation only runs when DEBUG = True with override_settings(DEBUG=True): class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = 10 site = AdminSite() six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.", site.register, ValidationTestModel, ValidationTestModelAdmin, ) with override_settings(DEBUG=False): site = AdminSite() site.register(ValidationTestModel, ValidationTestModelAdmin)
def test_autocomplete_e040(self): class NoSearchFieldsAdmin(ModelAdmin): pass class AutocompleteAdmin(ModelAdmin): autocomplete_fields = ('featuring',) site = AdminSite() site.register(Band, NoSearchFieldsAdmin) self.assertIsInvalid( AutocompleteAdmin, Song, msg=( 'NoSearchFieldsAdmin must define "search_fields", because ' 'it\'s referenced by AutocompleteAdmin.autocomplete_fields.' ), id='admin.E040', invalid_obj=AutocompleteAdmin, admin_site=site, )
def test_validation_only_runs_in_debug(self): # Ensure validation only runs when DEBUG = True with override_settings(DEBUG=True): class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = 10 site = AdminSite() six.assertRaisesRegex( self, ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.", site.register, ValidationTestModel, ValidationTestModelAdmin, ) with override_settings(DEBUG=False): site = AdminSite() site.register(ValidationTestModel, ValidationTestModelAdmin)
def test_validation_only_runs_in_debug(self): # Ensure validation only runs when DEBUG = True try: settings.DEBUG = True class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = 10 site = AdminSite() self.assertRaisesRegexp( ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.", site.register, ValidationTestModel, ValidationTestModelAdmin, ) finally: settings.DEBUG = False site = AdminSite() site.register(ValidationTestModel, ValidationTestModelAdmin)
def test_validation_only_runs_in_debug(self): # Ensure validation only runs when DEBUG = True try: settings.DEBUG = True class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = 10 site = AdminSite() self.assertRaisesRegexp( ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.", site.register, ValidationTestModel, ValidationTestModelAdmin, ) finally: settings.DEBUG = False site = AdminSite() site.register(ValidationTestModel, ValidationTestModelAdmin)
from django.contrib.admin.sites import AdminSite from libscampi.contrib.cms.renaissance import models as renaissance_models, admin as renaissance_admin from libscampi.contrib.cms.conduit import models as conduit_models, admin as conduit_admin from libscampi.contrib.cms.communism import models as communism_models, admin as communism_admin from libscampi.contrib.cms.newsengine import models as newsengine_models, admin as newsengine_admin cms_admin = AdminSite() # Admin for communism cms_admin.register(communism_models.Theme) cms_admin.register(communism_models.StyleSheet, communism_admin.GenericDOMElementAdmin) cms_admin.register(communism_models.Javascript, communism_admin.GenericDOMElementAdmin) cms_admin.register(communism_models.Realm, communism_admin.RealmAdmin) cms_admin.register(communism_models.RealmNotification, communism_admin.RealmNotificationAdmin) cms_admin.register(communism_models.Section, communism_admin.SectionAdmin) cms_admin.register(communism_models.Slice, communism_admin.SliceAdmin) cms_admin.register(communism_models.NamedBox, communism_admin.BoxAdmin) cms_admin.register(communism_models.Commune, communism_admin.CommuneAdmin) cms_admin.register(communism_models.Application, communism_admin.ApplicationAdmin) # Admin for conduit cms_admin.register(conduit_models.DynamicPicker, conduit_admin.DynamicPickerAdmin) cms_admin.register(conduit_models.StaticPicker) cms_admin.register(conduit_models.PickerTemplate, conduit_admin.PickerTemplateAdmin) # Admin for newsengine cms_admin.register(newsengine_models.Article, newsengine_admin.ArticleAdmin) cms_admin.register(newsengine_models.ArticleTranslation) cms_admin.register(newsengine_models.StoryCategory) cms_admin.register(newsengine_models.Story, newsengine_admin.StoryAdmin) cms_admin.register(newsengine_models.PublishCategory, newsengine_admin.PublishCategoryAdmin)
from django.contrib.admin.sites import AdminSite from django.contrib.admin import site as admin from django.contrib.databrowse import site as databrowse management = AdminSite("management") assemblies = AdminSite("assemblies") basic = AdminSite("basic") structure = AdminSite("structures") types = AdminSite("types") combined = AdminSite("combined") advanced = AdminSite("advanced") from django.contrib.auth.models import Group, User from django.contrib.auth.admin import GroupAdmin, UserAdmin management.register(Group, GroupAdmin) management.register(User, UserAdmin) from django.contrib.sites.models import Site from django.contrib.sites.admin import SiteAdmin management.register(Site, SiteAdmin) def registerer(*sites): def register(model, modeladmin=None, **kwargs): if kwargs.get("advanced"): admins = (admin, types, advanced) else: admins = sites + (admin, combined, advanced) for site in admins:
class ModelAdminTests(TestCase): def setUp(self): self.band = Band.objects.create( name='The Doors', bio='', sign_date=date(1965, 1, 1), ) self.site = AdminSite() def test_modeladmin_str(self): ma = ModelAdmin(Band, self.site) self.assertEqual(str(ma), 'modeladmin.ModelAdmin') # form/fields/fieldsets interaction ############################## def test_default_fields(self): ma = ModelAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'bio', 'sign_date']) self.assertEqual(list(ma.get_fields(request)), ['name', 'bio', 'sign_date']) self.assertEqual(list(ma.get_fields(request, self.band)), ['name', 'bio', 'sign_date']) self.assertIsNone(ma.get_exclude(request, self.band)) def test_default_fieldsets(self): # fieldsets_add and fieldsets_change should return a special data structure that # is used in the templates. They should generate the "right thing" whether we # have specified a custom form, the fields argument, or nothing at all. # # Here's the default case. There are no custom form_add/form_change methods, # no fields argument, and no fieldsets argument. ma = ModelAdmin(Band, self.site) self.assertEqual(ma.get_fieldsets(request), [(None, { 'fields': ['name', 'bio', 'sign_date'] })]) self.assertEqual(ma.get_fieldsets(request, self.band), [(None, { 'fields': ['name', 'bio', 'sign_date'] })]) def test_get_fieldsets(self): # get_fieldsets() is called when figuring out form fields (#18681). class BandAdmin(ModelAdmin): def get_fieldsets(self, request, obj=None): return [(None, {'fields': ['name', 'bio']})] ma = BandAdmin(Band, self.site) form = ma.get_form(None) self.assertEqual(form._meta.fields, ['name', 'bio']) class InlineBandAdmin(TabularInline): model = Concert fk_name = 'main_band' can_delete = False def get_fieldsets(self, request, obj=None): return [(None, {'fields': ['day', 'transport']})] ma = InlineBandAdmin(Band, self.site) form = ma.get_formset(None).form self.assertEqual(form._meta.fields, ['day', 'transport']) def test_lookup_allowed_allows_nonexistent_lookup(self): """ A lookup_allowed allows a parameter whose field lookup doesn't exist. (#21129). """ class BandAdmin(ModelAdmin): fields = ['name'] ma = BandAdmin(Band, self.site) self.assertTrue(ma.lookup_allowed('name__nonexistent', 'test_value')) @isolate_apps('modeladmin') def test_lookup_allowed_onetoone(self): class Department(models.Model): code = models.CharField(max_length=4, unique=True) class Employee(models.Model): department = models.ForeignKey(Department, models.CASCADE, to_field="code") class EmployeeProfile(models.Model): employee = models.OneToOneField(Employee, models.CASCADE) class EmployeeInfo(models.Model): employee = models.OneToOneField(Employee, models.CASCADE) description = models.CharField(max_length=100) class EmployeeProfileAdmin(ModelAdmin): list_filter = [ 'employee__employeeinfo__description', 'employee__department__code', ] ma = EmployeeProfileAdmin(EmployeeProfile, self.site) # Reverse OneToOneField self.assertIs( ma.lookup_allowed('employee__employeeinfo__description', 'test_value'), True) # OneToOneField and ForeignKey self.assertIs( ma.lookup_allowed('employee__department__code', 'test_value'), True) def test_field_arguments(self): # If fields is specified, fieldsets_add and fieldsets_change should # just stick the fields into a formsets structure and return it. class BandAdmin(ModelAdmin): fields = ['name'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_fields(request)), ['name']) self.assertEqual(list(ma.get_fields(request, self.band)), ['name']) self.assertEqual(ma.get_fieldsets(request), [(None, { 'fields': ['name'] })]) self.assertEqual(ma.get_fieldsets(request, self.band), [(None, { 'fields': ['name'] })]) def test_field_arguments_restricted_on_form(self): # If fields or fieldsets is specified, it should exclude fields on the # Form class to the fields specified. This may cause errors to be # raised in the db layer if required model fields aren't in fields/ # fieldsets, but that's preferable to ghost errors where a field in the # Form class isn't being displayed because it's not in fields/fieldsets. # Using `fields`. class BandAdmin(ModelAdmin): fields = ['name'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name']) self.assertEqual(list(ma.get_form(request, self.band).base_fields), ['name']) # Using `fieldsets`. class BandAdmin(ModelAdmin): fieldsets = [(None, {'fields': ['name']})] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name']) self.assertEqual(list(ma.get_form(request, self.band).base_fields), ['name']) # Using `exclude`. class BandAdmin(ModelAdmin): exclude = ['bio'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'sign_date']) # You can also pass a tuple to `exclude`. class BandAdmin(ModelAdmin): exclude = ('bio', ) ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'sign_date']) # Using `fields` and `exclude`. class BandAdmin(ModelAdmin): fields = ['name', 'bio'] exclude = ['bio'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name']) def test_custom_form_meta_exclude_with_readonly(self): """ The custom ModelForm's `Meta.exclude` is respected when used in conjunction with `ModelAdmin.readonly_fields` and when no `ModelAdmin.exclude` is defined (#14496). """ # With ModelAdmin class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ['bio'] class BandAdmin(ModelAdmin): readonly_fields = ['name'] form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['sign_date']) # With InlineModelAdmin class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): readonly_fields = ['transport'] form = AdminConcertForm fk_name = 'main_band' model = Concert class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ['main_band', 'opening_band', 'id', 'DELETE']) def test_custom_formfield_override_readonly(self): class AdminBandForm(forms.ModelForm): name = forms.CharField() class Meta: exclude = () model = Band class BandAdmin(ModelAdmin): form = AdminBandForm readonly_fields = ['name'] ma = BandAdmin(Band, self.site) # `name` shouldn't appear in base_fields because it's part of # readonly_fields. self.assertEqual(list(ma.get_form(request).base_fields), ['bio', 'sign_date']) # But it should appear in get_fields()/fieldsets() so it can be # displayed as read-only. self.assertEqual(list(ma.get_fields(request)), ['bio', 'sign_date', 'name']) self.assertEqual(list(ma.get_fieldsets(request)), [(None, { 'fields': ['bio', 'sign_date', 'name'] })]) def test_custom_form_meta_exclude(self): """ The custom ModelForm's `Meta.exclude` is overridden if `ModelAdmin.exclude` or `InlineModelAdmin.exclude` are defined (#14496). """ # With ModelAdmin class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ['bio'] class BandAdmin(ModelAdmin): exclude = ['name'] form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['bio', 'sign_date']) # With InlineModelAdmin class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): exclude = ['transport'] form = AdminConcertForm fk_name = 'main_band' model = Concert class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ['main_band', 'opening_band', 'day', 'id', 'DELETE']) def test_overriding_get_exclude(self): class BandAdmin(ModelAdmin): def get_exclude(self, request, obj=None): return ['name'] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request).base_fields), ['bio', 'sign_date']) def test_get_exclude_overrides_exclude(self): class BandAdmin(ModelAdmin): exclude = ['bio'] def get_exclude(self, request, obj=None): return ['name'] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request).base_fields), ['bio', 'sign_date']) def test_get_exclude_takes_obj(self): class BandAdmin(ModelAdmin): def get_exclude(self, request, obj=None): if obj: return ['sign_date'] return ['name'] self.assertEqual( list( BandAdmin(Band, self.site).get_form(request, self.band).base_fields), ['name', 'bio']) def test_custom_form_validation(self): # If a form is specified, it should use it allowing custom validation # to work properly. This won't break any of the admin widgets or media. class AdminBandForm(forms.ModelForm): delete = forms.BooleanField() class BandAdmin(ModelAdmin): form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'bio', 'sign_date', 'delete']) self.assertEqual( type(ma.get_form(request).base_fields['sign_date'].widget), AdminDateWidget) def test_form_exclude_kwarg_override(self): """ The `exclude` kwarg passed to `ModelAdmin.get_form()` overrides all other declarations (#8999). """ class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ['name'] class BandAdmin(ModelAdmin): exclude = ['sign_date'] form = AdminBandForm def get_form(self, request, obj=None, **kwargs): kwargs['exclude'] = ['bio'] return super().get_form(request, obj, **kwargs) ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'sign_date']) def test_formset_exclude_kwarg_override(self): """ The `exclude` kwarg passed to `InlineModelAdmin.get_formset()` overrides all other declarations (#8999). """ class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): exclude = ['transport'] form = AdminConcertForm fk_name = 'main_band' model = Concert def get_formset(self, request, obj=None, **kwargs): kwargs['exclude'] = ['opening_band'] return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ['main_band', 'day', 'transport', 'id', 'DELETE']) def test_formset_overriding_get_exclude_with_form_fields(self): class AdminConcertForm(forms.ModelForm): class Meta: model = Concert fields = ['main_band', 'opening_band', 'day', 'transport'] class ConcertInline(TabularInline): form = AdminConcertForm fk_name = 'main_band' model = Concert def get_exclude(self, request, obj=None): return ['opening_band'] class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ['main_band', 'day', 'transport', 'id', 'DELETE']) def test_formset_overriding_get_exclude_with_form_exclude(self): class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): form = AdminConcertForm fk_name = 'main_band' model = Concert def get_exclude(self, request, obj=None): return ['opening_band'] class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ['main_band', 'day', 'transport', 'id', 'DELETE']) def test_queryset_override(self): # If the queryset of a ModelChoiceField in a custom form is overridden, # RelatedFieldWidgetWrapper doesn't mess that up. band2 = Band.objects.create(name='The Beatles', bio='', sign_date=date(1962, 1, 1)) ma = ModelAdmin(Concert, self.site) form = ma.get_form(request)() self.assertHTMLEqual( str(form["main_band"]), '<div class="related-widget-wrapper">' '<select name="main_band" id="id_main_band" required>' '<option value="" selected>---------</option>' '<option value="%d">The Beatles</option>' '<option value="%d">The Doors</option>' '</select></div>' % (band2.id, self.band.id)) class AdminConcertForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["main_band"].queryset = Band.objects.filter( name='The Doors') class ConcertAdminWithForm(ModelAdmin): form = AdminConcertForm ma = ConcertAdminWithForm(Concert, self.site) form = ma.get_form(request)() self.assertHTMLEqual( str(form["main_band"]), '<div class="related-widget-wrapper">' '<select name="main_band" id="id_main_band" required>' '<option value="" selected>---------</option>' '<option value="%d">The Doors</option>' '</select></div>' % self.band.id) def test_regression_for_ticket_15820(self): """ `obj` is passed from `InlineModelAdmin.get_fieldsets()` to `InlineModelAdmin.get_formset()`. """ class CustomConcertForm(forms.ModelForm): class Meta: model = Concert fields = ['day'] class ConcertInline(TabularInline): model = Concert fk_name = 'main_band' def get_formset(self, request, obj=None, **kwargs): if obj: kwargs['form'] = CustomConcertForm return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] Concert.objects.create(main_band=self.band, opening_band=self.band, day=1) ma = BandAdmin(Band, self.site) inline_instances = ma.get_inline_instances(request) fieldsets = list(inline_instances[0].get_fieldsets(request)) self.assertEqual(fieldsets[0][1]['fields'], ['main_band', 'opening_band', 'day', 'transport']) fieldsets = list(inline_instances[0].get_fieldsets( request, inline_instances[0].model)) self.assertEqual(fieldsets[0][1]['fields'], ['day']) # radio_fields behavior ########################################### def test_default_foreign_key_widget(self): # First, without any radio_fields specified, the widgets for ForeignKey # and fields with choices specified ought to be a basic Select widget. # ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so # they need to be handled properly when type checking. For Select fields, all of # the choices lists have a first entry of dashes. cma = ModelAdmin(Concert, self.site) cmafa = cma.get_form(request) self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget), Select) self.assertEqual(list(cmafa.base_fields['main_band'].widget.choices), [('', '---------'), (self.band.id, 'The Doors')]) self.assertEqual(type(cmafa.base_fields['opening_band'].widget.widget), Select) self.assertEqual( list(cmafa.base_fields['opening_band'].widget.choices), [('', '---------'), (self.band.id, 'The Doors')]) self.assertEqual(type(cmafa.base_fields['day'].widget), Select) self.assertEqual(list(cmafa.base_fields['day'].widget.choices), [('', '---------'), (1, 'Fri'), (2, 'Sat')]) self.assertEqual(type(cmafa.base_fields['transport'].widget), Select) self.assertEqual(list(cmafa.base_fields['transport'].widget.choices), [('', '---------'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')]) def test_foreign_key_as_radio_field(self): # Now specify all the fields as radio_fields. Widgets should now be # RadioSelect, and the choices list should have a first entry of 'None' if # blank=True for the model field. Finally, the widget should have the # 'radiolist' attr, and 'inline' as well if the field is specified HORIZONTAL. class ConcertAdmin(ModelAdmin): radio_fields = { 'main_band': HORIZONTAL, 'opening_band': VERTICAL, 'day': VERTICAL, 'transport': HORIZONTAL, } cma = ConcertAdmin(Concert, self.site) cmafa = cma.get_form(request) self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['main_band'].widget.attrs, {'class': 'radiolist inline'}) self.assertEqual(list(cmafa.base_fields['main_band'].widget.choices), [(self.band.id, 'The Doors')]) self.assertEqual(type(cmafa.base_fields['opening_band'].widget.widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['opening_band'].widget.attrs, {'class': 'radiolist'}) self.assertEqual( list(cmafa.base_fields['opening_band'].widget.choices), [('', 'None'), (self.band.id, 'The Doors')]) self.assertEqual(type(cmafa.base_fields['day'].widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['day'].widget.attrs, {'class': 'radiolist'}) self.assertEqual(list(cmafa.base_fields['day'].widget.choices), [(1, 'Fri'), (2, 'Sat')]) self.assertEqual(type(cmafa.base_fields['transport'].widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['transport'].widget.attrs, {'class': 'radiolist inline'}) self.assertEqual(list(cmafa.base_fields['transport'].widget.choices), [('', 'None'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')]) class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ('transport', ) class ConcertAdmin(ModelAdmin): form = AdminConcertForm ma = ConcertAdmin(Concert, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['main_band', 'opening_band', 'day']) class AdminConcertForm(forms.ModelForm): extra = forms.CharField() class Meta: model = Concert fields = ['extra', 'transport'] class ConcertAdmin(ModelAdmin): form = AdminConcertForm ma = ConcertAdmin(Concert, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['extra', 'transport']) class ConcertInline(TabularInline): form = AdminConcertForm model = Concert fk_name = 'main_band' can_delete = True class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ['extra', 'transport', 'id', 'DELETE', 'main_band']) def test_log_actions(self): ma = ModelAdmin(Band, self.site) mock_request = MockRequest() mock_request.user = User.objects.create(username='******') content_type = get_content_type_for_model(self.band) tests = ( (ma.log_addition, ADDITION, { 'added': {} }), (ma.log_change, CHANGE, { 'changed': { 'fields': ['name', 'bio'] } }), (ma.log_deletion, DELETION, str(self.band)), ) for method, flag, message in tests: with self.subTest(name=method.__name__): created = method(mock_request, self.band, message) fetched = LogEntry.objects.filter( action_flag=flag).latest('id') self.assertEqual(created, fetched) self.assertEqual(fetched.action_flag, flag) self.assertEqual(fetched.content_type, content_type) self.assertEqual(fetched.object_id, str(self.band.pk)) self.assertEqual(fetched.user, mock_request.user) if flag == DELETION: self.assertEqual(fetched.change_message, '') self.assertEqual(fetched.object_repr, message) else: self.assertEqual(fetched.change_message, str(message)) self.assertEqual(fetched.object_repr, str(self.band)) def test_get_autocomplete_fields(self): class NameAdmin(ModelAdmin): search_fields = ['name'] class SongAdmin(ModelAdmin): autocomplete_fields = ['featuring'] fields = ['featuring', 'band'] class OtherSongAdmin(SongAdmin): def get_autocomplete_fields(self, request): return ['band'] self.site.register(Band, NameAdmin) try: # Uses autocomplete_fields if not overridden. model_admin = SongAdmin(Song, self.site) form = model_admin.get_form(request)() self.assertIsInstance(form.fields['featuring'].widget.widget, AutocompleteSelectMultiple) # Uses overridden get_autocomplete_fields model_admin = OtherSongAdmin(Song, self.site) form = model_admin.get_form(request)() self.assertIsInstance(form.fields['band'].widget.widget, AutocompleteSelect) finally: self.site.unregister(Band)
ImplementationRelationDescription, ImplementationRelationType, \ ImplementationComputedFieldDescription, ComponentInstanceField, \ ComponentInstanceRelation from ref.models.parameters import MageParam from ref.models.com import Link ################################################################################ ## Create admin site object ################################################################################ site = AdminSite() site.login_template = 'login.html' site.site_header = "Administration MAGE" site.site_title = 'MAGE' site.index_title = None site.register(Group, GroupAdmin) site.register(User, UserAdmin) ################################################################################ ## Parameters ################################################################################ class MageParamAdmin(ModelAdmin): list_display = [ 'app', 'key', 'value', 'model', 'axis1', 'description',
from django.conf.urls import include, patterns, url from django.contrib.admin.sites import AdminSite from multilingual.admin import MultilingualModelAdmin from .models import Article SITE = AdminSite() SITE.register(Article, MultilingualModelAdmin) urlpatterns = patterns('', url(r'^admin/', include(SITE.urls)), )
from django.conf.urls import include, patterns, url from django.contrib.admin.sites import AdminSite from multilingual.admin import MultilingualModelAdmin from .models import Multiling SITE = AdminSite() SITE.register(Multiling, MultilingualModelAdmin) urlpatterns = patterns('', url(r'^admin/', include(SITE.urls)), )
from django.contrib import admin from django.forms import ModelForm from django.contrib.auth.models import User from django.core.exceptions import ObjectDoesNotExist from productions.models import * from auditions.models import * from django.contrib.admin.sites import AdminSite admin_site = AdminSite() # Allow administration of admin users admin_site.register(User) # Allow administration of productions admin_site.register(ProductionType) class ProductionAdmin(admin.ModelAdmin): list_display = ('name', 'default_production') admin_site.register(Production, ProductionAdmin) # The form which is used for each audition when editing an actor. class AuditionInlineForm(ModelForm): model = Audition def __init__(self, *args, **kwargs): super(AuditionInlineForm, self).__init__(*args, **kwargs)
from flatblocks.models import FlatBlock from courses.models import ( Course, Student, Subject, Teacher, Timeslot, UserProfile) admin_site = AdminSite() class CourseAdmin(admin.ModelAdmin): pass admin_site.register(Course, CourseAdmin) admin_site.register(User) class UserProfileAdmin(admin.ModelAdmin): pass admin_site.register(UserProfile, UserProfileAdmin) class StudentAdmin(admin.ModelAdmin): pass admin_site.register(Student, StudentAdmin)
from django.contrib import admin from django.forms import ModelForm from django.contrib.auth.models import User from django.core.exceptions import ObjectDoesNotExist from productions.models import * from auditions.models import * from django.contrib.admin.sites import AdminSite admin_site = AdminSite() # Allow administration of admin users admin_site.register(User) # Allow administration of productions admin_site.register(ProductionType) class ProductionAdmin(admin.ModelAdmin): list_display = ('name', 'default_production') admin_site.register(Production, ProductionAdmin) # The form which is used for each audition when editing an actor. class AuditionInlineForm(ModelForm): model = Audition
from django.contrib import admin from django.contrib.admin.sites import AdminSite from .models import * # Register your models here. adminSite = AdminSite() adminSite.register(Expense) adminSite.register(User)
and request.user.groups.filter(name='users').count() admin = SuperAdminSite(name='admin') staff = AdminSite(name='staff') user = UserSite(name='user') # admin admin.register(Site, SiteAdmin) admin.register(User, UserAdmin) admin.register(Group, GroupAdmin) admin.register(Author, AuthorAdmin) admin.register(BookCategory, BookCategoryAdmin) admin.register(Book, BookAdmin) admin.register(CdCategory, CdCategoryAdmin) admin.register(Cd, CdAdmin) admin.register(DvdCategory, DvdCategoryAdmin) admin.register(Dvd, DvdAdmin) # staff staff.register(Author, AuthorAdmin) staff.register(BookCategory, BookCategoryAdmin) staff.register(CdCategory, CdCategoryAdmin) staff.register(DvdCategory, DvdCategoryAdmin) # user user.register(Book, UserBookAdmin) user.register(Cd, UserCdAdmin) user.register(Dvd, UserDvdAdmin)
from django.contrib import admin from django.contrib.admin.sites import AdminSite from evolve.rules.models import (BuildingKind, Resource, Science, Variant, Age, City, CitySpecial, Building, BuildOption, Cost, CostLine, Effect, Building, BuildOption) from evolve.rules.forms import EffectForm site = AdminSite('rules') site.register(BuildingKind) site.register(Resource) site.register(Science) site.register(Variant) site.register(Age) class CitySpecialInline(admin.TabularInline): model = CitySpecial class CityAdmin(admin.ModelAdmin): inlines = [CitySpecialInline] list_display = ('name', 'resource') class BuildingAdmin(admin.ModelAdmin): list_display = ('name', 'kind', 'cost', 'effect') list_filter = ('kind', )
define a ModelAdmin for every site where is needed. By now, every ModelAdmin from every module inside this package is imported by hand and registered when needed. Maybe it could be possible automate these proccess by defining a tupple in every module with una Model and one ModelAdmin or with one Model, and iterate over every module inside this package and register those tuples. To associate a tuple with an specific admin site, a dict could be used instead of only the tuple (i.e a dict of sites:tuples) The only issue to resolve when automated is the authorization issue. How to associate an admin_site with an authorization evaluation... """ from django.contrib import admin from django.contrib.admin.sites import AdminSite from ..models import Building from .building import BuildingAdmin admin_site = AdminSite('admin_site') admin_site.register(Building, BuildingAdmin)
To associate a tuple with an specific admin site, a dict could be used instead of only the tuple (i.e a dict of sites:tuples) The only issue to resolve when automated is the authorization issue. How to associate an admin_site with an authorization evaluation... """ from django.contrib.gis import admin from django.contrib.admin.sites import AdminSite from photologue.models import Gallery from photologue.models import GalleryUpload from photologue.models import Photo from photologue.admin import PhotoAdmin from photologue.admin import GalleryAdmin from funvisis.geo.bridges.models import Bridge from funvisis.geo.bridges.admin import BridgeAdmin from funvisis.gallery.admin import FvisGalleryAdmin from ..models import BridgeInspection from .bridgeinspection import BridgeInspectionAdmin admin_site = AdminSite("admin_site") admin_site.register(BridgeInspection, BridgeInspectionAdmin) admin_site.register(Bridge, BridgeAdmin) admin_site.register(Gallery, FvisGalleryAdmin) admin_site.register(Photo, PhotoAdmin)
#!/usr/bin/env python # -*- coding: utf-8 -*- from django.contrib import admin from .models import MyModel from django.contrib.admin.sites import AdminSite, site myadminsite = AdminSite() class MyModelAdmin(admin.ModelAdmin): model = MyModel myadminsite.register(MyModel, MyModelAdmin)
admin.site.register(Donor, DonorAdmin) # advanced advanced_admin = AdminSite(name='advanced') class DonorAdvanced(admin.ModelAdmin): list_display = ('__unicode__', 'membership', 'asked', 'pledged', 'gifted') list_filter = ('asked', 'membership__giving_project') search_fields = ['firstname', 'lastname'] class MembershipAdvanced(admin.ModelAdmin): list_display = ('member', 'giving_project', estimated, pledged, overdue_steps, 'last_activity', 'approved', 'leader') actions = [approve] list_filter = ('approved', 'leader', 'giving_project') class MemberAdvanced(admin.ModelAdmin): list_display = ('__unicode__', 'email') search_fields = ['first_name', 'last_name', 'email'] class StepAdv(admin.ModelAdmin): list_display = ('description', 'donor', 'date', 'complete') advanced_admin.register(User, UserAdmin) advanced_admin.register(Member, MemberAdvanced) advanced_admin.register(Donor, DonorAdvanced) advanced_admin.register(Membership, MembershipAdvanced) advanced_admin.register(GivingProject, GPAdmin) advanced_admin.register(NewsItem, NewsAdmin) advanced_admin.register(Event, EventAdmin) advanced_admin.register(Step)
FieldListFilter, BooleanFieldListFilter, RelatedFieldListFilter, ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter) import os import copy from django.conf import settings from django.utils.importlib import import_module from django.utils.module_loading import module_has_submodule BASE_DIR = os.path.dirname(os.path.dirname(__file__)) site = AdminSite() site.index_template=BASE_DIR+"/templates/admin/index.html" site.register(User, UserAdmin) def autodiscover(): """ Autodiscover function from django.contrib.admin """ for app in settings.INSTALLED_APPS: mod = import_module(app) try: before_import_registry = copy.copy(site._registry) import_module('%s.admin' % app)
from django.contrib.admin.sites import AdminSite from django.contrib.auth.models import User from django.contrib.auth.admin import UserAdmin from pages.models import Page from pages.admin import PageAdmin publisher_admin = AdminSite('pageadmin') publisher_admin.register(Page, PageAdmin) publisher_admin.register(User, UserAdmin)
from django.contrib import admin from django.contrib.admin.sites import AdminSite import core import core.admin site = AdminSite("settings") # pylint: disable-msg=C0103 site.index_template = "settings/index.html" site.app_index_template = "settings/app_index.html" site.register(( core.models.Semester, core.models.Group, )) site.register(core.models.Subject, core.admin.SubjectAdmin) # site.register(core.models.Lesson, LessonAdmin)
from django.contrib.admin.sites import AdminSite from django.contrib.auth.models import User from django.contrib.auth.admin import UserAdmin from pages.models import Page from pages.admin import PageAdmin publisher_admin = AdminSite('pageadmin') publisher_admin.register(Page, PageAdmin) publisher_admin.register(User, UserAdmin) def groups_part_of(self,obj): return ', '.join([group.name for group in obj.groups.all()]) def number_of_logins(self,obj): return obj.get_profile().number_of_logins def expiry_date(self,obj): return obj.get_profile().expiry_date UserAdmin.groups_part_of = groups_part_of UserAdmin.number_of_logins = number_of_logins UserAdmin.expiry_date = expiry_date UserAdmin.list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'is_active', 'last_login', 'groups_part_of', 'number_of_logins','expiry_date')
class TestPublishSelectedAction(TransactionTestCase, RequestFactoryMixin): def setUp(self): super(TestPublishSelectedAction, self).setUp() self.fp1 = Page.objects.create(slug='fp1', title='FP1') self.fp2 = Page.objects.create(slug='fp2', title='FP2') self.fp3 = Page.objects.create(slug='fp3', title='FP3') self.admin_site = AdminSite('Test Admin') self.page_admin = PublishableAdmin(Page, self.admin_site) self.user = User.objects.create_user('test1', '*****@*****.**', 'jkljkl') # override urls, so reverse works settings.ROOT_URLCONF = [ url('^admin/', include(self.admin_site.urls)), ] def test_publish_selected_confirm(self): pages = Page.objects.exclude(id=self.fp3.id) class dummy_request(object): META = {} POST = {} class user(object): @classmethod def has_perm(cls, *arg): return True @classmethod def get_and_delete_messages(cls): return [] response = publish_selected(self.page_admin, dummy_request, pages) self.failIf(Page.objects.published().count() > 0) self.failUnless(response is not None) self.failUnlessEqual(200, response.status_code) def test_publish_selected_confirmed(self): pages = Page.objects.exclude(id=self.fp3.id) dummy_request = self.build_post_request({'post': True}) response = publish_selected(self.page_admin, dummy_request, pages) self.failUnlessEqual(2, Page.objects.published().count()) # self.failUnless(getattr(self, '_message', None) is not None) self.failUnless(response is None) def test_convert_all_published_to_html(self): self.admin_site.register(Page, PublishableAdmin) all_published = NestedSet() page = Page.objects.create(slug='here', title='title') block = PageBlock.objects.create(page=page, content='stuff here') all_published.add(page) all_published.add(block, parent=page) converted = _convert_all_published_to_html(self.admin_site, all_published) expected = [ u'<a href="../../publish/page/%d/">Page: Page object (Changed - not yet published)</a>' % page.id, [u'Page block: PageBlock object'] ] self.failUnlessEqual(expected, converted) def test_publish_selected_does_not_have_permission(self): self.admin_site.register(Page, PublishableAdmin) pages = Page.objects.exclude(id=self.fp3.id) dummy_request = self.build_post_request({}) dummy_request.user = self.build_common_user() response = publish_selected(self.page_admin, dummy_request, pages) self.failIf(response is None) # publish button should not be in response self.failIf('value="publish_selected"' in response.content) self.failIf('value="Yes, Publish"' in response.content) self.failIf('form' in response.content) self.failIf(Page.objects.published().count() > 0) def test_publish_selected_does_not_have_related_permission(self): # check we can't publish when we don't have permission # for a related model (in this case authors) self.admin_site.register(Author, PublishableAdmin) author = Author.objects.create(name='John') self.fp1.authors.add(author) pages = Page.objects.draft() dummy_request = self.build_post_request({'post': True}) dummy_request.user = self.build_common_user() try: publish_selected(self.page_admin, dummy_request, pages) self.fail() except PermissionDenied: pass self.failIf(Page.objects.published().count() > 0) def test_publish_selected_logs_publication(self): self.admin_site.register(Page, PublishableAdmin) pages = Page.objects.exclude(id=self.fp3.id) dummy_request = self.build_post_request({'post': True}) publish_selected(self.page_admin, dummy_request, pages) # should have logged two publications from django.contrib.admin.models import LogEntry from django.contrib.contenttypes.models import ContentType ContentType.objects.get_for_model(self.fp1).pk self.failUnlessEqual(2, LogEntry.objects.filter().count())
from django.contrib.admin.sites import AdminSite from django.contrib.auth.models import User from django.contrib.auth.admin import UserAdmin from pages.models import Page from pages.admin import PageAdmin from registration.models import UserProfile from registration.admin import UserProfileAdmin publisher_admin = AdminSite('pageadmin') publisher_admin.register(Page, PageAdmin) publisher_admin.register(User, UserAdmin) publisher_admin.register(UserProfile, UserProfileAdmin)
admin = SuperAdminSite(name='adminpanel') staff = AdminSite(name='staffpanel') user = UserSite(name='userpanel') # admin admin.register(Site, SiteAdmin) admin.register(User, UserAdmin) admin.register(Group, GroupAdmin) admin.register(Author, AuthorAdmin) admin.register(BookCategory, BookCategoryAdmin) admin.register(Book, BookAdmin) admin.register(CdCategory, CdCategoryAdmin) admin.register(Cd, CdAdmin) admin.register(DvdCategory, DvdCategoryAdmin) admin.register(Dvd, DvdAdmin) admin.register(TestModel, TestModelAdmin) # staff staff.register(Author, AuthorAdmin) staff.register(BookCategory, BookCategoryAdmin) staff.register(CdCategory, CdCategoryAdmin) staff.register(DvdCategory, DvdCategoryAdmin) staff.register(TestModel, MoreComplicatedTestModelAdmin) # user user.register(Book, UserBookAdmin) user.register(Cd, UserCdAdmin) user.register(Dvd, UserDvdAdmin)
used instead of only the tuple (i.e a dict of sites:tuples) The only issue to resolve when automated is the authorization issue. How to associate an admin_site with an authorization evaluation... """ from django.contrib.gis import admin from django.contrib.admin.sites import AdminSite from photologue.models import Gallery from photologue.models import GalleryUpload from photologue.models import Photo from photologue.admin import PhotoAdmin from photologue.admin import GalleryAdmin from funvisis.gallery.admin import FvisGalleryAdmin from funvisis.geo.buildings.admin import BuildingAdmin from funvisis.geo.buildings.models import Building from ..models import BuildingInspection from .buildinginspection import BuildingInspectionAdmin admin_site = AdminSite('admin_site') admin_site.register(BuildingInspection, BuildingInspectionAdmin) admin_site.register(Building, BuildingAdmin) admin_site.register(Gallery, FvisGalleryAdmin) admin_site.register(Photo, PhotoAdmin)
class PolymorphicParentModelAdmin(admin.ModelAdmin): """ A admin interface that can displays different change/delete pages, depending on the polymorphic model. To use this class, two variables need to be defined: * :attr:`base_model` should * :attr:`child_models` should be a list of (Model, Admin) tuples Alternatively, the following methods can be implemented: * :func:`get_child_models` should return a list of (Model, ModelAdmin) tuples * optionally, :func:`get_child_type_choices` can be overwritten to refine the choices for the add dialog. This class needs to be inherited by the model admin base class that is registered in the site. The derived models should *not* register the ModelAdmin, but instead it should be returned by :func:`get_child_models`. """ #: The base model that the class uses base_model = None #: The child models that should be displayed child_models = None #: Whether the list should be polymorphic too, leave to ``False`` to optimize polymorphic_list = False add_type_template = None add_type_form = PolymorphicModelChoiceForm #: The regular expression to filter the primary key in the URL. #: This accepts only numbers as defensive measure against catch-all URLs. #: If your primary key consists of string values, update this regular expression. pk_regex = '(\d+)' def __init__(self, model, admin_site, *args, **kwargs): super(PolymorphicParentModelAdmin, self).__init__(model, admin_site, *args, **kwargs) self._child_admin_site = AdminSite(name=self.admin_site.name) self._is_setup = False def _lazy_setup(self): if self._is_setup: return # By not having this in __init__() there is less stress on import dependencies as well, # considering an advanced use cases where a plugin system scans for the child models. child_models = self.get_child_models() for Model, Admin in child_models: self.register_child(Model, Admin) self._child_models = dict(child_models) # This is needed to deal with the improved ForeignKeyRawIdWidget in Django 1.4 and perhaps other widgets too. # The ForeignKeyRawIdWidget checks whether the referenced model is registered in the admin, otherwise it displays itself as a textfield. # As simple solution, just make sure all parent admin models are also know in the child admin site. # This should be done after all parent models are registered off course. complete_registry = self.admin_site._registry.copy() complete_registry.update(self._child_admin_site._registry) self._child_admin_site._registry = complete_registry self._is_setup = True def register_child(self, model, model_admin): """ Register a model with admin to display. """ # After the get_urls() is called, the URLs of the child model can't be exposed anymore to the Django URLconf, # which also means that a "Save and continue editing" button won't work. if self._is_setup: raise RegistrationClosed("The admin model can't be registered anymore at this point.") if not issubclass(model, self.base_model): raise TypeError("{0} should be a subclass of {1}".format(model.__name__, self.base_model.__name__)) if not issubclass(model_admin, admin.ModelAdmin): raise TypeError("{0} should be a subclass of {1}".format(model_admin.__name__, admin.ModelAdmin.__name__)) self._child_admin_site.register(model, model_admin) def get_child_models(self): """ Return the derived model classes which this admin should handle. This should return a list of tuples, exactly like :attr:`child_models` is. The model classes can be retrieved as ``base_model.__subclasses__()``, a setting in a config file, or a query of a plugin registration system at your option """ if self.child_models is None: raise NotImplementedError("Implement get_child_models() or child_models") return self.child_models def get_child_type_choices(self): """ Return a list of polymorphic types which can be added. """ choices = [] for model, _ in self.get_child_models(): ct = ContentType.objects.get_for_model(model, for_concrete_model=False) choices.append((ct.id, model._meta.verbose_name)) return choices def _get_real_admin(self, object_id): obj = self.model.objects.non_polymorphic().values('polymorphic_ctype').get(pk=object_id) return self._get_real_admin_by_ct(obj['polymorphic_ctype']) def _get_real_admin_by_ct(self, ct_id): try: ct = ContentType.objects.get_for_id(ct_id) except ContentType.DoesNotExist as e: raise Http404(e) # Handle invalid GET parameters model_class = ct.model_class() if not model_class: raise Http404("No model found for '{0}.{1}'.".format(*ct.natural_key())) # Handle model deletion return self._get_real_admin_by_model(model_class) def _get_real_admin_by_model(self, model_class): # In case of a ?ct_id=### parameter, the view is already checked for permissions. # Hence, make sure this is a derived object, or risk exposing other admin interfaces. if model_class not in self._child_models: raise PermissionDenied("Invalid model '{0}', it must be registered as child model.".format(model_class)) try: # HACK: the only way to get the instance of an model admin, # is to read the registry of the AdminSite. return self._child_admin_site._registry[model_class] except KeyError: raise ChildAdminNotRegistered("No child admin site was registered for a '{0}' model.".format(model_class)) def queryset(self, request): # optimize the list display. qs = super(PolymorphicParentModelAdmin, self).queryset(request) if not self.polymorphic_list: qs = qs.non_polymorphic() return qs def add_view(self, request, form_url='', extra_context=None): """Redirect the add view to the real admin.""" ct_id = int(request.GET.get('ct_id', 0)) if not ct_id: # Display choices return self.add_type_view(request) else: real_admin = self._get_real_admin_by_ct(ct_id) return real_admin.add_view(request, form_url, extra_context) def change_view(self, request, object_id, *args, **kwargs): """Redirect the change view to the real admin.""" # between Django 1.3 and 1.4 this method signature differs. Hence the *args, **kwargs real_admin = self._get_real_admin(object_id) return real_admin.change_view(request, object_id, *args, **kwargs) def delete_view(self, request, object_id, extra_context=None): """Redirect the delete view to the real admin.""" real_admin = self._get_real_admin(object_id) return real_admin.delete_view(request, object_id, extra_context) def get_urls(self): """ Expose the custom URLs for the subclasses and the URL resolver. """ urls = super(PolymorphicParentModelAdmin, self).get_urls() info = self.model._meta.app_label, self.model._meta.module_name # Patch the change URL so it's not a big catch-all; allowing all custom URLs to be added to the end. # The url needs to be recreated, patching url.regex is not an option Django 1.4's LocaleRegexProvider changed it. new_change_url = url(r'^{0}/$'.format(self.pk_regex), self.admin_site.admin_view(self.change_view), name='{0}_{1}_change'.format(*info)) for i, oldurl in enumerate(urls): if oldurl.name == new_change_url.name: urls[i] = new_change_url # Define the catch-all for custom views custom_urls = patterns('', url(r'^(?P<path>.+)$', self.admin_site.admin_view(self.subclass_view)) ) # At this point. all admin code needs to be known. self._lazy_setup() # Add reverse names for all polymorphic models, so the delete button and "save and add" just work. # These definitions are masked by the definition above, since it needs special handling (and a ct_id parameter). dummy_urls = [] for model, _ in self.get_child_models(): admin = self._get_real_admin_by_model(model) dummy_urls += admin.get_urls() return urls + custom_urls + dummy_urls def subclass_view(self, request, path): """ Forward any request to a custom view of the real admin. """ ct_id = int(request.GET.get('ct_id', 0)) if not ct_id: # See if the path started with an ID. try: pos = path.find('/') object_id = long(path[0:pos]) except ValueError: raise Http404("No ct_id parameter, unable to find admin subclass for path '{0}'.".format(path)) ct_id = self.model.objects.values_list('polymorphic_ctype_id', flat=True).get(pk=object_id) real_admin = self._get_real_admin_by_ct(ct_id) resolver = RegexURLResolver('^', real_admin.urls) resolvermatch = resolver.resolve(path) # May raise Resolver404 if not resolvermatch: raise Http404("No match for path '{0}' in admin subclass.".format(path)) return resolvermatch.func(request, *resolvermatch.args, **resolvermatch.kwargs) def add_type_view(self, request, form_url=''): """ Display a choice form to select which page type to add. """ if not self.has_add_permission(request): raise PermissionDenied extra_qs = '' if request.META['QUERY_STRING']: extra_qs = '&' + request.META['QUERY_STRING'] choices = self.get_child_type_choices() if len(choices) == 1: return HttpResponseRedirect('?ct_id={0}{1}'.format(choices[0][0], extra_qs)) # Create form form = self.add_type_form( data=request.POST if request.method == 'POST' else None, initial={'ct_id': choices[0][0]} ) form.fields['ct_id'].choices = choices if form.is_valid(): return HttpResponseRedirect('?ct_id={0}{1}'.format(form.cleaned_data['ct_id'], extra_qs)) # Wrap in all admin layout fieldsets = ((None, {'fields': ('ct_id',)}),) adminForm = AdminForm(form, fieldsets, {}, model_admin=self) media = self.media + adminForm.media opts = self.model._meta context = { 'title': _('Add %s') % force_text(opts.verbose_name), 'adminform': adminForm, 'is_popup': "_popup" in request.REQUEST, 'media': mark_safe(media), 'errors': AdminErrorList(form, ()), 'app_label': opts.app_label, } return self.render_add_type_form(request, context, form_url) def render_add_type_form(self, request, context, form_url=''): """ Render the page type choice form. """ opts = self.model._meta app_label = opts.app_label context.update({ 'has_change_permission': self.has_change_permission(request), 'form_url': mark_safe(form_url), 'opts': opts, 'add': True, 'save_on_top': self.save_on_top, }) if hasattr(self.admin_site, 'root_path'): context['root_path'] = self.admin_site.root_path # Django < 1.4 context_instance = RequestContext(request, current_app=self.admin_site.name) return render_to_response(self.add_type_template or [ "admin/%s/%s/add_type_form.html" % (app_label, opts.object_name.lower()), "admin/%s/add_type_form.html" % app_label, "admin/polymorphic/add_type_form.html", # added default here "admin/add_type_form.html" ], context, context_instance=context_instance) @property def change_list_template(self): opts = self.model._meta app_label = opts.app_label # Pass the base options base_opts = self.base_model._meta base_app_label = base_opts.app_label return [ "admin/%s/%s/change_list.html" % (app_label, opts.object_name.lower()), "admin/%s/change_list.html" % app_label, # Added base class: "admin/%s/%s/change_list.html" % (base_app_label, base_opts.object_name.lower()), "admin/%s/change_list.html" % base_app_label, "admin/change_list.html" ]
class DonorAdvanced(admin.ModelAdmin): list_display = ('__unicode__', 'membership', 'asked', 'pledged', 'gifted') list_filter = ('asked', 'membership__giving_project') search_fields = ['firstname', 'lastname'] class MembershipAdvanced(admin.ModelAdmin): list_display = ('member', 'giving_project', estimated, pledged, overdue_steps, 'last_activity', 'approved', 'leader') actions = [approve] list_filter = ('approved', 'leader', 'giving_project') class MemberAdvanced(admin.ModelAdmin): list_display = ('__unicode__', 'email') search_fields = ['first_name', 'last_name', 'email'] class StepAdv(admin.ModelAdmin): list_display = ('description', 'donor', 'date', 'complete') advanced_admin.register(User, UserAdmin) advanced_admin.register(Member, MemberAdvanced) advanced_admin.register(Donor, DonorAdvanced) advanced_admin.register(Membership, MembershipAdvanced) advanced_admin.register(GivingProject, GPAdmin) advanced_admin.register(NewsItem, NewsAdmin) advanced_admin.register(Event, EventAdmin) advanced_admin.register(Step)
ListFilter, SimpleListFilter, FieldListFilter, BooleanFieldListFilter, RelatedFieldListFilter, ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter) import os import copy from django.conf import settings from django.utils.importlib import import_module from django.utils.module_loading import module_has_submodule BASE_DIR = os.path.dirname(os.path.dirname(__file__)) site = AdminSite() site.index_template = BASE_DIR + "/templates/admin/index.html" site.register(User, UserAdmin) def autodiscover(): """ Autodiscover function from django.contrib.admin """ for app in settings.INSTALLED_APPS: mod = import_module(app) try: before_import_registry = copy.copy(site._registry) import_module('%s.admin' % app) except: site._registry = before_import_registry
admin = SuperAdminSite(name='adminpanel') staff = AdminSite(name='staffpanel') user = UserSite(name='userpanel') # admin if apps.is_installed('django.contrib.sites'): admin.register(Site, SiteAdmin) admin.register(User, UserAdmin) admin.register(Group, GroupAdmin) admin.register(Author, AuthorAdmin) admin.register(BookCategory, BookCategoryAdmin) admin.register(Book, BookAdmin) admin.register(CdCategory, CdCategoryAdmin) admin.register(Cd, CdAdmin) admin.register(DvdCategory, DvdCategoryAdmin) admin.register(Dvd, DvdAdmin) admin.register(TestModel, TestModelAdmin) # staff staff.register(Author, AuthorAdmin) staff.register(BookCategory, BookCategoryAdmin) staff.register(CdCategory, CdCategoryAdmin) staff.register(DvdCategory, DvdCategoryAdmin) staff.register(TestModel, MoreComplicatedTestModelAdmin) # user user.register(Book, UserBookAdmin) user.register(Cd, UserCdAdmin) user.register(Dvd, UserDvdAdmin)
from django.contrib import admin from django.contrib.admin.sites import AdminSite from evolve.rules.models import ( BuildingKind, Resource, Science, Variant, Age, City, CitySpecial, Building, BuildOption, Cost, CostLine, Effect, Building, BuildOption ) from evolve.rules.forms import EffectForm site=AdminSite('rules') site.register(BuildingKind) site.register(Resource) site.register(Science) site.register(Variant) site.register(Age) class CitySpecialInline(admin.TabularInline): model = CitySpecial class CityAdmin(admin.ModelAdmin): inlines = [CitySpecialInline] list_display = ('name', 'resource') class BuildingAdmin(admin.ModelAdmin): list_display = ('name', 'kind', 'cost','effect') list_filter = ('kind',) class BuildOptionAdmin(admin.ModelAdmin): list_display = ('building', 'players_needed', 'age')
from django.contrib import admin from .models import * from django.contrib.admin.sites import AdminSite user_admin_site = AdminSite(name='usersadmin') user_admin_site.register(User) user_admin_site.register(Mem) user_admin_site.register(Creator) user_admin_site.register(Sphere) user_admin_site.register(Source) user_admin_site.register(Tag) admin.site.register(User) admin.site.register(Mem) admin.site.register(Creator) admin.site.register(Sphere) admin.site.register(Source) admin.site.register(Tag)
list_filter = [ "promotion", "buy_date", ] # each specified field should be either a BooleanField, CharField, DateField, DateTimeField, IntegerField or ForeignKey. # inlines = [ChoiceInline] # date_hierarchy = 'pub_date' search_fields = ["entry"] list_per_page = 30 # prepopulated_fields = {"comment": ("entry",)} # may be just for SlugField radio_fields = {"pack_by": admin.HORIZONTAL} # readonly_fields = ['add_date'] form = YummyForm admin_site = AdminSite() admin_site.register(Category) admin_site.register(Package) admin_site.register(Yummy, MyYummyAdmin) admin_site.index_template = "min_admin.html" # admin.site.register(Poll) # class PollAdmin(admin.ModelAdmin): # fields = ['pub_date', 'question'] # # admin.site.register(Poll, PollAdmin) # class PollAdmin(admin.ModelAdmin): # fieldsets = [ # (None, {'fields': ['question']}), # ('Date information', {'fields': ['pub_date']}), # ] # admin.site.register(Poll, PollAdmin)
# 'fields':('checkin_time','checkin_station') # }), # ) date_hierarchy = 'checkin_time' ordering = ('-checkout_time',) actions = ['check_in'] search_fields = ['rider__name','rider__penncard','bike__bike_name'] save_on_top = True ## change_form_template = 'c:/djcode/penncycle/templates/admin/app/change_form.html' # make this only work for bikes not already checked in # def check_in(self, request, queryset): # return RidesAdmin.check_in(self, request, queryset) # check_in = admin_check_in def add_view(self, request, extra_context={}): try: station = request.user.groups.exclude(name='Associate')[0].name except: email_razzi("{} tried to sign somebody in it would seem. They were told to check their /admin/auth/user status. They had groups {}".format(request.user.get_full_name(), request.user.groups.all())) return HttpResponse("You don't have any groups. Go to app.penncycle.org/admin/auth/user and make sure 'associate' and your station are checked.") extra_context['station'] = station return super(pcRidesAdmin, self).add_view(request, extra_context=extra_context) pcAdminSite = AdminSite(name='pcadmin') pcAdminSite.register(Ride, pcRidesAdmin) pcAdminSite.register(Payment, PaymentAdmin) pcAdminSite.register(Bike, BikeAdmin) pcAdminSite.register(Student, StudentAdmin) pcAdminSite.register(Comment) # pcAdminSite.register(Station)
class ModelAdminTests(TestCase): @classmethod def setUpTestData(cls): cls.band = Band.objects.create( name="The Doors", bio="", sign_date=date(1965, 1, 1), ) def setUp(self): self.site = AdminSite() def test_modeladmin_str(self): ma = ModelAdmin(Band, self.site) self.assertEqual(str(ma), "modeladmin.ModelAdmin") def test_default_attributes(self): ma = ModelAdmin(Band, self.site) self.assertEqual(ma.actions, ()) self.assertEqual(ma.inlines, ()) # form/fields/fieldsets interaction ############################## def test_default_fields(self): ma = ModelAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name", "bio", "sign_date"]) self.assertEqual(list(ma.get_fields(request)), ["name", "bio", "sign_date"]) self.assertEqual(list(ma.get_fields(request, self.band)), ["name", "bio", "sign_date"]) self.assertIsNone(ma.get_exclude(request, self.band)) def test_default_fieldsets(self): # fieldsets_add and fieldsets_change should return a special data structure that # is used in the templates. They should generate the "right thing" whether we # have specified a custom form, the fields argument, or nothing at all. # # Here's the default case. There are no custom form_add/form_change methods, # no fields argument, and no fieldsets argument. ma = ModelAdmin(Band, self.site) self.assertEqual( ma.get_fieldsets(request), [(None, { "fields": ["name", "bio", "sign_date"] })], ) self.assertEqual( ma.get_fieldsets(request, self.band), [(None, { "fields": ["name", "bio", "sign_date"] })], ) def test_get_fieldsets(self): # get_fieldsets() is called when figuring out form fields (#18681). class BandAdmin(ModelAdmin): def get_fieldsets(self, request, obj=None): return [(None, {"fields": ["name", "bio"]})] ma = BandAdmin(Band, self.site) form = ma.get_form(None) self.assertEqual(form._meta.fields, ["name", "bio"]) class InlineBandAdmin(TabularInline): model = Concert fk_name = "main_band" can_delete = False def get_fieldsets(self, request, obj=None): return [(None, {"fields": ["day", "transport"]})] ma = InlineBandAdmin(Band, self.site) form = ma.get_formset(None).form self.assertEqual(form._meta.fields, ["day", "transport"]) def test_lookup_allowed_allows_nonexistent_lookup(self): """ A lookup_allowed allows a parameter whose field lookup doesn't exist. (#21129). """ class BandAdmin(ModelAdmin): fields = ["name"] ma = BandAdmin(Band, self.site) self.assertTrue(ma.lookup_allowed("name__nonexistent", "test_value")) @isolate_apps("modeladmin") def test_lookup_allowed_onetoone(self): class Department(models.Model): code = models.CharField(max_length=4, unique=True) class Employee(models.Model): department = models.ForeignKey(Department, models.CASCADE, to_field="code") class EmployeeProfile(models.Model): employee = models.OneToOneField(Employee, models.CASCADE) class EmployeeInfo(models.Model): employee = models.OneToOneField(Employee, models.CASCADE) description = models.CharField(max_length=100) class EmployeeProfileAdmin(ModelAdmin): list_filter = [ "employee__employeeinfo__description", "employee__department__code", ] ma = EmployeeProfileAdmin(EmployeeProfile, self.site) # Reverse OneToOneField self.assertIs( ma.lookup_allowed("employee__employeeinfo__description", "test_value"), True) # OneToOneField and ForeignKey self.assertIs( ma.lookup_allowed("employee__department__code", "test_value"), True) def test_field_arguments(self): # If fields is specified, fieldsets_add and fieldsets_change should # just stick the fields into a formsets structure and return it. class BandAdmin(ModelAdmin): fields = ["name"] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_fields(request)), ["name"]) self.assertEqual(list(ma.get_fields(request, self.band)), ["name"]) self.assertEqual(ma.get_fieldsets(request), [(None, { "fields": ["name"] })]) self.assertEqual(ma.get_fieldsets(request, self.band), [(None, { "fields": ["name"] })]) def test_field_arguments_restricted_on_form(self): # If fields or fieldsets is specified, it should exclude fields on the # Form class to the fields specified. This may cause errors to be # raised in the db layer if required model fields aren't in fields/ # fieldsets, but that's preferable to ghost errors where a field in the # Form class isn't being displayed because it's not in fields/fieldsets. # Using `fields`. class BandAdmin(ModelAdmin): fields = ["name"] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name"]) self.assertEqual(list(ma.get_form(request, self.band).base_fields), ["name"]) # Using `fieldsets`. class BandAdmin(ModelAdmin): fieldsets = [(None, {"fields": ["name"]})] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name"]) self.assertEqual(list(ma.get_form(request, self.band).base_fields), ["name"]) # Using `exclude`. class BandAdmin(ModelAdmin): exclude = ["bio"] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name", "sign_date"]) # You can also pass a tuple to `exclude`. class BandAdmin(ModelAdmin): exclude = ("bio", ) ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name", "sign_date"]) # Using `fields` and `exclude`. class BandAdmin(ModelAdmin): fields = ["name", "bio"] exclude = ["bio"] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name"]) def test_custom_form_meta_exclude_with_readonly(self): """ The custom ModelForm's `Meta.exclude` is respected when used in conjunction with `ModelAdmin.readonly_fields` and when no `ModelAdmin.exclude` is defined (#14496). """ # With ModelAdmin class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ["bio"] class BandAdmin(ModelAdmin): readonly_fields = ["name"] form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["sign_date"]) # With InlineModelAdmin class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ["day"] class ConcertInline(TabularInline): readonly_fields = ["transport"] form = AdminConcertForm fk_name = "main_band" model = Concert class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ["main_band", "opening_band", "id", "DELETE"], ) def test_custom_formfield_override_readonly(self): class AdminBandForm(forms.ModelForm): name = forms.CharField() class Meta: exclude = () model = Band class BandAdmin(ModelAdmin): form = AdminBandForm readonly_fields = ["name"] ma = BandAdmin(Band, self.site) # `name` shouldn't appear in base_fields because it's part of # readonly_fields. self.assertEqual(list(ma.get_form(request).base_fields), ["bio", "sign_date"]) # But it should appear in get_fields()/fieldsets() so it can be # displayed as read-only. self.assertEqual(list(ma.get_fields(request)), ["bio", "sign_date", "name"]) self.assertEqual( list(ma.get_fieldsets(request)), [(None, { "fields": ["bio", "sign_date", "name"] })], ) def test_custom_form_meta_exclude(self): """ The custom ModelForm's `Meta.exclude` is overridden if `ModelAdmin.exclude` or `InlineModelAdmin.exclude` are defined (#14496). """ # With ModelAdmin class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ["bio"] class BandAdmin(ModelAdmin): exclude = ["name"] form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["bio", "sign_date"]) # With InlineModelAdmin class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ["day"] class ConcertInline(TabularInline): exclude = ["transport"] form = AdminConcertForm fk_name = "main_band" model = Concert class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ["main_band", "opening_band", "day", "id", "DELETE"], ) def test_overriding_get_exclude(self): class BandAdmin(ModelAdmin): def get_exclude(self, request, obj=None): return ["name"] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request).base_fields), ["bio", "sign_date"], ) def test_get_exclude_overrides_exclude(self): class BandAdmin(ModelAdmin): exclude = ["bio"] def get_exclude(self, request, obj=None): return ["name"] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request).base_fields), ["bio", "sign_date"], ) def test_get_exclude_takes_obj(self): class BandAdmin(ModelAdmin): def get_exclude(self, request, obj=None): if obj: return ["sign_date"] return ["name"] self.assertEqual( list( BandAdmin(Band, self.site).get_form(request, self.band).base_fields), ["name", "bio"], ) def test_custom_form_validation(self): # If a form is specified, it should use it allowing custom validation # to work properly. This won't break any of the admin widgets or media. class AdminBandForm(forms.ModelForm): delete = forms.BooleanField() class BandAdmin(ModelAdmin): form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual( list(ma.get_form(request).base_fields), ["name", "bio", "sign_date", "delete"], ) self.assertEqual( type(ma.get_form(request).base_fields["sign_date"].widget), AdminDateWidget) def test_form_exclude_kwarg_override(self): """ The `exclude` kwarg passed to `ModelAdmin.get_form()` overrides all other declarations (#8999). """ class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ["name"] class BandAdmin(ModelAdmin): exclude = ["sign_date"] form = AdminBandForm def get_form(self, request, obj=None, **kwargs): kwargs["exclude"] = ["bio"] return super().get_form(request, obj, **kwargs) ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["name", "sign_date"]) def test_formset_exclude_kwarg_override(self): """ The `exclude` kwarg passed to `InlineModelAdmin.get_formset()` overrides all other declarations (#8999). """ class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ["day"] class ConcertInline(TabularInline): exclude = ["transport"] form = AdminConcertForm fk_name = "main_band" model = Concert def get_formset(self, request, obj=None, **kwargs): kwargs["exclude"] = ["opening_band"] return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ["main_band", "day", "transport", "id", "DELETE"], ) def test_formset_overriding_get_exclude_with_form_fields(self): class AdminConcertForm(forms.ModelForm): class Meta: model = Concert fields = ["main_band", "opening_band", "day", "transport"] class ConcertInline(TabularInline): form = AdminConcertForm fk_name = "main_band" model = Concert def get_exclude(self, request, obj=None): return ["opening_band"] class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ["main_band", "day", "transport", "id", "DELETE"], ) def test_formset_overriding_get_exclude_with_form_exclude(self): class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ["day"] class ConcertInline(TabularInline): form = AdminConcertForm fk_name = "main_band" model = Concert def get_exclude(self, request, obj=None): return ["opening_band"] class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ["main_band", "day", "transport", "id", "DELETE"], ) def test_raw_id_fields_widget_override(self): """ The autocomplete_fields, raw_id_fields, and radio_fields widgets may overridden by specifying a widget in get_formset(). """ class ConcertInline(TabularInline): model = Concert fk_name = "main_band" raw_id_fields = ("opening_band", ) def get_formset(self, request, obj=None, **kwargs): kwargs["widgets"] = {"opening_band": Select} return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) band_widget = (list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields["opening_band"].widget) # Without the override this would be ForeignKeyRawIdWidget. self.assertIsInstance(band_widget, Select) def test_queryset_override(self): # If the queryset of a ModelChoiceField in a custom form is overridden, # RelatedFieldWidgetWrapper doesn't mess that up. band2 = Band.objects.create(name="The Beatles", bio="", sign_date=date(1962, 1, 1)) ma = ModelAdmin(Concert, self.site) form = ma.get_form(request)() self.assertHTMLEqual( str(form["main_band"]), '<div class="related-widget-wrapper" data-model-ref="band">' '<select name="main_band" id="id_main_band" required>' '<option value="" selected>---------</option>' '<option value="%d">The Beatles</option>' '<option value="%d">The Doors</option>' "</select></div>" % (band2.id, self.band.id), ) class AdminConcertForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["main_band"].queryset = Band.objects.filter( name="The Doors") class ConcertAdminWithForm(ModelAdmin): form = AdminConcertForm ma = ConcertAdminWithForm(Concert, self.site) form = ma.get_form(request)() self.assertHTMLEqual( str(form["main_band"]), '<div class="related-widget-wrapper" data-model-ref="band">' '<select name="main_band" id="id_main_band" required>' '<option value="" selected>---------</option>' '<option value="%d">The Doors</option>' "</select></div>" % self.band.id, ) def test_regression_for_ticket_15820(self): """ `obj` is passed from `InlineModelAdmin.get_fieldsets()` to `InlineModelAdmin.get_formset()`. """ class CustomConcertForm(forms.ModelForm): class Meta: model = Concert fields = ["day"] class ConcertInline(TabularInline): model = Concert fk_name = "main_band" def get_formset(self, request, obj=None, **kwargs): if obj: kwargs["form"] = CustomConcertForm return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] Concert.objects.create(main_band=self.band, opening_band=self.band, day=1) ma = BandAdmin(Band, self.site) inline_instances = ma.get_inline_instances(request) fieldsets = list(inline_instances[0].get_fieldsets(request)) self.assertEqual(fieldsets[0][1]["fields"], ["main_band", "opening_band", "day", "transport"]) fieldsets = list(inline_instances[0].get_fieldsets( request, inline_instances[0].model)) self.assertEqual(fieldsets[0][1]["fields"], ["day"]) # radio_fields behavior ########################################### def test_default_foreign_key_widget(self): # First, without any radio_fields specified, the widgets for ForeignKey # and fields with choices specified ought to be a basic Select widget. # ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so # they need to be handled properly when type checking. For Select fields, all of # the choices lists have a first entry of dashes. cma = ModelAdmin(Concert, self.site) cmafa = cma.get_form(request) self.assertEqual(type(cmafa.base_fields["main_band"].widget.widget), Select) self.assertEqual( list(cmafa.base_fields["main_band"].widget.choices), [("", "---------"), (self.band.id, "The Doors")], ) self.assertEqual(type(cmafa.base_fields["opening_band"].widget.widget), Select) self.assertEqual( list(cmafa.base_fields["opening_band"].widget.choices), [("", "---------"), (self.band.id, "The Doors")], ) self.assertEqual(type(cmafa.base_fields["day"].widget), Select) self.assertEqual( list(cmafa.base_fields["day"].widget.choices), [("", "---------"), (1, "Fri"), (2, "Sat")], ) self.assertEqual(type(cmafa.base_fields["transport"].widget), Select) self.assertEqual( list(cmafa.base_fields["transport"].widget.choices), [("", "---------"), (1, "Plane"), (2, "Train"), (3, "Bus")], ) def test_foreign_key_as_radio_field(self): # Now specify all the fields as radio_fields. Widgets should now be # RadioSelect, and the choices list should have a first entry of 'None' if # blank=True for the model field. Finally, the widget should have the # 'radiolist' attr, and 'inline' as well if the field is specified HORIZONTAL. class ConcertAdmin(ModelAdmin): radio_fields = { "main_band": HORIZONTAL, "opening_band": VERTICAL, "day": VERTICAL, "transport": HORIZONTAL, } cma = ConcertAdmin(Concert, self.site) cmafa = cma.get_form(request) self.assertEqual(type(cmafa.base_fields["main_band"].widget.widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields["main_band"].widget.attrs, {"class": "radiolist inline"}) self.assertEqual( list(cmafa.base_fields["main_band"].widget.choices), [(self.band.id, "The Doors")], ) self.assertEqual(type(cmafa.base_fields["opening_band"].widget.widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields["opening_band"].widget.attrs, {"class": "radiolist"}) self.assertEqual( list(cmafa.base_fields["opening_band"].widget.choices), [("", "None"), (self.band.id, "The Doors")], ) self.assertEqual(type(cmafa.base_fields["day"].widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields["day"].widget.attrs, {"class": "radiolist"}) self.assertEqual(list(cmafa.base_fields["day"].widget.choices), [(1, "Fri"), (2, "Sat")]) self.assertEqual(type(cmafa.base_fields["transport"].widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields["transport"].widget.attrs, {"class": "radiolist inline"}) self.assertEqual( list(cmafa.base_fields["transport"].widget.choices), [("", "None"), (1, "Plane"), (2, "Train"), (3, "Bus")], ) class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ("transport", ) class ConcertAdmin(ModelAdmin): form = AdminConcertForm ma = ConcertAdmin(Concert, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["main_band", "opening_band", "day"]) class AdminConcertForm(forms.ModelForm): extra = forms.CharField() class Meta: model = Concert fields = ["extra", "transport"] class ConcertAdmin(ModelAdmin): form = AdminConcertForm ma = ConcertAdmin(Concert, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ["extra", "transport"]) class ConcertInline(TabularInline): form = AdminConcertForm model = Concert fk_name = "main_band" can_delete = True class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list( list(ma.get_formsets_with_inlines(request))[0][0] ().forms[0].fields), ["extra", "transport", "id", "DELETE", "main_band"], ) def test_log_actions(self): ma = ModelAdmin(Band, self.site) mock_request = MockRequest() mock_request.user = User.objects.create(username="******") content_type = get_content_type_for_model(self.band) tests = ( (ma.log_addition, ADDITION, { "added": {} }), (ma.log_change, CHANGE, { "changed": { "fields": ["name", "bio"] } }), (ma.log_deletion, DELETION, str(self.band)), ) for method, flag, message in tests: with self.subTest(name=method.__name__): created = method(mock_request, self.band, message) fetched = LogEntry.objects.filter( action_flag=flag).latest("id") self.assertEqual(created, fetched) self.assertEqual(fetched.action_flag, flag) self.assertEqual(fetched.content_type, content_type) self.assertEqual(fetched.object_id, str(self.band.pk)) self.assertEqual(fetched.user, mock_request.user) if flag == DELETION: self.assertEqual(fetched.change_message, "") self.assertEqual(fetched.object_repr, message) else: self.assertEqual(fetched.change_message, str(message)) self.assertEqual(fetched.object_repr, str(self.band)) def test_get_autocomplete_fields(self): class NameAdmin(ModelAdmin): search_fields = ["name"] class SongAdmin(ModelAdmin): autocomplete_fields = ["featuring"] fields = ["featuring", "band"] class OtherSongAdmin(SongAdmin): def get_autocomplete_fields(self, request): return ["band"] self.site.register(Band, NameAdmin) try: # Uses autocomplete_fields if not overridden. model_admin = SongAdmin(Song, self.site) form = model_admin.get_form(request)() self.assertIsInstance(form.fields["featuring"].widget.widget, AutocompleteSelectMultiple) # Uses overridden get_autocomplete_fields model_admin = OtherSongAdmin(Song, self.site) form = model_admin.get_form(request)() self.assertIsInstance(form.fields["band"].widget.widget, AutocompleteSelect) finally: self.site.unregister(Band) def test_get_deleted_objects(self): mock_request = MockRequest() mock_request.user = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") self.site.register(Band, ModelAdmin) ma = self.site._registry[Band] ( deletable_objects, model_count, perms_needed, protected, ) = ma.get_deleted_objects([self.band], request) self.assertEqual(deletable_objects, ["Band: The Doors"]) self.assertEqual(model_count, {"bands": 1}) self.assertEqual(perms_needed, set()) self.assertEqual(protected, []) def test_get_deleted_objects_with_custom_has_delete_permission(self): """ ModelAdmin.get_deleted_objects() uses ModelAdmin.has_delete_permission() for permissions checking. """ mock_request = MockRequest() mock_request.user = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") class TestModelAdmin(ModelAdmin): def has_delete_permission(self, request, obj=None): return False self.site.register(Band, TestModelAdmin) ma = self.site._registry[Band] ( deletable_objects, model_count, perms_needed, protected, ) = ma.get_deleted_objects([self.band], request) self.assertEqual(deletable_objects, ["Band: The Doors"]) self.assertEqual(model_count, {"bands": 1}) self.assertEqual(perms_needed, {"band"}) self.assertEqual(protected, []) def test_modeladmin_repr(self): ma = ModelAdmin(Band, self.site) self.assertEqual( repr(ma), "<ModelAdmin: model=Band site=AdminSite(name='admin')>", )
class TestPublishableAdmin(TransactionTestCase, RequestFactoryMixin): def setUp(self): super(TestPublishableAdmin, self).setUp() self.page1 = Page.objects.create(slug='page1', title='page 1') self.page2 = Page.objects.create(slug='page2', title='page 2') self.page1.publish() self.page2.publish() self.author1 = Author.objects.create(name='a1') self.author2 = Author.objects.create(name='a2') self.author1.publish() self.author2.publish() self.admin_site = AdminSite('Test Admin') class PageBlockInline(PublishableStackedInline): model = PageBlock class PageAdmin(PublishableAdmin): inlines = [PageBlockInline] self.admin_site.register(Page, PageAdmin) self.page_admin = PageAdmin(Page, self.admin_site) # override urls, so reverse works settings.ROOT_URLCONF = [ url('^admin/', include(self.admin_site.urls)), ] def test_get_publish_status_display(self): page = Page.objects.create(slug="hhkkk", title="hjkhjkh") self.failUnlessEqual( 'Changed - not yet published', self.page_admin.get_publish_status_display(page)) page.publish() self.failUnlessEqual( 'Published', self.page_admin.get_publish_status_display(page)) page.save() self.failUnlessEqual( 'Changed', self.page_admin.get_publish_status_display(page)) page.delete() self.failUnlessEqual( 'To be deleted', self.page_admin.get_publish_status_display(page)) def test_queryset(self): # make sure we only get back draft objects request = None self.failUnlessEqual( set([ self.page1, self.page1.public, self.page2, self.page2.public ]), set(Page.objects.all())) self.failUnlessEqual(set([self.page1, self.page2]), set(self.page_admin.queryset(request))) def test_get_actions_global_delete_replaced(self): from publish.actions import delete_selected class request(object): GET = {} actions = self.page_admin.get_actions(request) self.failUnless('delete_selected' in actions) action, name, description = actions['delete_selected'] self.failUnlessEqual(delete_selected, action) self.failUnlessEqual('delete_selected', name) self.failUnlessEqual(delete_selected.short_description, description) def test_formfield_for_foreignkey(self): # foreign key forms fields in admin # for publishable models should be filtered # to hide public object request = None parent_field = None for field in Page._meta.fields: if field.name == 'parent': parent_field = field break self.failUnless(parent_field) choice_field = self.page_admin.formfield_for_foreignkey( parent_field, request) self.failUnless(choice_field) self.failUnless(isinstance(choice_field, ModelChoiceField)) self.failUnlessEqual( set([ self.page1, self.page1.public, self.page2, self.page2.public ]), set(Page.objects.all())) self.failUnlessEqual(set([self.page1, self.page2]), set(choice_field.queryset)) def test_formfield_for_manytomany(self): request = None authors_field = None for field in Page._meta.many_to_many: if field.name == 'authors': authors_field = field break self.failUnless(authors_field) choice_field = self.page_admin.formfield_for_manytomany( authors_field, request) self.failUnless(choice_field) self.failUnless(isinstance(choice_field, ModelMultipleChoiceField)) self.failUnlessEqual( set([ self.author1, self.author1.public, self.author2, self.author2.public ]), set(Author.objects.all())) self.failUnlessEqual(set([self.author1, self.author2]), set(choice_field.queryset)) def test_has_change_permission(self): class dummy_request(object): method = 'GET' REQUEST = {} class user(object): @classmethod def has_perm(cls, permission): return True self.failUnless( self.page_admin.has_change_permission(dummy_request)) self.failUnless( self.page_admin.has_change_permission(dummy_request, self.page1)) self.failIf( self.page_admin.has_change_permission(dummy_request, self.page1.public)) # can view deleted items self.page1.publish_state = Publishable.PUBLISH_DELETE self.failUnless( self.page_admin.has_change_permission(dummy_request, self.page1)) # but cannot modify them dummy_request.method = 'POST' self.failIf( self.page_admin.has_change_permission(dummy_request, self.page1)) def test_has_delete_permission(self): class dummy_request(object): method = 'GET' REQUEST = {} class user(object): @classmethod def has_perm(cls, permission): return True self.failUnless( self.page_admin.has_delete_permission(dummy_request)) self.failUnless( self.page_admin.has_delete_permission(dummy_request, self.page1)) self.failIf( self.page_admin.has_delete_permission(dummy_request, self.page1.public)) @skip('Failing due to NoReverseMatch error') def test_change_view_normal(self): dummy_request = self.build_get_request() response = self.page_admin.change_view(dummy_request, str(self.page1.id)) self.failUnless(response is not None) # self.failIf('deleted' in _get_rendered_content(response)) @skip('weird error') def test_change_view_not_deleted(self): dummy_request = self.build_get_request( **{'wsgi.url_scheme': 'http'}) response = self.page_admin.change_view( dummy_request, unicode(self.page1.public.id)) # should be redirecting to the draft version self.failUnless(response is not None) self.assertEquals(302, response.status_code) self.assertEquals('/admin/publish/page/%d/' % self.page1.id, response['Location']) @skip('Failing due to NoReverseMatch error') def test_change_view_deleted(self): dummy_request = self.build_get_request() self.page1.delete() response = self.page_admin.change_view(dummy_request, str(self.page1.id)) self.failUnless(response is not None) # self.failUnless('deleted' in _get_rendered_content(response)) def test_change_view_deleted_POST(self): dummy_request = self.build_post_request({}) self.page1.delete() try: self.page_admin.change_view(dummy_request, str(self.page1.id)) self.fail() except PermissionDenied: pass @skip('Failing due to NoReverseMatch error') def test_change_view_delete_inline(self): block = PageBlock.objects.create(page=self.page1, content='some content') page1 = Page.objects.get(pk=self.page1.pk) page1.publish() # fake selecting the delete tickbox for the block dummy_request = self.build_post_request({ 'slug': page1.slug, 'title': page1.title, 'content': page1.content, 'pub_date_0': '2010-02-12', 'pub_date_1': '17:40:00', 'pageblock_set-TOTAL_FORMS': '2', 'pageblock_set-INITIAL_FORMS': '1', 'pageblock_set-0-id': str(block.id), 'pageblock_set-0-page': str(page1.id), 'pageblock_set-0-DELETE': 'yes' }) block = PageBlock.objects.get(id=block.id) public_block = block.public response = self.page_admin.change_view(dummy_request, str(page1.id)) self.assertEqual(302, response.status_code) # the block should have been deleted (but not the public one) self.failUnlessEqual([public_block], list(PageBlock.objects.all()))
#this is the subpage 'Manage Resources' only displayable to the admin class ResourceManager(AdminSite): pass #or methods resource_manager = AdminSite(name="ResourceManager") class ResourceAdmin(admin.ModelAdmin): list_display = ["name", "type", "description"] search_fields = ["name", "type", "description"] resource_manager.register(Resource, ResourceAdmin) #this is the subpage 'Manage Users' also only displayable to the admin class UserManager(AdminSite): pass #or methods user_manager = AdminSite(name="UserManager") class UserAdmin(admin.ModelAdmin): list_display = [ "last_name", "first_name", "email", "is_active", "is_staff", "last_login", "date_joined"
from concertapp.models import * from django.contrib import admin from django.contrib.admin.sites import AdminSite from django.contrib.auth.models import User admin_site = AdminSite() # Manage users admin_site.register(User) admin_site.register(Collection) admin_site.register(Request) admin_site.register(AudioFile) admin_site.register(AudioSegment) admin_site.register(Tag)
from django.contrib.admin.sites import AdminSite from simple_history.admin import SimpleHistoryAdmin from .models import State site = AdminSite(name="other_admin") site.register(State, SimpleHistoryAdmin)
class PolymorphicParentModelAdmin(admin.ModelAdmin): """ A admin interface that can displays different change/delete pages, depending on the polymorphic model. To use this class, two variables need to be defined: * :attr:`base_model` should * :attr:`child_models` should be a list of (Model, Admin) tuples Alternatively, the following methods can be implemented: * :func:`get_child_models` should return a list of (Model, ModelAdmin) tuples * optionally, :func:`get_child_type_choices` can be overwritten to refine the choices for the add dialog. This class needs to be inherited by the model admin base class that is registered in the site. The derived models should *not* register the ModelAdmin, but instead it should be returned by :func:`get_child_models`. """ #: The base model that the class uses base_model = None #: The child models that should be displayed child_models = None #: Whether the list should be polymorphic too, leave to ``False`` to optimize polymorphic_list = False add_type_template = None add_type_form = PolymorphicModelChoiceForm def __init__(self, model, admin_site, *args, **kwargs): super(PolymorphicParentModelAdmin, self).__init__(model, admin_site, *args, **kwargs) self._child_admin_site = AdminSite(name=self.admin_site.name) self._is_setup = False def _lazy_setup(self): if self._is_setup: return # By not having this in __init__() there is less stress on import dependencies as well, # considering an advanced use cases where a plugin system scans for the child models. child_models = self.get_child_models() for Model, Admin in child_models: self.register_child(Model, Admin) self._child_models = dict(child_models) # This is needed to deal with the improved ForeignKeyRawIdWidget in Django 1.4 and perhaps other widgets too. # The ForeignKeyRawIdWidget checks whether the referenced model is registered in the admin, otherwise it displays itself as a textfield. # As simple solution, just make sure all parent admin models are also know in the child admin site. # This should be done after all parent models are registered off course. complete_registry = self.admin_site._registry.copy() complete_registry.update(self._child_admin_site._registry) self._child_admin_site._registry = complete_registry self._is_setup = True def register_child(self, model, model_admin): """ Register a model with admin to display. """ # After the get_urls() is called, the URLs of the child model can't be exposed anymore to the Django URLconf, # which also means that a "Save and continue editing" button won't work. if self._is_setup: raise RegistrationClosed("The admin model can't be registered anymore at this point.") if not issubclass(model, self.base_model): raise TypeError("{0} should be a subclass of {1}".format(model.__name__, self.base_model.__name__)) if not issubclass(model_admin, admin.ModelAdmin): raise TypeError("{0} should be a subclass of {1}".format(model_admin.__name__, admin.ModelAdmin.__name__)) self._child_admin_site.register(model, model_admin) def get_child_models(self): """ Return the derived model classes which this admin should handle. This should return a list of tuples, exactly like :attr:`child_models` is. The model classes can be retrieved as ``base_model.__subclasses__()``, a setting in a config file, or a query of a plugin registration system at your option """ if self.child_models is None: raise NotImplementedError("Implement get_child_models() or child_models") return self.child_models def get_child_type_choices(self): """ Return a list of polymorphic types which can be added. """ choices = [] for model, _ in self.get_child_models(): ct = ContentType.objects.get_for_model(model, for_concrete_model=False) choices.append((ct.id, model._meta.verbose_name)) return choices def _get_real_admin(self, object_id): obj = self.model.objects.non_polymorphic().values('polymorphic_ctype').get(pk=object_id) return self._get_real_admin_by_ct(obj['polymorphic_ctype']) def _get_real_admin_by_ct(self, ct_id): try: ct = ContentType.objects.get_for_id(ct_id) except ContentType.DoesNotExist as e: raise Http404(e) # Handle invalid GET parameters model_class = ct.model_class() if not model_class: raise Http404("No model found for '{0}.{1}'.".format(*ct.natural_key())) # Handle model deletion return self._get_real_admin_by_model(model_class) def _get_real_admin_by_model(self, model_class): # In case of a ?ct_id=### parameter, the view is already checked for permissions. # Hence, make sure this is a derived object, or risk exposing other admin interfaces. if model_class not in self._child_models: raise PermissionDenied("Invalid model '{0}', it must be registered as child model.".format(model_class)) try: # HACK: the only way to get the instance of an model admin, # is to read the registry of the AdminSite. return self._child_admin_site._registry[model_class] except KeyError: raise ChildAdminNotRegistered("No child admin site was registered for a '{0}' model.".format(model_class)) def queryset(self, request): # optimize the list display. qs = super(PolymorphicParentModelAdmin, self).queryset(request) if not self.polymorphic_list: qs = qs.non_polymorphic() return qs def add_view(self, request, form_url='', extra_context=None): """Redirect the add view to the real admin.""" ct_id = int(request.GET.get('ct_id', 0)) if not ct_id: # Display choices return self.add_type_view(request) else: real_admin = self._get_real_admin_by_ct(ct_id) return real_admin.add_view(request, form_url, extra_context) def change_view(self, request, object_id, *args, **kwargs): """Redirect the change view to the real admin.""" # between Django 1.3 and 1.4 this method signature differs. Hence the *args, **kwargs real_admin = self._get_real_admin(object_id) return real_admin.change_view(request, object_id, *args, **kwargs) def delete_view(self, request, object_id, extra_context=None): """Redirect the delete view to the real admin.""" real_admin = self._get_real_admin(object_id) return real_admin.delete_view(request, object_id, extra_context) def get_urls(self): """ Expose the custom URLs for the subclasses and the URL resolver. """ urls = super(PolymorphicParentModelAdmin, self).get_urls() info = self.model._meta.app_label, self.model._meta.module_name # Patch the change URL so it's not a big catch-all; allowing all custom URLs to be added to the end. # The url needs to be recreated, patching url.regex is not an option Django 1.4's LocaleRegexProvider changed it. new_change_url = url(r'^(\d+)/$', self.admin_site.admin_view(self.change_view), name='{0}_{1}_change'.format(*info)) for i, oldurl in enumerate(urls): if oldurl.name == new_change_url.name: urls[i] = new_change_url # Define the catch-all for custom views custom_urls = patterns('', url(r'^(?P<path>.+)$', self.admin_site.admin_view(self.subclass_view)) ) # At this point. all admin code needs to be known. self._lazy_setup() # Add reverse names for all polymorphic models, so the delete button and "save and add" just work. # These definitions are masked by the definition above, since it needs special handling (and a ct_id parameter). dummy_urls = [] for model, _ in self.get_child_models(): admin = self._get_real_admin_by_model(model) dummy_urls += admin.get_urls() return urls + custom_urls + dummy_urls def subclass_view(self, request, path): """ Forward any request to a custom view of the real admin. """ ct_id = int(request.GET.get('ct_id', 0)) if not ct_id: # See if the path started with an ID. try: pos = path.find('/') object_id = long(path[0:pos]) except ValueError: raise Http404("No ct_id parameter, unable to find admin subclass for path '{0}'.".format(path)) ct_id = self.model.objects.values_list('polymorphic_ctype_id', flat=True).get(pk=object_id) real_admin = self._get_real_admin_by_ct(ct_id) resolver = RegexURLResolver('^', real_admin.urls) resolvermatch = resolver.resolve(path) # May raise Resolver404 if not resolvermatch: raise Http404("No match for path '{0}' in admin subclass.".format(path)) return resolvermatch.func(request, *resolvermatch.args, **resolvermatch.kwargs) def add_type_view(self, request, form_url=''): """ Display a choice form to select which page type to add. """ if not self.has_add_permission(request): raise PermissionDenied extra_qs = '' if request.META['QUERY_STRING']: extra_qs = '&' + request.META['QUERY_STRING'] choices = self.get_child_type_choices() if len(choices) == 1: return HttpResponseRedirect('?ct_id={0}{1}'.format(choices[0][0], extra_qs)) # Create form form = self.add_type_form( data=request.POST if request.method == 'POST' else None, initial={'ct_id': choices[0][0]} ) form.fields['ct_id'].choices = choices if form.is_valid(): return HttpResponseRedirect('?ct_id={0}{1}'.format(form.cleaned_data['ct_id'], extra_qs)) # Wrap in all admin layout fieldsets = ((None, {'fields': ('ct_id',)}),) adminForm = AdminForm(form, fieldsets, {}, model_admin=self) media = self.media + adminForm.media opts = self.model._meta context = { 'title': _('Add %s') % force_text(opts.verbose_name), 'adminform': adminForm, 'is_popup': "_popup" in request.REQUEST, 'media': mark_safe(media), 'errors': AdminErrorList(form, ()), 'app_label': opts.app_label, } return self.render_add_type_form(request, context, form_url) def render_add_type_form(self, request, context, form_url=''): """ Render the page type choice form. """ opts = self.model._meta app_label = opts.app_label context.update({ 'has_change_permission': self.has_change_permission(request), 'form_url': mark_safe(form_url), 'opts': opts, 'add': True, 'save_on_top': self.save_on_top, }) if hasattr(self.admin_site, 'root_path'): context['root_path'] = self.admin_site.root_path # Django < 1.4 context_instance = RequestContext(request, current_app=self.admin_site.name) return render_to_response(self.add_type_template or [ "admin/%s/%s/add_type_form.html" % (app_label, opts.object_name.lower()), "admin/%s/add_type_form.html" % app_label, "admin/polymorphic/add_type_form.html", # added default here "admin/add_type_form.html" ], context, context_instance=context_instance) @property def change_list_template(self): opts = self.model._meta app_label = opts.app_label # Pass the base options base_opts = self.base_model._meta base_app_label = base_opts.app_label return [ "admin/%s/%s/change_list.html" % (app_label, opts.object_name.lower()), "admin/%s/change_list.html" % app_label, # Added base class: "admin/%s/%s/change_list.html" % (base_app_label, base_opts.object_name.lower()), "admin/%s/change_list.html" % base_app_label, "admin/change_list.html" ]
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib.admin.sites import AdminSite from django.contrib.auth.models import User from django.contrib.auth.admin import UserAdmin from signbank.contentpages.admin import FlatPageAdmin from django.contrib.flatpages.models import FlatPage publisher_admin = AdminSite('flatpageadmin') publisher_admin.register(FlatPage, FlatPageAdmin) publisher_admin.register(User, UserAdmin)
class ModelAdminTests(TestCase): def setUp(self): self.band = Band.objects.create( name='The Doors', bio='', sign_date=date(1965, 1, 1), ) self.site = AdminSite() def test_modeladmin_str(self): ma = ModelAdmin(Band, self.site) self.assertEqual(str(ma), 'modeladmin.ModelAdmin') # form/fields/fieldsets interaction ############################## def test_default_fields(self): ma = ModelAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'bio', 'sign_date']) self.assertEqual(list(ma.get_fields(request)), ['name', 'bio', 'sign_date']) self.assertEqual(list(ma.get_fields(request, self.band)), ['name', 'bio', 'sign_date']) self.assertIsNone(ma.get_exclude(request, self.band)) def test_default_fieldsets(self): # fieldsets_add and fieldsets_change should return a special data structure that # is used in the templates. They should generate the "right thing" whether we # have specified a custom form, the fields argument, or nothing at all. # # Here's the default case. There are no custom form_add/form_change methods, # no fields argument, and no fieldsets argument. ma = ModelAdmin(Band, self.site) self.assertEqual(ma.get_fieldsets(request), [(None, {'fields': ['name', 'bio', 'sign_date']})]) self.assertEqual(ma.get_fieldsets(request, self.band), [(None, {'fields': ['name', 'bio', 'sign_date']})]) def test_get_fieldsets(self): # get_fieldsets() is called when figuring out form fields (#18681). class BandAdmin(ModelAdmin): def get_fieldsets(self, request, obj=None): return [(None, {'fields': ['name', 'bio']})] ma = BandAdmin(Band, self.site) form = ma.get_form(None) self.assertEqual(form._meta.fields, ['name', 'bio']) class InlineBandAdmin(TabularInline): model = Concert fk_name = 'main_band' can_delete = False def get_fieldsets(self, request, obj=None): return [(None, {'fields': ['day', 'transport']})] ma = InlineBandAdmin(Band, self.site) form = ma.get_formset(None).form self.assertEqual(form._meta.fields, ['day', 'transport']) def test_lookup_allowed_allows_nonexistent_lookup(self): """ A lookup_allowed allows a parameter whose field lookup doesn't exist. (#21129). """ class BandAdmin(ModelAdmin): fields = ['name'] ma = BandAdmin(Band, self.site) self.assertTrue(ma.lookup_allowed('name__nonexistent', 'test_value')) @isolate_apps('modeladmin') def test_lookup_allowed_onetoone(self): class Department(models.Model): code = models.CharField(max_length=4, unique=True) class Employee(models.Model): department = models.ForeignKey(Department, models.CASCADE, to_field="code") class EmployeeProfile(models.Model): employee = models.OneToOneField(Employee, models.CASCADE) class EmployeeInfo(models.Model): employee = models.OneToOneField(Employee, models.CASCADE) description = models.CharField(max_length=100) class EmployeeProfileAdmin(ModelAdmin): list_filter = [ 'employee__employeeinfo__description', 'employee__department__code', ] ma = EmployeeProfileAdmin(EmployeeProfile, self.site) # Reverse OneToOneField self.assertIs(ma.lookup_allowed('employee__employeeinfo__description', 'test_value'), True) # OneToOneField and ForeignKey self.assertIs(ma.lookup_allowed('employee__department__code', 'test_value'), True) def test_field_arguments(self): # If fields is specified, fieldsets_add and fieldsets_change should # just stick the fields into a formsets structure and return it. class BandAdmin(ModelAdmin): fields = ['name'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_fields(request)), ['name']) self.assertEqual(list(ma.get_fields(request, self.band)), ['name']) self.assertEqual(ma.get_fieldsets(request), [(None, {'fields': ['name']})]) self.assertEqual(ma.get_fieldsets(request, self.band), [(None, {'fields': ['name']})]) def test_field_arguments_restricted_on_form(self): # If fields or fieldsets is specified, it should exclude fields on the # Form class to the fields specified. This may cause errors to be # raised in the db layer if required model fields aren't in fields/ # fieldsets, but that's preferable to ghost errors where a field in the # Form class isn't being displayed because it's not in fields/fieldsets. # Using `fields`. class BandAdmin(ModelAdmin): fields = ['name'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name']) self.assertEqual(list(ma.get_form(request, self.band).base_fields), ['name']) # Using `fieldsets`. class BandAdmin(ModelAdmin): fieldsets = [(None, {'fields': ['name']})] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name']) self.assertEqual(list(ma.get_form(request, self.band).base_fields), ['name']) # Using `exclude`. class BandAdmin(ModelAdmin): exclude = ['bio'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'sign_date']) # You can also pass a tuple to `exclude`. class BandAdmin(ModelAdmin): exclude = ('bio',) ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'sign_date']) # Using `fields` and `exclude`. class BandAdmin(ModelAdmin): fields = ['name', 'bio'] exclude = ['bio'] ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name']) def test_custom_form_meta_exclude_with_readonly(self): """ The custom ModelForm's `Meta.exclude` is respected when used in conjunction with `ModelAdmin.readonly_fields` and when no `ModelAdmin.exclude` is defined (#14496). """ # With ModelAdmin class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ['bio'] class BandAdmin(ModelAdmin): readonly_fields = ['name'] form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['sign_date']) # With InlineModelAdmin class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): readonly_fields = ['transport'] form = AdminConcertForm fk_name = 'main_band' model = Concert class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields), ['main_band', 'opening_band', 'id', 'DELETE']) def test_custom_formfield_override_readonly(self): class AdminBandForm(forms.ModelForm): name = forms.CharField() class Meta: exclude = () model = Band class BandAdmin(ModelAdmin): form = AdminBandForm readonly_fields = ['name'] ma = BandAdmin(Band, self.site) # `name` shouldn't appear in base_fields because it's part of # readonly_fields. self.assertEqual( list(ma.get_form(request).base_fields), ['bio', 'sign_date'] ) # But it should appear in get_fields()/fieldsets() so it can be # displayed as read-only. self.assertEqual( list(ma.get_fields(request)), ['bio', 'sign_date', 'name'] ) self.assertEqual( list(ma.get_fieldsets(request)), [(None, {'fields': ['bio', 'sign_date', 'name']})] ) def test_custom_form_meta_exclude(self): """ The custom ModelForm's `Meta.exclude` is overridden if `ModelAdmin.exclude` or `InlineModelAdmin.exclude` are defined (#14496). """ # With ModelAdmin class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ['bio'] class BandAdmin(ModelAdmin): exclude = ['name'] form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['bio', 'sign_date']) # With InlineModelAdmin class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): exclude = ['transport'] form = AdminConcertForm fk_name = 'main_band' model = Concert class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields), ['main_band', 'opening_band', 'day', 'id', 'DELETE'] ) def test_overriding_get_exclude(self): class BandAdmin(ModelAdmin): def get_exclude(self, request, obj=None): return ['name'] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request).base_fields), ['bio', 'sign_date'] ) def test_get_exclude_overrides_exclude(self): class BandAdmin(ModelAdmin): exclude = ['bio'] def get_exclude(self, request, obj=None): return ['name'] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request).base_fields), ['bio', 'sign_date'] ) def test_get_exclude_takes_obj(self): class BandAdmin(ModelAdmin): def get_exclude(self, request, obj=None): if obj: return ['sign_date'] return ['name'] self.assertEqual( list(BandAdmin(Band, self.site).get_form(request, self.band).base_fields), ['name', 'bio'] ) def test_custom_form_validation(self): # If a form is specified, it should use it allowing custom validation # to work properly. This won't break any of the admin widgets or media. class AdminBandForm(forms.ModelForm): delete = forms.BooleanField() class BandAdmin(ModelAdmin): form = AdminBandForm ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'bio', 'sign_date', 'delete']) self.assertEqual(type(ma.get_form(request).base_fields['sign_date'].widget), AdminDateWidget) def test_form_exclude_kwarg_override(self): """ The `exclude` kwarg passed to `ModelAdmin.get_form()` overrides all other declarations (#8999). """ class AdminBandForm(forms.ModelForm): class Meta: model = Band exclude = ['name'] class BandAdmin(ModelAdmin): exclude = ['sign_date'] form = AdminBandForm def get_form(self, request, obj=None, **kwargs): kwargs['exclude'] = ['bio'] return super().get_form(request, obj, **kwargs) ma = BandAdmin(Band, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['name', 'sign_date']) def test_formset_exclude_kwarg_override(self): """ The `exclude` kwarg passed to `InlineModelAdmin.get_formset()` overrides all other declarations (#8999). """ class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): exclude = ['transport'] form = AdminConcertForm fk_name = 'main_band' model = Concert def get_formset(self, request, obj=None, **kwargs): kwargs['exclude'] = ['opening_band'] return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields), ['main_band', 'day', 'transport', 'id', 'DELETE'] ) def test_formset_overriding_get_exclude_with_form_fields(self): class AdminConcertForm(forms.ModelForm): class Meta: model = Concert fields = ['main_band', 'opening_band', 'day', 'transport'] class ConcertInline(TabularInline): form = AdminConcertForm fk_name = 'main_band' model = Concert def get_exclude(self, request, obj=None): return ['opening_band'] class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields), ['main_band', 'day', 'transport', 'id', 'DELETE'] ) def test_formset_overriding_get_exclude_with_form_exclude(self): class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ['day'] class ConcertInline(TabularInline): form = AdminConcertForm fk_name = 'main_band' model = Concert def get_exclude(self, request, obj=None): return ['opening_band'] class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields), ['main_band', 'day', 'transport', 'id', 'DELETE'] ) def test_queryset_override(self): # If the queryset of a ModelChoiceField in a custom form is overridden, # RelatedFieldWidgetWrapper doesn't mess that up. band2 = Band.objects.create(name='The Beatles', bio='', sign_date=date(1962, 1, 1)) ma = ModelAdmin(Concert, self.site) form = ma.get_form(request)() self.assertHTMLEqual( str(form["main_band"]), '<div class="related-widget-wrapper">' '<select name="main_band" id="id_main_band" required>' '<option value="" selected>---------</option>' '<option value="%d">The Beatles</option>' '<option value="%d">The Doors</option>' '</select></div>' % (band2.id, self.band.id) ) class AdminConcertForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["main_band"].queryset = Band.objects.filter(name='The Doors') class ConcertAdminWithForm(ModelAdmin): form = AdminConcertForm ma = ConcertAdminWithForm(Concert, self.site) form = ma.get_form(request)() self.assertHTMLEqual( str(form["main_band"]), '<div class="related-widget-wrapper">' '<select name="main_band" id="id_main_band" required>' '<option value="" selected>---------</option>' '<option value="%d">The Doors</option>' '</select></div>' % self.band.id ) def test_regression_for_ticket_15820(self): """ `obj` is passed from `InlineModelAdmin.get_fieldsets()` to `InlineModelAdmin.get_formset()`. """ class CustomConcertForm(forms.ModelForm): class Meta: model = Concert fields = ['day'] class ConcertInline(TabularInline): model = Concert fk_name = 'main_band' def get_formset(self, request, obj=None, **kwargs): if obj: kwargs['form'] = CustomConcertForm return super().get_formset(request, obj, **kwargs) class BandAdmin(ModelAdmin): inlines = [ConcertInline] Concert.objects.create(main_band=self.band, opening_band=self.band, day=1) ma = BandAdmin(Band, self.site) inline_instances = ma.get_inline_instances(request) fieldsets = list(inline_instances[0].get_fieldsets(request)) self.assertEqual(fieldsets[0][1]['fields'], ['main_band', 'opening_band', 'day', 'transport']) fieldsets = list(inline_instances[0].get_fieldsets(request, inline_instances[0].model)) self.assertEqual(fieldsets[0][1]['fields'], ['day']) # radio_fields behavior ########################################### def test_default_foreign_key_widget(self): # First, without any radio_fields specified, the widgets for ForeignKey # and fields with choices specified ought to be a basic Select widget. # ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so # they need to be handled properly when type checking. For Select fields, all of # the choices lists have a first entry of dashes. cma = ModelAdmin(Concert, self.site) cmafa = cma.get_form(request) self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget), Select) self.assertEqual( list(cmafa.base_fields['main_band'].widget.choices), [('', '---------'), (self.band.id, 'The Doors')]) self.assertEqual(type(cmafa.base_fields['opening_band'].widget.widget), Select) self.assertEqual( list(cmafa.base_fields['opening_band'].widget.choices), [('', '---------'), (self.band.id, 'The Doors')] ) self.assertEqual(type(cmafa.base_fields['day'].widget), Select) self.assertEqual( list(cmafa.base_fields['day'].widget.choices), [('', '---------'), (1, 'Fri'), (2, 'Sat')] ) self.assertEqual(type(cmafa.base_fields['transport'].widget), Select) self.assertEqual( list(cmafa.base_fields['transport'].widget.choices), [('', '---------'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')]) def test_foreign_key_as_radio_field(self): # Now specify all the fields as radio_fields. Widgets should now be # RadioSelect, and the choices list should have a first entry of 'None' if # blank=True for the model field. Finally, the widget should have the # 'radiolist' attr, and 'inline' as well if the field is specified HORIZONTAL. class ConcertAdmin(ModelAdmin): radio_fields = { 'main_band': HORIZONTAL, 'opening_band': VERTICAL, 'day': VERTICAL, 'transport': HORIZONTAL, } cma = ConcertAdmin(Concert, self.site) cmafa = cma.get_form(request) self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['main_band'].widget.attrs, {'class': 'radiolist inline'}) self.assertEqual( list(cmafa.base_fields['main_band'].widget.choices), [(self.band.id, 'The Doors')] ) self.assertEqual(type(cmafa.base_fields['opening_band'].widget.widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['opening_band'].widget.attrs, {'class': 'radiolist'}) self.assertEqual( list(cmafa.base_fields['opening_band'].widget.choices), [('', 'None'), (self.band.id, 'The Doors')] ) self.assertEqual(type(cmafa.base_fields['day'].widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['day'].widget.attrs, {'class': 'radiolist'}) self.assertEqual(list(cmafa.base_fields['day'].widget.choices), [(1, 'Fri'), (2, 'Sat')]) self.assertEqual(type(cmafa.base_fields['transport'].widget), AdminRadioSelect) self.assertEqual(cmafa.base_fields['transport'].widget.attrs, {'class': 'radiolist inline'}) self.assertEqual( list(cmafa.base_fields['transport'].widget.choices), [('', 'None'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')] ) class AdminConcertForm(forms.ModelForm): class Meta: model = Concert exclude = ('transport',) class ConcertAdmin(ModelAdmin): form = AdminConcertForm ma = ConcertAdmin(Concert, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['main_band', 'opening_band', 'day']) class AdminConcertForm(forms.ModelForm): extra = forms.CharField() class Meta: model = Concert fields = ['extra', 'transport'] class ConcertAdmin(ModelAdmin): form = AdminConcertForm ma = ConcertAdmin(Concert, self.site) self.assertEqual(list(ma.get_form(request).base_fields), ['extra', 'transport']) class ConcertInline(TabularInline): form = AdminConcertForm model = Concert fk_name = 'main_band' can_delete = True class BandAdmin(ModelAdmin): inlines = [ConcertInline] ma = BandAdmin(Band, self.site) self.assertEqual( list(list(ma.get_formsets_with_inlines(request))[0][0]().forms[0].fields), ['extra', 'transport', 'id', 'DELETE', 'main_band'] ) def test_log_actions(self): ma = ModelAdmin(Band, self.site) mock_request = MockRequest() mock_request.user = User.objects.create(username='******') content_type = get_content_type_for_model(self.band) tests = ( (ma.log_addition, ADDITION, {'added': {}}), (ma.log_change, CHANGE, {'changed': {'fields': ['name', 'bio']}}), (ma.log_deletion, DELETION, str(self.band)), ) for method, flag, message in tests: with self.subTest(name=method.__name__): created = method(mock_request, self.band, message) fetched = LogEntry.objects.filter(action_flag=flag).latest('id') self.assertEqual(created, fetched) self.assertEqual(fetched.action_flag, flag) self.assertEqual(fetched.content_type, content_type) self.assertEqual(fetched.object_id, str(self.band.pk)) self.assertEqual(fetched.user, mock_request.user) if flag == DELETION: self.assertEqual(fetched.change_message, '') self.assertEqual(fetched.object_repr, message) else: self.assertEqual(fetched.change_message, str(message)) self.assertEqual(fetched.object_repr, str(self.band)) def test_get_autocomplete_fields(self): class NameAdmin(ModelAdmin): search_fields = ['name'] class SongAdmin(ModelAdmin): autocomplete_fields = ['featuring'] fields = ['featuring', 'band'] class OtherSongAdmin(SongAdmin): def get_autocomplete_fields(self, request): return ['band'] self.site.register(Band, NameAdmin) try: # Uses autocomplete_fields if not overridden. model_admin = SongAdmin(Song, self.site) form = model_admin.get_form(request)() self.assertIsInstance(form.fields['featuring'].widget.widget, AutocompleteSelectMultiple) # Uses overridden get_autocomplete_fields model_admin = OtherSongAdmin(Song, self.site) form = model_admin.get_form(request)() self.assertIsInstance(form.fields['band'].widget.widget, AutocompleteSelect) finally: self.site.unregister(Band) def test_get_deleted_objects(self): mock_request = MockRequest() mock_request.user = User.objects.create_superuser(username='******', email='*****@*****.**', password='******') self.site.register(Band, ModelAdmin) ma = self.site._registry[Band] deletable_objects, model_count, perms_needed, protected = ma.get_deleted_objects([self.band], request) self.assertEqual(deletable_objects, ['Band: The Doors']) self.assertEqual(model_count, {'bands': 1}) self.assertEqual(perms_needed, set()) self.assertEqual(protected, []) def test_get_deleted_objects_with_custom_has_delete_permission(self): """ ModelAdmin.get_deleted_objects() uses ModelAdmin.has_delete_permission() for permissions checking. """ mock_request = MockRequest() mock_request.user = User.objects.create_superuser(username='******', email='*****@*****.**', password='******') class TestModelAdmin(ModelAdmin): def has_delete_permission(self, request, obj=None): return False self.site.register(Band, TestModelAdmin) ma = self.site._registry[Band] deletable_objects, model_count, perms_needed, protected = ma.get_deleted_objects([self.band], request) self.assertEqual(deletable_objects, ['Band: The Doors']) self.assertEqual(model_count, {'bands': 1}) self.assertEqual(perms_needed, {'band'}) self.assertEqual(protected, [])
from django.contrib.admin.sites import AdminSite from django.contrib.admin import site as admin from django.contrib.databrowse import site as databrowse management = AdminSite('management') assemblies = AdminSite('assemblies') basic = AdminSite('basic') structure = AdminSite('structures') types = AdminSite('types') combined = AdminSite('combined') advanced = AdminSite('advanced') from django.contrib.auth.models import Group, User from django.contrib.auth.admin import GroupAdmin, UserAdmin management.register(Group, GroupAdmin) management.register(User, UserAdmin) from django.contrib.sites.models import Site from django.contrib.sites.admin import SiteAdmin management.register(Site, SiteAdmin) def registerer(*sites): def register(model, modeladmin=None, **kwargs): if kwargs.get('advanced'): admins = (admin, types, advanced) else: admins = sites + (admin, combined, advanced) for site in admins: site.register(model, modeladmin) databrowse.register(model)