Как изменить виджет по умолчанию для всех встроенных полей формы определенного типа в Django?


Это продолжение Как изменить виджет по умолчанию для всех полей даты Django в форме модели?.

Предположим, у вас есть очень большое количество моделей (например, A-ZZZ), которые растут с вводом других разработчиков, которые находятся вне вашего контроля, и вы хотите изменить способ ввода всех полей даты (например, с помощью jQueryUI). Как лучше всего обеспечить заполнение всех полей даты с помощью этого нового виджета?

Одно предложение из приведенного вопроса было:

def make_custom_datefield(f):
   if isinstance(f, models.DateField):
       # return form field with your custom widget here...
   else:
       return f.formfield()

class SomeForm(forms.ModelForm): 
   formfield_callback = make_custom_datefield

   class Meta:
       # normal modelform stuff here...

Однако возможно ли это сделать там, где у вас нет явных шаблонов ModelForm, но шаблоны url приходят непосредственно из моделей? то есть Ваш url config выглядит следующим образом:

url(r'^A/?$', 'list_detail.object_list', SomeModelA)

Где SomeModelA-это модель (не форма), которая была превращена в ModelForm Джанго в фоновом режиме.

В настоящее время в моей системе нет форм для каждой модели. Единственным моментом явного создания форм было бы добавление formfield_callback, предложенного в предыдущем решении, но это идет против сухих принципов, и был бы подвержен ошибкам и трудоемким.

Я рассматривал (как было предложено в последнем потоке) создание моего собственного поля, которое имеет специальный виджет и использует его вместо встроенного. Это не так трудоемко, но это может быть подвержено ошибкам (ничего хорошего grep не мог исправить, хотя).

Предложения и мысли приветствуются.

1 4

1 ответ:

Похоже, что вы хотите сделать это в рамках всего проекта (т. е.: вы не пытаетесь сделать это в некоторых случаях, но во всех случаях в вашем запущенном приложении).

Одна из возможностей заключается в замене атрибута widget самого класса DateField. Вам нужно будет сделать это в каком-нибудь центральном месте... что-то, что гарантированно будет загружено каждым запущенным экземпляром приложения django. Промежуточное программное обеспечение может помочь в этом. В противном случае просто поместите его в файл __init__ вашего приложения.

Что вы хотите do-это повторно назначить свойство виджета для форм.Дата самого класса. При создании нового поля даты Django проверяет, указывает ли код какой-либо конкретный виджет в определении свойства поля. Если нет, то используется поле по умолчанию для даты. Я предполагаю, что если пользователь в вашем сценарии действительно определил конкретный виджет, вы захотите выполнить это, несмотря на изменение вашего глобального API.

Попробуйте это в качестве примера принудительного применения значения по умолчанию к какому-либо другому виджету... в этом случае HiddenInput:

from django import forms
forms.DateField.widget = forms.HiddenInput

class Foo(forms.Form):
    a = forms.DateField()

f = Foo()
print f.fields['a'].widget
# results in <django.forms.widgets.HiddenInput object at 0x16bd910>