From 4dad8cdf9a65949fba58ebee1e8ab2a46647875c Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Tue, 1 Aug 2017 14:00:29 +0000 Subject: [PATCH] Added a test to check for missing admin models, and added the admin models that were currently missing. - Legacy-Id: 14021 --- ietf/community/admin.py | 21 ++++++++++++++ ietf/doc/admin.py | 51 ++++++++++++++++++++++++++------- ietf/group/admin.py | 22 ++++++++++++-- ietf/ipr/admin.py | 8 +++++- ietf/liaisons/admin.py | 12 ++++++++ ietf/message/admin.py | 10 +++++-- ietf/name/admin.py | 15 +++++----- ietf/nomcom/admin.py | 63 ++++++++++++++++++++++++++++------------- ietf/person/admin.py | 14 ++++++++- ietf/review/admin.py | 9 ++++-- ietf/settings.py | 1 + ietf/utils/admin.py | 7 +++++ ietf/utils/tests.py | 50 ++++++++++++++++++++++++++++---- 13 files changed, 231 insertions(+), 52 deletions(-) create mode 100644 ietf/community/admin.py diff --git a/ietf/community/admin.py b/ietf/community/admin.py new file mode 100644 index 000000000..34f39930f --- /dev/null +++ b/ietf/community/admin.py @@ -0,0 +1,21 @@ + +from __future__ import unicode_literals +from django.contrib import admin + +from ietf.community.models import CommunityList, SearchRule, EmailSubscription + +class CommunityListAdmin(admin.ModelAdmin): + list_display = [u'id', 'user', 'group'] + raw_id_fields = ['user', 'group'] +admin.site.register(CommunityList, CommunityListAdmin) + +class SearchRuleAdmin(admin.ModelAdmin): + list_display = [u'id', 'community_list', 'rule_type', 'state', 'group', 'person', 'text'] + raw_id_fields = ['community_list', 'state', 'group', 'person'] +admin.site.register(SearchRule, SearchRuleAdmin) + +class EmailSubscriptionAdmin(admin.ModelAdmin): + list_display = [u'id', 'community_list', 'email', 'notify_on'] + raw_id_fields = ['community_list', 'email'] +admin.site.register(EmailSubscription, EmailSubscriptionAdmin) + diff --git a/ietf/doc/admin.py b/ietf/doc/admin.py index 58222b24e..b775998e9 100644 --- a/ietf/doc/admin.py +++ b/ietf/doc/admin.py @@ -3,10 +3,12 @@ from django.utils.safestring import mark_safe from django.contrib import admin from django import forms -from models import (StateType, State, DocAlias, DocumentAuthor, RelatedDocument, - Document, DocHistory, BallotType, DocEvent, NewRevisionDocEvent, StateDocEvent, - ConsensusDocEvent, BallotDocEvent, WriteupDocEvent, LastCallDocEvent, - TelechatDocEvent, BallotPositionDocEvent) +from models import (StateType, State, RelatedDocument, DocumentAuthor, Document, RelatedDocHistory, + DocHistoryAuthor, DocHistory, DocAlias, DocReminder, DocEvent, NewRevisionDocEvent, + StateDocEvent, ConsensusDocEvent, BallotType, BallotDocEvent, WriteupDocEvent, LastCallDocEvent, + TelechatDocEvent, BallotPositionDocEvent, ReviewRequestDocEvent, InitialReviewDocEvent, + AddedMessageEvent, SubmissionDocEvent, DeletedEvent, EditedAuthorsDocEvent, ) + from ietf.doc.utils import get_state_types @@ -96,6 +98,12 @@ class DocumentForm(forms.ModelForm): fields = '__all__' model = Document +class DocumentAuthorAdmin(admin.ModelAdmin): + list_display = ['id', 'document', 'person', 'email', 'affiliation', 'country', 'order'] + search_fields = ['document__docalias__name', 'person__name', 'email__address', 'affiliation', 'country'] + raw_id_fields = ["document", "person", "email"] +admin.site.register(DocumentAuthor, DocumentAuthorAdmin) + class DocumentAdmin(admin.ModelAdmin): list_display = ['name', 'rev', 'group', 'pages', 'intended_std_level', 'author_list', 'time'] search_fields = ['name'] @@ -136,6 +144,12 @@ class DocAliasAdmin(admin.ModelAdmin): raw_id_fields = ['document'] admin.site.register(DocAlias, DocAliasAdmin) +class DocReminderAdmin(admin.ModelAdmin): + list_display = ['id', 'event', 'type', 'due', 'active'] + list_filter = ['type', 'due', 'active'] + raw_id_fields = ['event'] +admin.site.register(DocReminder, DocReminderAdmin) + class RelatedDocumentAdmin(admin.ModelAdmin): list_display = ['source', 'target', 'relationship', ] list_filter = ['relationship', ] @@ -143,6 +157,17 @@ class RelatedDocumentAdmin(admin.ModelAdmin): raw_id_fields = ['source', 'target', ] admin.site.register(RelatedDocument, RelatedDocumentAdmin) +class RelatedDocHistoryAdmin(admin.ModelAdmin): + list_display = ['id', 'source', 'target', 'relationship'] + list_filter = ['relationship'] + raw_id_fields = ['source', 'target'] +admin.site.register(RelatedDocHistory, RelatedDocHistoryAdmin) + +class DocHistoryAuthorAdmin(admin.ModelAdmin): + list_display = ['id', 'person', 'email', 'affiliation', 'country', 'order', 'document'] + raw_id_fields = ['person', 'email', 'document'] +admin.site.register(DocHistoryAuthor, DocHistoryAuthorAdmin) + class BallotTypeAdmin(admin.ModelAdmin): list_display = ["slug", "doc_type", "name", "question"] admin.site.register(BallotType, BallotTypeAdmin) @@ -169,14 +194,20 @@ admin.site.register(BallotDocEvent, DocEventAdmin) admin.site.register(WriteupDocEvent, DocEventAdmin) admin.site.register(LastCallDocEvent, DocEventAdmin) admin.site.register(TelechatDocEvent, DocEventAdmin) +admin.site.register(ReviewRequestDocEvent, DocEventAdmin) +admin.site.register(InitialReviewDocEvent, DocEventAdmin) +admin.site.register(AddedMessageEvent, DocEventAdmin) +admin.site.register(SubmissionDocEvent, DocEventAdmin) +admin.site.register(EditedAuthorsDocEvent, DocEventAdmin) + + +class DeletedEventAdmin(admin.ModelAdmin): + list_display = [u'id', 'content_type', 'json', 'by', 'time'] + list_filter = ['time'] + raw_id_fields = ['content_type', 'by'] +admin.site.register(DeletedEvent, DeletedEventAdmin) class BallotPositionDocEventAdmin(DocEventAdmin): raw_id_fields = ["doc", "by", "ad", "ballot"] admin.site.register(BallotPositionDocEvent, BallotPositionDocEventAdmin) -class DocumentAuthorAdmin(admin.ModelAdmin): - list_display = ['id', 'document', 'person', 'email', 'affiliation', 'country', 'order'] - search_fields = ['document__docalias__name', 'person__name', 'email__address', 'affiliation', 'country'] - raw_id_fields = ["document", "person", "email"] -admin.site.register(DocumentAuthor, DocumentAuthorAdmin) - diff --git a/ietf/group/admin.py b/ietf/group/admin.py index 3d0a18dfa..a0b645442 100644 --- a/ietf/group/admin.py +++ b/ietf/group/admin.py @@ -10,7 +10,9 @@ from django.utils.encoding import force_unicode from django.utils.html import escape from django.utils.translation import ugettext as _ -from ietf.group.models import Group, GroupHistory, GroupEvent, GroupURL, GroupMilestone, Role, RoleHistory, ChangeStateGroupEvent +from ietf.group.models import (Group, GroupHistory, GroupEvent, GroupURL, GroupMilestone, + GroupMilestoneHistory, GroupStateTransitions, Role, RoleHistory, ChangeStateGroupEvent, + MilestoneGroupEvent, ) class RoleInline(admin.TabularInline): model = Role @@ -108,12 +110,23 @@ class GroupHistoryAdmin(admin.ModelAdmin): admin.site.register(GroupHistory, GroupHistoryAdmin) +class GroupURLAdmin(admin.ModelAdmin): + list_display = [u'id', 'group', 'name', 'url'] + raw_id_fields = ['group'] + search_fields = ['name'] +admin.site.register(GroupURL, GroupURLAdmin) + class GroupMilestoneAdmin(admin.ModelAdmin): list_display = ["group", "desc", "due", "resolved", "time"] search_fields = ["group__name", "group__acronym", "desc", "resolved"] raw_id_fields = ["group", "docs"] - admin.site.register(GroupMilestone, GroupMilestoneAdmin) +admin.site.register(GroupMilestoneHistory, GroupMilestoneAdmin) + +class GroupStateTransitionsAdmin(admin.ModelAdmin): + list_display = [u'id', 'group', 'state'] + raw_id_fields = ['group', 'state'] +admin.site.register(GroupStateTransitions, GroupStateTransitionsAdmin) class RoleAdmin(admin.ModelAdmin): list_display = ["name", "person", "email", "group"] @@ -136,3 +149,8 @@ class ChangeStateGroupEventAdmin(admin.ModelAdmin): search_fields = ["group__name", "group__acronym"] admin.site.register(ChangeStateGroupEvent, ChangeStateGroupEventAdmin) +class MilestoneGroupEventAdmin(admin.ModelAdmin): + list_display = [u'id', 'group', 'time', 'type', 'by', 'desc', 'milestone'] + list_filter = ['time'] + raw_id_fields = ['group', 'by', 'milestone'] +admin.site.register(MilestoneGroupEvent, MilestoneGroupEventAdmin) diff --git a/ietf/ipr/admin.py b/ietf/ipr/admin.py index 924687093..2656dce90 100644 --- a/ietf/ipr/admin.py +++ b/ietf/ipr/admin.py @@ -4,7 +4,7 @@ from django.contrib import admin from ietf.name.models import DocRelationshipName from ietf.ipr.models import (IprDisclosureBase, IprDocRel, IprEvent, RelatedIpr, HolderIprDisclosure, ThirdPartyIprDisclosure, GenericIprDisclosure, - NonDocSpecificIprDisclosure) + NonDocSpecificIprDisclosure, LegacyMigrationIprEvent) # ------------------------------------------------------ # ModelAdmins @@ -101,3 +101,9 @@ class IprEventAdmin(admin.ModelAdmin): search_fields = ["disclosure__title", "by__name"] raw_id_fields = ["disclosure", "by", "message", "in_reply_to"] admin.site.register(IprEvent, IprEventAdmin) + +class LegacyMigrationIprEventAdmin(admin.ModelAdmin): + list_display = [u'id', 'time', 'type', 'by', 'disclosure', 'desc', 'message', 'in_reply_to', 'response_due'] + list_filter = ['time', 'type', 'response_due'] + raw_id_fields = ['by', 'disclosure', 'message', 'in_reply_to'] +admin.site.register(LegacyMigrationIprEvent, LegacyMigrationIprEventAdmin) diff --git a/ietf/liaisons/admin.py b/ietf/liaisons/admin.py index bcbd64fee..4fdf7e406 100644 --- a/ietf/liaisons/admin.py +++ b/ietf/liaisons/admin.py @@ -28,6 +28,18 @@ class LiaisonStatementAdmin(admin.ModelAdmin): return '
'.join(['%s' % (reverse('admin:liaisons_liaisonstatement_change', None, (i.target.id, )), str(i.target)) for i in obj.source_of_set.select_related('target').all()]) related_to.allow_tags = True +class LiaisonStatementAttachmentAdmin(admin.ModelAdmin): + list_display = [u'id', 'statement', 'document', 'removed'] + list_filter = ['removed'] + raw_id_fields = ['statement', 'document'] +admin.site.register(LiaisonStatementAttachment, LiaisonStatementAttachmentAdmin) + +class RelatedLiaisonStatementAdmin(admin.ModelAdmin): + list_display = [u'id', 'source', 'target', 'relationship'] + list_filter = ['relationship'] + raw_id_fields = ['source', 'target'] +admin.site.register(RelatedLiaisonStatement, RelatedLiaisonStatementAdmin) + class LiaisonStatementEventAdmin(admin.ModelAdmin): list_display = ["statement", "type", "by", "time"] search_fields = ["statement__title", "by__name"] diff --git a/ietf/message/admin.py b/ietf/message/admin.py index 14f4ba47f..b4e7a6a23 100644 --- a/ietf/message/admin.py +++ b/ietf/message/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from ietf.message.models import Message, SendQueue, AnnouncementFrom +from ietf.message.models import Message, MessageAttachment, SendQueue, AnnouncementFrom class MessageAdmin(admin.ModelAdmin): list_display = ["subject", "by", "time", "groups"] @@ -10,9 +10,13 @@ class MessageAdmin(admin.ModelAdmin): def groups(self, instance): return ", ".join(g.acronym for g in instance.related_groups.all()) - admin.site.register(Message, MessageAdmin) +class MessageAttachmentAdmin(admin.ModelAdmin): + list_display = ['id', 'message', 'filename', 'removed',] + raw_id_fields = ['message'] +admin.site.register(MessageAttachment, MessageAttachmentAdmin) + class SendQueueAdmin(admin.ModelAdmin): list_display = ["time", "by", "message", "send_at", "sent_at"] list_filter = ["time", "send_at", "sent_at"] @@ -24,3 +28,5 @@ admin.site.register(SendQueue, SendQueueAdmin) class AnnouncementFromAdmin(admin.ModelAdmin): list_display = ['name', 'group', 'address', ] admin.site.register(AnnouncementFrom, AnnouncementFromAdmin) + + diff --git a/ietf/name/admin.py b/ietf/name/admin.py index a40547222..8b57e7b3a 100644 --- a/ietf/name/admin.py +++ b/ietf/name/admin.py @@ -1,15 +1,14 @@ from django.contrib import admin from ietf.name.models import ( - BallotPositionName, ConstraintName, ContinentName, CountryName, - DBTemplateTypeName, DocRelationshipName, - DocReminderTypeName, DocTagName, DocTypeName, DraftSubmissionStateName, + BallotPositionName, ConstraintName, ContinentName, CountryName, DBTemplateTypeName, + DocRelationshipName, DocReminderTypeName, DocTagName, DocTypeName, DraftSubmissionStateName, FeedbackTypeName, FormalLanguageName, GroupMilestoneStateName, GroupStateName, GroupTypeName, - ImportantDateName, IntendedStdLevelName, IprDisclosureStateName, IprEventTypeName, IprLicenseTypeName, - LiaisonStatementEventTypeName, LiaisonStatementPurposeName, LiaisonStatementState, - LiaisonStatementTagName, MeetingTypeName, NomineePositionStateName, + ImportantDateName, IntendedStdLevelName, IprDisclosureStateName, IprEventTypeName, + IprLicenseTypeName, LiaisonStatementEventTypeName, LiaisonStatementPurposeName, + LiaisonStatementState, LiaisonStatementTagName, MeetingTypeName, NomineePositionStateName, ReviewRequestStateName, ReviewResultName, ReviewTypeName, RoleName, RoomResourceName, - SessionStatusName, StdLevelName, StreamName, TimeSlotTypeName, ) + SessionStatusName, StdLevelName, StreamName, TimeSlotTypeName, TopicAudienceName, ) from ietf.stats.models import CountryAlias @@ -75,4 +74,4 @@ admin.site.register(SessionStatusName, NameAdmin) admin.site.register(StdLevelName, NameAdmin) admin.site.register(StreamName, NameAdmin) admin.site.register(TimeSlotTypeName, NameAdmin) - +admin.site.register(TopicAudienceName, NameAdmin) diff --git a/ietf/nomcom/admin.py b/ietf/nomcom/admin.py index b830edd6d..66711ca9c 100644 --- a/ietf/nomcom/admin.py +++ b/ietf/nomcom/admin.py @@ -1,40 +1,63 @@ from django.contrib import admin -from ietf.nomcom.models import NomCom, Nomination, Nominee, NomineePosition, \ - Position, Feedback +from ietf.nomcom.models import ( ReminderDates, NomCom, Nomination, Nominee, NomineePosition, + Position, Feedback, FeedbackLastSeen, TopicFeedbackLastSeen) +class ReminderDatesAdmin(admin.ModelAdmin): + list_display = ['id', 'date', 'nomcom'] + list_filter = ['date', 'nomcom'] +admin.site.register(ReminderDates, ReminderDatesAdmin) + class NomComAdmin(admin.ModelAdmin): - raw_id_fields = ('group', ) - + list_display = ['id', 'group', 'send_questionnaire', 'reminder_interval', 'initial_text', 'show_nominee_pictures'] + list_filter = ['send_questionnaire', 'show_nominee_pictures'] + raw_id_fields = ['group'] +admin.site.register(NomCom, NomComAdmin) class NominationAdmin(admin.ModelAdmin): - list_display = ('candidate_email', 'nominator_email', 'position') - + list_display = ['id', 'position', 'candidate_name', 'candidate_email', 'candidate_phone', 'nominee', 'comments', 'nominator_email', 'user', 'time', 'share_nominator'] + list_filter = ['time', 'share_nominator'] + raw_id_fields = ['nominee', 'comments', 'user'] +admin.site.register(Nomination, NominationAdmin) class NomineeAdmin(admin.ModelAdmin): list_display = ('email', 'person', 'duplicated', 'nomcom') search_fields = ('email__address', 'person__name', ) list_filter = ('nomcom', ) + raw_id_fields = ['nominee_position', 'email', 'person', 'duplicated'] +admin.site.register(Nominee, NomineeAdmin) class NomineePositionAdmin(admin.ModelAdmin): - pass - list_display = ('nominee', 'position', 'state') - list_filter = ('state', 'position') - + list_display = ['id', 'position', 'nominee', 'state', 'time'] + list_filter = ['state', 'position', 'time'] + raw_id_fields = ['nominee'] +admin.site.register(NomineePosition, NomineePositionAdmin) class PositionAdmin(admin.ModelAdmin): list_display = ('name', 'nomcom', 'is_open', 'accepting_nominations', 'accepting_feedback') - list_filter = ('nomcom',) - + list_filter = ['nomcom', 'is_open', 'accepting_nominations', 'accepting_feedback'] + raw_id_fields = ['requirement', 'questionnaire'] + search_fields = ['name'] +admin.site.register(Position, PositionAdmin) class FeedbackAdmin(admin.ModelAdmin): - list_display = ('author', 'type') - list_filter = ('type',) - -admin.site.register(NomCom, NomComAdmin) -admin.site.register(Nomination, NominationAdmin) -admin.site.register(Nominee, NomineeAdmin) -admin.site.register(NomineePosition, NomineePositionAdmin) -admin.site.register(Position, PositionAdmin) + list_display = ['id', 'nomcom', 'author', 'subject', 'type', 'user', 'time'] + list_filter = ['nomcom', 'type', 'time'] + raw_id_fields = ['positions', 'topics', 'user'] admin.site.register(Feedback, FeedbackAdmin) + + +class FeedbackLastSeenAdmin(admin.ModelAdmin): + list_display = ['id', 'reviewer', 'nominee', 'time'] + list_filter = ['time'] + raw_id_fields = ['reviewer', 'nominee'] +admin.site.register(FeedbackLastSeen, FeedbackLastSeenAdmin) + +class TopicFeedbackLastSeenAdmin(admin.ModelAdmin): + list_display = ['id', 'reviewer', 'topic', 'time'] + list_filter = ['topic', 'time'] + raw_id_fields = ['reviewer'] +admin.site.register(TopicFeedbackLastSeen, TopicFeedbackLastSeenAdmin) + + diff --git a/ietf/person/admin.py b/ietf/person/admin.py index e51427afa..c50536280 100644 --- a/ietf/person/admin.py +++ b/ietf/person/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin -from ietf.person.models import Email, Alias, Person +from ietf.person.models import Email, Alias, Person, PersonHistory from ietf.person.name import name_parts class EmailAdmin(admin.ModelAdmin): @@ -32,3 +32,15 @@ class PersonAdmin(admin.ModelAdmin): inlines = [ EmailInline, AliasInline, ] # actions = None admin.site.register(Person, PersonAdmin) + +class PersonHistoryAdmin(admin.ModelAdmin): + def plain_name(self, obj): + prefix, first, middle, last, suffix = name_parts(obj.name) + return "%s %s" % (first, last) + list_display = ['name', 'short', 'plain_name', 'time', 'user', 'person', ] + list_filter = ['time'] + raw_id_fields = ['person', 'user'] + search_fields = ['name', 'ascii'] +admin.site.register(PersonHistory, PersonHistoryAdmin) + + diff --git a/ietf/review/admin.py b/ietf/review/admin.py index a706fc744..30ace82f8 100644 --- a/ietf/review/admin.py +++ b/ietf/review/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin -from ietf.review.models import (ReviewerSettings, UnavailablePeriod, ReviewWish, NextReviewerInTeam, - ReviewRequest, ReviewTeamSettings ) +from ietf.review.models import (ReviewerSettings, ReviewSecretarySettings, UnavailablePeriod, + ReviewWish, NextReviewerInTeam, ReviewRequest, ReviewTeamSettings ) class ReviewerSettingsAdmin(admin.ModelAdmin): def acronym(self, obj): @@ -14,6 +14,11 @@ class ReviewerSettingsAdmin(admin.ModelAdmin): admin.site.register(ReviewerSettings, ReviewerSettingsAdmin) +class ReviewSecretarySettingsAdmin(admin.ModelAdmin): + list_display = [u'id', 'team', 'person', 'remind_days_before_deadline'] + raw_id_fields = ['team', 'person'] +admin.site.register(ReviewSecretarySettings, ReviewSecretarySettingsAdmin) + class UnavailablePeriodAdmin(admin.ModelAdmin): list_display = ["person", "team", "start_date", "end_date", "availability"] list_display_links = ["person"] diff --git a/ietf/settings.py b/ietf/settings.py index 62996baa8..0b810d25e 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -371,6 +371,7 @@ INSTALLED_APPS = ( # External apps 'anora', 'bootstrap3', + 'django_admin_generator', 'django_markup', 'django_password_strength', 'djangobwr', diff --git a/ietf/utils/admin.py b/ietf/utils/admin.py index 73e166409..94c0a9c96 100644 --- a/ietf/utils/admin.py +++ b/ietf/utils/admin.py @@ -47,6 +47,13 @@ def admin_link(field, label=None, ordering="", display=name, suffix=""): _link.admin_order_field = ordering return _link +from models import DumpInfo +class DumpInfoAdmin(admin.ModelAdmin): + list_display = ['date', 'host', 'tz'] + list_filter = ['date'] +admin.site.register(DumpInfo, DumpInfoAdmin) + class VersionInfoAdmin(admin.ModelAdmin): list_display = ['command', 'switch', 'version', 'time', ] admin.site.register(VersionInfo, VersionInfoAdmin) + diff --git a/ietf/utils/tests.py b/ietf/utils/tests.py index 63618afec..d8c3aa3e1 100644 --- a/ietf/utils/tests.py +++ b/ietf/utils/tests.py @@ -2,16 +2,19 @@ import os.path import types import shutil -from StringIO import StringIO -from pipe import pipe -from unittest import skipIf -from fnmatch import fnmatch -from textwrap import dedent -from email.mime.text import MIMEText from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from fnmatch import fnmatch +from importlib import import_module +from pipe import pipe +from StringIO import StringIO +from textwrap import dedent +from unittest import skipIf +from django.apps import apps +from django.contrib.auth.models import User from django.conf import settings from django.core.management import call_command from django.template import Context @@ -269,6 +272,41 @@ class TestWikiGlueManagementCommand(TestCase): self.assertIn("Adding page %s" % os.path.basename(page), command_output) self.assertIn("Indexing default repository", command_output) +OMITTED_APPS = [ + 'ietf.secr.meetings', + 'ietf.secr.proceedings', + 'ietf.redirects', +] + +class AdminTestCase(TestCase): + def __init__(self, *args, **kwargs): + self.apps = {} + for app_name in settings.INSTALLED_APPS: + if app_name.startswith('ietf') and not app_name in OMITTED_APPS: + app = import_module(app_name) + name = app_name.split('.',1)[-1] + models_path = os.path.join(os.path.dirname(app.__file__), "models.py") + if os.path.exists(models_path): + self.apps[name] = app_name + super(AdminTestCase, self).__init__(*args, **kwargs) + + def test_all_model_admins_exist(self): + + User.objects.create_superuser('admin', 'admin@example.org', 'admin+password') + self.client.login(username='admin', password='admin+password') + rtop = self.client.get("/admin/") + self.assertContains(rtop, 'Django administration') + for name in self.apps: + app_name = self.apps[name] + self.assertContains(rtop, name) + app = import_module(app_name) + r = self.client.get('/admin/%s/'%name) + # + model_list = apps.get_app_config(name).get_models() + for model in model_list: + self.assertContains(r, model._meta.model_name, + msg_prefix="There doesn't seem to be any admin API for model %s.models.%s"%(app.__name__,model.__name__,)) + ## One might think that the code below would work, but it doesn't ... # def list_static_files(path):