Я постараюсь быть как можно более кратким.
Фон
У меня есть модель Person
, которая имеет ForeignKey
для модели Document
.Каждый Person
может иметь только один Document
, но, как вы, возможно, уже знаете, каждый Document
может быть связан со многими Person
s.
В форме администратора Document
, которую я имеюPerson
s, связанные с Document
, отображаемым в строке.Я могу редактировать, добавлять или удалять Person
s прямо там.
Проблема
Следуя этим шагам, я получаю ошибку:
- Я открываю форму редактирования администратора для
Document
.Давайте назовем это Документ A .С этим Document
связаны два Person
, назовем их Джон Доу и Джейн Доу .Вы можете видеть их там (встроенными) в форме, и поля доступны для редактирования, но я их не трогаю. - Я открываю другую вкладку и сразу перехожу к списку
Person
s и удаляю Джейн Доу . - Я возвращаюсь к первой вкладке (форма редактирования
Document
) и нажимаю " Сохранить и продолжить редактирование ". - Форма отправлена, и я получаю общую ошибку вверху (что-то вроде) " Пожалуйста, исправьте следующие ошибки ".Но форма не показывает ошибок (рядом с полями) для исправления и, очевидно, запись для Джейн Доу не отображается.
- Я снова нажимаю " Сохранить ипродолжить редактирование"и при отправке формы я получаю сообщение об ошибке"
MultiValueDictKeyError: "u'person_set-1-id'"
".
Идеальное решение
Я бы хотелиметь возможность отображать пользовательскую ошибку на средней стадии (когда появляется первая ошибка, после первого сохранения), говоря что-то вроде " Человек, связанный с этим документом, был удален, когда вы редактировали его ".Кроме того, предотвращение последней ошибки крайне желательно.
Дамп ошибок
MultiValueDictKeyError at /admin/persons/document/1145/
"u'person_set-1-id'"
Request Method: POST
Request URL: http://localhost:8000/admin/persons/document/1145/
Django Version: 1.7.7
Exception Type: MultiValueDictKeyError
Exception Value:
"u'person_set-1-id'"
Exception Location: /__PATH__/local/lib/python2.7/site-packages/django/utils/datastructures.py in __getitem__, line 319
Python Executable: /__PATH__/bin/python
Python Version: 2.7.15
Python Path:
['/__PATH__/test/test/apps',
'/__PATH__/test',
'/__PATH__/lib/python2.7',
'/__PATH__/lib/python2.7/plat-x86_64-linux-gnu',
'/__PATH__/lib/python2.7/lib-tk',
'/__PATH__/lib/python2.7/lib-old',
'/__PATH__/lib/python2.7/lib-dynload',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/__PATH__/local/lib/python2.7/site-packages',
'/__PATH__/src/django-smart-selects',
'/__PATH__/lib/python2.7/site-packages',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/local/lib/python2.7/site-packages/odf',
'/__PATH__/test']
Server time: Mar, 29 Ene 2019 11:52:18 -0300
Environment:
Request Method: POST
Request URL: http://localhost:8000/admin/persons/document/1145/
Django Version: 1.7.7
Python Version: 2.7.15
Installed Applications:
('salmonella',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'crispy_forms',
'test.apps.persons',
'captcha',
'django_countries',
'django_extensions',
'import_export',
'django_object_actions',
'widget_tweaks',
'smart_selects',
'daterange_filter',
'compressor',
'auditlog')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'auditlog.middleware.AuditlogMiddleware')
Traceback:
File "/__PATH__/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
583. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
105. response = view_func(request, *args, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
52. response = view_func(request, *args, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
206. return view(request, *args, **kwargs)
File "/__PATH__/local/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 "/__PATH__/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
29. return bound_func(*args, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
105. response = view_func(request, *args, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
25. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/__PATH__/local/lib/python2.7/site-packages/django/db/transaction.py" in inner
394. return func(*args, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in changeform_view
1403. if all_valid(formsets) and form_validated:
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/formsets.py" in all_valid
438. if not formset.is_valid():
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/formsets.py" in is_valid
303. self.errors
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/formsets.py" in errors
277. self.full_clean()
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/formsets.py" in full_clean
325. form = self.forms[i]
File "/__PATH__/local/lib/python2.7/site-packages/django/utils/functional.py" in __get__
55. res = instance.__dict__[self.func.__name__] = self.func(instance)
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/formsets.py" in forms
141. forms = [self._construct_form(i) for i in xrange(self.total_form_count())]
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/models.py" in _construct_form
868. form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
File "/__PATH__/local/lib/python2.7/site-packages/django/forms/models.py" in _construct_form
581. pk = self.data[pk_key]
File "/__PATH__/local/lib/python2.7/site-packages/django/utils/datastructures.py" in __getitem__
319. raise MultiValueDictKeyError(repr(key))
Exception Type: MultiValueDictKeyError at /admin/persons/document/1145/
Exception Value: "u'person_set-1-id'"
ОБНОВЛЕНИЕ
Я добавляюопределения для моделей Person и Document.
class Document(models.Model):
creation_date = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=300, null=True, blank=True)
class Person(models.Model):
first_name = models.CharField(max_length=300)
last_name = models.CharField(max_length=300)
email = models.EmailField(max_length=300)
document = models.ForeignKey(Document)
ОБНОВЛЕНИЕ 2
Одна важная вещь, которую я заметил, заключается в том, что на первой странице ошибки (после первого представления Документ A ) скрытые вводы, такие как person_set-TOTAL_FORMS
и person_set-INITIAL_FORMS
, устанавливаются на 2, в то время как они должны быть установлены на 1 (фактическое количество человек).Очевидно, это происходит потому, что представленные данные не отражают фактическое состояние базы данных.