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

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

Предположим, у вас очень большое количество моделей (например, 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 - likeo:

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

где SomeModelA - это модель (а не форма), которую Джанго на заднем плане превратил в ModelForm.

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

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

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

1 Ответ

7 голосов
/ 20 марта 2009

Звучит так, будто вы хотите сделать это в рамках всего проекта (то есть: вы пытаетесь сделать это не в некоторых случаях, а во ВСЕХ случаях в запущенном приложении).

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

То, что вы хотите сделать, это переназначить свойство виджета для самого класса forms.DateField. Когда создается новое поле DateField, Django проверяет, указывает ли код какой-либо конкретный виджет в определении свойства поля. Если нет, он использует значение по умолчанию для DateField. Я предполагаю, что если пользователь в вашем сценарии действительно определил конкретный виджет, вы хотели бы соблюдать это, несмотря на изменение вашего глобального 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>
...