KeyError重写django ModelAdmin.get_readonly_fields()

时间:2016-12-16 22:44:09

标签: django django-admin

我正在尝试覆盖django ModelAdmin中的get_readonly_fields()方法。如果存在某种情况,我想将几​​乎所有字段都返回为readonly_fields。这是看起来的样子:

from django.contrib import admin
from cms.admin.placeholderadmin import PlaceholderAdminMixin

from .models import (Story, StoryCategory, AVAILABLE_STORY, GLOBAL_STORY)


RESTRICTED_PUB_FIELDS = ('pub_date',)
RESTRICTED_FIELDS = ( 
    'global_status',
    'title',
    'byline',
    'byline_headshot',
    'featured_image',
    'use_featured_image_on_detail_page',
    'outside_article_box',
    'has_detail_page',
    'landing_page_link',
    'link_text',
    'global_categories',
    'initiatives_tags',
    'stat_text_before',
    'stat_number',
    'stat_text_after',
    'offices',
    'rural_liscs',
)

class StoryAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
    def get_readonly_fields(self, request, obj=None):
        if obj and obj.global_status == AVAILABLE_STORY:
            fields = self.readonly_fields + \ 
                RESTRICTED_PUB_FIELDS + RESTRICTED_FIELDS
            return fields
        return self.readonly_fields

    def change_view(self, request, object_id, extra_context=None):
        if '_saveasnew' in request.POST:
            if request.POST['global_status'] == AVAILABLE_STORY:
                request.POST['global_status'] = GLOBAL_STORY

        return super(StoryAdmin, self).change_view(
                        request, object_id, extra_context=extra_context
                    )   

    fieldsets = ( 
        ('Publishing Information', {
            'fields': (
                'status', RESTRICTED_PUB_FIELDS, 'expire_date', 'slug'
            )   
        }), 
        (None, {'fields': (
            RESTRICTED_FIELDS,
            'excerpt',
            'local_categories',
            'is_featured',
        )}),
    )   

    [...]

admin.site.register(Story, StoryAdmin)

但是当get_readonly_fields()中的条件为真时,会引发KeyError - 而不是Story对象而是StoryForm。我知道Django为我动态创建了一个ModelForm,所以我假设我在某些时候错误地传递了一些东西,但是我看不到它在哪里。我试着几乎逐字逐句地回答这个问题:https://stackoverflow.com/a/11601613/4846824

这是完整的堆栈跟踪:

Environment:   

Request Method: GET
Request URL: http://localhost:8000/communitycenter/stories/story/369/

Django Version: 1.7.8
Python Version: 2.7.10
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.humanize',
 'django.contrib.messages',
 'django.contrib.redirects',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.sitemaps',
 'djangocms_admin_style',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'django.contrib.staticfiles',
 'djangocms_text_ckeditor',
 'cms',
 'djangocms_snippet',
 'filer',
 'menus',
 'sekizai',
 'djangocms_link',
 'clear_cache',
 'compressor',
 'constance',
 'constance.backends.database',
 'adminsortable',
 'django_extensions',
 'easy_thumbnails',
 'gunicorn',
 'haystack',
 'memcache_status',
 'mptt',
 'simplejson',
 'tinymce',
 'treebeard',
 'twython',
 'apps.common',
 'apps.charter',
 'apps.submenu',
 'apps.offices',
 'apps.events',
 'apps.microsites',
 'apps.resources',
 'apps.search',
 'apps.stories',
 'apps.plugins',
 'apps.twitter',
 'apps.charter_calculator')
Installed Middleware:
('django.middleware.cache.UpdateCacheMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'cms.middleware.page.CurrentPageMiddleware',
 'cms.middleware.user.CurrentUserMiddleware',
 'cms.middleware.toolbar.ToolbarMiddleware',
 'django.middleware.cache.FetchFromCacheMiddleware')


Traceback:
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
  583.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
  105.                     response = view_func(request, *args, **kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  52.         response = view_func(request, *args, **kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
  206.             return view(request, *args, **kwargs)
File "/Users/kedmundson/DEV/lisc/source/apps/stories/admin.py" in change_view
  46.                         request, object_id, extra_context=extra_context
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
  1456.         return self.changeform_view(request, object_id, form_url, extra_context)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
  29.             return bound_func(*args, **kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
  105.                     response = view_func(request, *args, **kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
  25.                 return func.__get__(self, type(self))(*args2, **kwargs2)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/db/transaction.py" in inner
  394.                 return func(*args, **kwargs)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/contrib/admin/options.py" in changeform_view
  1427.             model_admin=self)
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/contrib/admin/helpers.py" in __init__
  36.         } for field_name, dependencies in prepopulated_fields.items()]
File "/Users/kedmundson/.virtualenvs/lisc/lib/python2.7/site-packages/django/forms/forms.py" in __getitem__
  147.                 "Key %r not found in '%s'" % (name, self.__class__.__name__))

Exception Type: KeyError at /communitycenter/stories/story/369/
Exception Value: u"Key 'title' not found in 'StoryForm'"

1 个答案:

答案 0 :(得分:1)

啊哈。问题是我的a值:

prepopulated_fields

看起来让prepopulated_fields = {'slug': ('title',)}只读,使其无法预填充title字段。但这对我来说没关系,因为用户无论如何都必须更改slug,所以我添加了slug的覆盖,它与get_prepopulated_fields()中的条件检查相同:

get_readonly_fields()