Arhn - архитектура программирования

KeyError переопределяет django ModelAdmin.get_readonly_fields()

Я пытаюсь переопределить метод get_readonly_fields() в моем django ModelAdmin. Если существует определенное условие, я хочу вернуть почти все свои поля как 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'"

  • полная трассировка стека 17.12.2016
  • Проблема только с title полями? Если это так, скорее всего, вы не включили title в качестве поля в конкретный вариант использования. 17.12.2016
  • Остановитесь с pdb или ipdb внутри if и посмотрите, какие поля вы извлекаете. установите вручную значение заголовка и продолжайте оттуда 21.12.2016

Ответы:


1

Ага. Проблема заключалась в моем значении prepopulated_fields:

prepopulated_fields = {'slug': ('title',)}

Похоже, что создание title только для чтения сделало невозможным предварительное заполнение поля slug. Но меня это устраивает, поскольку пользователю все равно придется изменить слаг, поэтому я добавил это переопределение get_prepopulated_fields(), которое выполняет ту же условную проверку, что и в get_readonly_fields():

def get_prepopulated_fields(self, request, obj=None):
    if obj and obj.global_status == AVAILABLE_STORY:
        return {}
    return self.prepopulated_fields 
22.12.2016
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..