Opened 10 years ago
Closed 10 years ago
#24187 closed Uncategorized (invalid)
admin.ModelAdmin base-class Cross referencing fields
Reported by: | Charles | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | 1.7 |
Severity: | Release blocker | Keywords: | ModelAdmin |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Hello,
I have found a bug on the ModelAdmin, I will try my best to explain.
My Environment is as follows:
Vagrant / Debian VM
nginx webserver
uWSGI webserver
Django 1.7.3
Grappelli admin panel
Basically I have a website, which has 2 types of articles Global and Local articles, each model inherit from a base (abstract) model:
class ArticleBase(models.Model): title = models.CharField(max_length=100, null=False, help_text="Character limit: 100") body = club_fields.WysiwygField(blank=True) etc... class Meta(object): abstract = True class Article(ArticleBase): # Can't be set in base as is unique in Global but not unique by itself in localised article slug = models.SlugField(max_length=100, unique=True) class Meta(object): index_together = [ ["slug", "status"], ] ordering = ("-creation_date",) class LocalisedArticle(ArticleBase): # Can't be set in base as is unique in Global but not unique by itself in localised article slug = models.SlugField(max_length=100) locale = models.CharField(max_length=10, null=False, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE) class Meta(object): unique_together = ( ("slug", "locale") ) index_together = [ ["slug", "status", "locale"], ] ordering = ("-pub_date",)
And I have setup the admin classes to follow a similar suit, where each article admin inherits from a baseclass which sets up fieldsets etc..
class ArticleAdmin(ImageCroppingMixin,admin.ModelAdmin): ordering = ("-pub_date",) list_display = ["title", "pub_date", "status", "update_date"] prepopulated_fields = {"slug": ("title", ), } exclude = ("overview_image", "hero_image") fieldsets = [ ["Meta", { "fields": ("title", "heading_intro", "heading_sub", "slug", "status", "pub_date", "meta_description", "social_description", "article_type", "category", "download") }], ["Content", { "fields": ("body", "image", "overview_crop", "overview_alignment", "hero_crop", "video_id", "discussion_question", "disable_comments") }], ] class GlobalArticleAdmin(ArticleAdmin): inlines = [ ArticleInlineImageAdmin, ArticleCarouselInlineAdmin ] class LocalisedArticleAdmin(ArticleAdmin): list_filter = ("locale", "status") inlines = [ LocalisedArticleInlineAdmin, LocalisedArticleCarouselInlineAdmin, ArticleCommentInlineAdmin, ] def get_list_display(self, request): list_display = super(LocalisedArticleAdmin, self).get_list_display(request) return list_display + ['locale'] def get_fieldsets(self, request, obj=None): fieldsets = super(LocalisedArticleAdmin, self).get_fieldsets(request, obj) for i, fieldset in enumerate(fieldsets): if fieldset[0] == 'Meta': if 'locale' not in fieldset[1]['fields']: fieldsets[i][1]['fields'] += ('locale',) break return fieldsets def get_form(self, request, obj=None, **kwargs): form = super(LocalisedArticleAdmin, self).get_form(request, obj, **kwargs) editable_locales = self.get_editable_locales(request) locale_choices = [] for lang in settings.LANGUAGES: if lang[0] in editable_locales: locale_choices.append(lang) form.base_fields['locale'].choices = locale_choices return form admin.site.register(Article, GlobalArticleAdmin) admin.site.register(LocalisedArticle, LocalisedArticleAdmin)
In the localised article admin class, I have overloaded certain methods to include the Locale Field in the forms, with appropriate editable locales based on custom model permissions (I haven't included the entire class as they are quite long, and I don't think the most part is necessary)
The Bug
Now, the bug is that, I can view the global article admin page no problems if I go to that admin page first, but as soon as I goto the localised article admin and save a localised article model, and go back to the global article admin page I get the following error:
Request Method: GET Request URL: http://localhost:8000/admin/my_app/article/1/ Django Version: 1.7.3 Python Version: 2.7.3 Installed Applications: (u'django.contrib.auth', u'django.contrib.contenttypes', u'django.contrib.sessions', u'django.contrib.messages', u'django.contrib.staticfiles', u'compressor', u'imagekit', u'haystack', u'my_app', u'grappelli.dashboard', u'grappelli', u'django.contrib.admin', u'django_user_agents', u'easy_thumbnails', u'image_cropping') Installed Middleware: (u'django.contrib.sessions.middleware.SessionMiddleware', u'django.middleware.locale.LocaleMiddleware', u'django.middleware.common.CommonMiddleware', u'django.middleware.csrf.CsrfViewMiddleware', u'django.contrib.auth.middleware.AuthenticationMiddleware', u'django.contrib.messages.middleware.MessageMiddleware', u'django.middleware.clickjacking.XFrameOptionsMiddleware', u'django_user_agents.middleware.UserAgentMiddleware') Traceback: File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response 111. response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in wrapper 583. return self.admin_site.admin_view(view)(*args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view 105. response = view_func(request, *args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func 52. response = view_func(request, *args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py" in inner 206. return view(request, *args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in change_view 1456. return self.changeform_view(request, object_id, form_url, extra_context) File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapper 29. return bound_func(*args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view 105. response = view_func(request, *args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in bound_func 25. return func.__get__(self, type(self))(*args2, **kwargs2) File "/usr/local/lib/python2.7/dist-packages/django/db/transaction.py" in inner 394. return func(*args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in changeform_view 1393. ModelForm = self.get_form(request, obj) File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in get_form 670. % (e, self.__class__.__name__)) Exception Type: FieldError at /admin/my_app/article/1/ Exception Value: Unknown field(s) (locale) specified for Article. Check fields/fieldsets/exclude attributes of class GlobalArticleAdmin.
Now, no where in the Article model, ArticleAdmin base class, or the GlobalArticleAdmin class is the field 'locale' referenced, the ONLY place this field is referenced is in the LocalisedArticle model and the LocalArticleAdmin class overloaded form and field methods.. and as I say, this only comes up after I save a Localiased article, if I reload the uWSGI instance, I can access the GlobalArticleAdmin no problem.. and this does not happen if I remove the ArticleAdmin base class, and duplicate the code in both admin classes..
I have no idea why the GlobalArticleAdmin is trying to add a 'locale' field to the admin page..
Please advise.
This line looks suspicious to me
fieldsets[i][1]['fields'] += ('locale',)
.Please see TicketClosingReasons/UseSupportChannels.