Сводка
Мы бы хотели установить начальный выбор полей выбора, представляющих различные виды отношений модели, на базовой странице «добавить» или «изменить» в админке Django.Первоначальный выбор должен быть сохранен в базе данных, если пользователь нажимает одну из кнопок «Сохранить».
Мы специально хотим сделать это, установив значение initial
в полях формы (для ModelAdmin
или TabularInline
).
Вопрос в следующем:
Какое «значение» присваивать Field.initial
, для различных видов отношенийполя формы?
Фон
Предположим, у нас есть простое Model
с одним или несколькими полями отношений , т.е. OneToOneField
, ForeignKey
или ManyToManyField
.По умолчанию последняя имеет модель неявная through
, но может также использовать модель явная through
, как объяснено в документах .Явная модель through
- это модель с как минимум двумя ForeignKey
полями.
Поля отношений, представленные полями выбора, автоматически появляются в стандартном ModelAdmin
"add"или" изменить "формы, за исключением ManyToManyField
с явной through
моделью.Для этого требуется встроенный символ, такой как TabularInline
, как объяснено здесь в документах.
Обратите внимание, что неявное ManyToManyField
связано с ModelMultipleChoiceField
в форме (admin), а другие поля отношений связаны с ModelChoiceField
.Последний включает ManyToManyField
с явной through
моделью, потому что это фактически представлено полем ForeignKey
в TabularInline
.
Цель
Теперь рассмотрим базовую страницу Django ModelAdmin
«add» (или «change») для этой модели, включая строчные для любых явных through
моделей.,Пример на основе пиццерии Джанго приведен ниже.
Мы хотим достичь двух целей:
- установить начальный выбор для одного или несколькихполя отношений
- начальный выбор должен быть сохранен в базе данных, если мы нажмем одну из кнопок «Сохранить» (при условии, что мы не изменили выбор вручную)
Обратите внимание, что второй кажется тривиальным, но, по-видимому, нет (см. Ниже).
Подход
Насколько далеконасколько я знаю, есть несколько способов достичь этого:
- установить в поле модели значение
default
, например, ForeignKey.default
, опционально передавая вызываемую ( docs ) - установить значение
Form.initial
для формы администратора ( документы ) - установить значение
Field.initial
для поля формы администратора ( документы )
Независимо от того, какой подход «лучший» для определенного варианта использования, этот вопрос относится к последнему подходу: setting значение Field.initial
.
Мы делаем это путем расширения ModelAdmin.formfield_for_dbfield
(или TabularInline.formfield_for_dbfield
) следующим образом:
def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'some_relationship_field_name':
kwargs['initial'] = value
return super().formfield_for_dbfield(db_field, request, **kwargs)
value
в этом примере может бытьobj.id
, obj
, [obj.id, ...]
или [obj, ...]
, где obj
- это Model
экземпляр.
Задача
В зависимости от типа поля отношения,различные типы value
могут работать или не работать.
Для ManyToManyField
с неявной through
моделью мы можем только назначить список объектов, так что один будет простым.
Для других отношений в некоторых случаях начальный выбор поля выбора соответствует назначенному значению, но не сохраняется (например, потому что Field.has_changed возвращает False
).В других случаях исходное значение поля выбора сохраняется, но не соответствует назначенному значению.
Вопрос
Итак, очевидный вопрос:
Как правильно value
назначить Field.initial
для различных типов полей отношений наадминистративная форма?
Похожие
Несмотря на то, что я потратил довольно много времени на поиск, я не смог найти четкого ответа ни в документации, ни в SO, ни где-либо еще.Также пытался выяснить это через исходный код, но это оказалось довольно сложно.
Некоторые похожие вопросы: