Переопределение начального значения в ModelForm - PullRequest
22 голосов
/ 07 июня 2010

в моем проекте Django (1.2) я хочу предварительно заполнить поле в форме модели, но мое новое значение игнорируется. Это фрагмент:

class ArtefactForm(ModelForm):
    material = CharField(widget=AutoCompleteWidget('material', force_selection=False))

    def __init__(self, *args, **kwargs):
        super(ArtefactForm, self).__init__(*args, **kwargs)
        self.fields['material'].initial = 'Test'

Я также пробовал с self.base_fields, но безрезультатно: в форме всегда отображается значение базы данных. Есть идеи?

Ответы [ 2 ]

40 голосов
/ 07 июня 2010

Попробуйте это:

def __init__(self, *args, **kwargs):
    initial = kwargs.get('initial', {})
    initial['material'] = 'Test'
    kwargs['initial'] = initial
    super(ArtefactForm, self).__init__(*args, **kwargs)
12 голосов
/ 30 ноября 2014

Старый вопрос, но добавление описательного ответа, так как я считаю, что это будет полезно для какого-то нового разработчика.

Я также пытался с self. base_fields, нобезрезультатно: в форме всегда отображается значение базы данных.Любые идеи?

Если форма является «инициализированной» формой, либо: -

  1. с использованием аргумента initial (например, YourModelFrom(initial={'filed1': variable}) - как правило,случай, когда вы хотите передать динамически рассчитанные начальные значения для некоторых полей).Ссылка Setting Initial Values

    или

  2. с использованием аргумента instance (например, YourModelFrom(instance=model_object) - обычно тот случай, когда вы хотите обновитьсуществующий объект экземпляра модели).Ссылки читайте в ModelFrom save() method

    Примечание:
    1 `ModelFrom` класс наследует ` BaseModelFrom` класс.Класс BaseModelFrom` наследует `BaseForm` class.
    2 Аргумент instance добавляется в ` BaseModelFrom` конструктор класса, когда мы назначаемобъект экземпляра класса модели для аргумента instance (следовательно, instance is not None), затем `BaseModelFrom` вызывает конструктор model_to_dict() и обновляет аргумент initial перед вызовом конструктора суперкласса.Проверьте def __init__ в классе BaseModelFrom

Затем явное присвоение начального значения полю (как показано в рассматриваемом коде OP) не действует,это связано с тем, что метод _clean_fields записан в классе BaseFrom.

Code Snip:

def _clean_fields(self):
    for name, field in self.fields.items():
        value = field.widget.value_from_datadict(
                self.data, self.files, self.add_prefix(name))
        try:
            if isinstance(field, FileField):
                initial = self.initial.get(name, field.initial) # <- Check
                value = field.clean(value, initial)
            else:

Согласно строке кода initial = self.initial.get(name, field.initial), если начальное значение для поля задано в initial dict, тогда значение, присвоенное field.initial, равно , а не используется.

[ОТВЕТ] :

Хотя, ответ @Daniel является совершенно правильным, но можно также использовать другой способ достижения того же эффекта, используя self.initial:

def __init__(self, *args, **kwargs):
    super(ArtefactForm, self).__init__(*args, **kwargs)
    self.initial['material'] = 'Test'

Попробуй !!

self.initial - это не что иное, как диктат, который мы передаем в качестве аргумента.Проверьте код __init__ в BaseForm:

class BaseForm(object):
    def __init__(........
                 ........):
        :
        self.prefix = prefix
        self.initial = initial or {}  # <-- Notice 
        self.error_class = error_class
        :

Примечание: я не нашел никакой документации, связанной с использованием начального атрибута, я просто исследовал базовый код и использовал его.

Редактировать: поведение, о котором сообщается в Вопросе, также задокументировано в Django Model

Динамические начальные значения

Форма.initial

Обратите внимание, что если Field определяет initial и , вы включаете initial при создании экземпляра формы, тогда последний initial будет иметь приоритет.В этом примере initial предоставляется как на уровне поля, так и на уровне экземпляра формы, и последний получает приоритет:

>>> from django import forms
>>> class CommentForm(forms.Form):
...     name = forms.CharField(initial='class')
...     url = forms.URLField()
...     comment = forms.CharField()
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
>>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="instance" />
<tr><th>Url:</th><td><input type="url" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>

PS:Кстати, пункт 2 в моих ответах говорит о разнице между аргументами initial и instance.Это еще один аргумент ключ-значение data - значения в этом триггере формируют проверки.Прочитайте это Разница между начальной формой и связанными данными Django? .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...