Всегда обрабатывайте поле ForeignKey так, как это было в raw_id_fields в Django Admin

#python #django #django-admin

#python #django #django-admin

Вопрос:

Этот сценарий происходит слишком часто в моем проекте:

  • кто-то добавляет модель Foo с несколькими ForeignKey полями, одно из которых ссылается на model Bar
  • для этой модели добавлен администратор (и работает нормально)
  • код развернут
  • на рабочем сервере, Bar имеет миллионы экземпляров
  • кто Foo -то обращается к странице администратора; Django пытается получить все Bar s сразу (чтобы отобразить их в поле со списком), и сервер перегружается
  • позже проблема будет устранена путем редактирования Foo admin и добавления bar в raw_id_fields .

Я бы хотел предотвратить повторение этой ситуации в будущем, желательно каким-то образом указав (раз и навсегда), что Bar у него много строк, и его всегда следует обрабатывать так, как если бы поле, ссылающееся на него, было указано raw_id_fields на всех страницах администратора. Возможно ли это как-то?

Ответ №1:

Это отличный момент. Это критическая проблема, которая может отключить базу данных и даже веб-сервер.

Учитывая это, я считаю, что подход по умолчанию ДОЛЖЕН быть raw_id_fields правильным. Если вы знаете, что делаете, тогда вы меняете это поведение.

К сожалению, большинство авторов библиотек интерфейсов администратора не согласны с этой мыслью. Не только для Python-Django, но и для других сообществ, таких как Ruby-Rails.

5 лет назад мне надоела одна и та же проблема, тогда я разработал django-smart-autoregister, который делает это, а также автоматически настраивает, используя другие хорошие шаблоны. Даже сегодня я сталкиваюсь с этой проблемой, поэтому, я думаю, стоит взглянуть.

ps: библиотека изначально была реализована с использованием модульного подхода, хотя вы просто вызываете некоторые функции, которые настраивают raw_id_fields для вас в соответствии с полем модели.

Ответ №2:

Из документов:

ForeignKey представлен django.forms .ModelChoiceField, которое является полем выбора, выбор которого является набором запросов модели.

ModelChoiceField расширяет поле и поэтому имеет свойство виджета, которым можно злоупотреблять https://github.com/django/django/blob/master/django/forms/fields.py#L49

Добавьте это где-нибудь в файлы вашего проекта.

 from django.forms import ModelChoiceField
from django.contrib.admin.widgets import ForeignKeyRawIdWidget
ModelChoiceField.widget = ForeignKeyRawIdWidget
 

недостаток: это также произойдет в формах, не являющихся администраторами

Комментарии:

1. Хм, это хорошая отправная точка — теперь, возможно, можно заставить ModelAdmin выборочно использовать этот виджет при создании его ModelForm.