53👍
Try this:
def __init__(self, *args, **kwargs):
initial = kwargs.get('initial', {})
initial['material'] = 'Test'
kwargs['initial'] = initial
super(ArtefactForm, self).__init__(*args, **kwargs)
19👍
Old question but adding a descriptive answer as I believe it would be helpful for some new developer.
I also tried with
self
.base_fields
, but no effect: there is always the database-value displaying in the form. Any ideas?
If a form is “initialized” form, either:-
-
using
initial
argument (eg.YourModelFrom(initial={'filed1': variable})
— generally the case, when you want to pass dynamically calculated initial values for some fields). ReferenceSetting Initial Values
or
-
using
instance
argument (eg.YourModelFrom(instance=model_object)
— usually the case, when you wants to update an existing model instance object) . References read ModelFrom’ssave() method
Note:
1 `ModelFrom` class inherits `BaseModelFrom` class. The `BaseModelFrom` class inherits `BaseForm` class.
2 The argumentinstance
is added in `BaseModelFrom` class constructor, when we assign a model class instance object toinstance
argument (henceinstance is not None
) then `BaseModelFrom` constructor callsmodel_to_dict()
and updatesinitial
argument before to call super class constructor. Checkdef __init__
in BaseModelFrom class
Then assigning initial value to a field explicitly (as shown in OP’s code in question) don’t effect, this is due to the way _clean_fields
method is written in BaseFrom
class.
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:
According to code line initial = self.initial.get(name, field.initial)
, if initial value for field is given in initial
dict then value assigned to field.initial
is not used.
[ANSWER]:
Although, @Daniel answer is perfectly correct but one can also like another way to achieve same effect is using self.initial
:
def __init__(self, *args, **kwargs):
super(ArtefactForm, self).__init__(*args, **kwargs)
self.initial['material'] = 'Test'
Give it a try!!
self.initial
is nothing but it the dict we pass in argument. Check code __init__
in BaseForm
:
class BaseForm(object):
def __init__(........
........):
:
self.prefix = prefix
self.initial = initial or {} # <-- Notice
self.error_class = error_class
:
Note: I didn’t find any documentation related to use initial attribute, I just explored the base code and used it.
Edit: the behavior reported in Question is also documented in Django Model
Dynamic initial values
Form.initial
Note that if a
Field
definesinitial
and you includeinitial
when
instantiating the Form, then the latterinitial
will have precedence.
In this example,initial
is provided both at the field level and at
the form instance level, and the latter gets precedence:>>> 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: Btw, point 2 in my answers tell difference between initial
and instance
argument. Their is one more key-value argument data
– values in that triggers form validations. read this Difference between Django Form ‘initial’ and ‘bound data’?.
- [Django]-When should I use a custom Manager versus a custom QuerySet in Django?
- [Django]-User Registration with error: no such table: auth_user
- [Django]-Django migrations – workflow with multiple dev branches