79👍
If you made the same mistake as me, you’ve slightly mistaken the documentation.
When I first saw this example…
formset = ArticleFormSet(initial=[
{'title': 'Django is now open source',
'pub_date': datetime.date.today(),}
])
I assumed that each form is given the same set of initial data based on a dictionary.
However, if you look carefully you’ll see that the formset is actually being passed a list of dictionaries.
In order to set different initial values for each form in a formset then, you just need to pass a list of dictionaries containing the different data.
Formset = formset_factory(SomeForm, extra=len(some_objects)
some_formset = FormSet(initial=[{'id': x.id} for x in some_objects])
11👍
You need to use the technique described in this post in order to be able to pass parameters in. Credit to that author for an excellent post. You achieve this in several parts:
A form aware it is going to pick up additional parameters
Example from the linked question:
def __init__(self, *args, **kwargs):
someeobject = kwargs.pop('someobject')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["somefield"].queryset = ServiceOption.objects.filter(
somem2mrel=someobject)
Or you can replace the latter code with
self.fields["somefield"].initial = someobject
Directly, and it works.
A curried form initialisation setup:
formset = formset_factory(Someform, extra=3)
formset.form = staticmethod(curry(someform, somem2mrel=someobject))
That gets you to passing custom form parameters. Now what you need is:
A generator to acquire your different initial parameters
I’m using this:
def ItemGenerator(Item):
i = 0
while i < len(Item):
yield Item[i]
i += 1
Now, I can do this:
iterdefs = ItemGenerator(ListofItems) # pass the different parameters
# as an object here
formset.form = staticmethod(curry(someform, somem2mrel=iterdefs.next()))
Hey presto. Each evaluation of the form
method is being evaluated in parts passing in an iterated parameter. We can iterate over what we like, so I’m using that fact to iterate over a set of objects and pass the value of each one in as a different initial parameter.
- [Django]-Django: How to get language code in template?
- [Django]-Django get the static files URL in view
- [Django]-Cleanest & Fastest server setup for Django
3👍
Building on Antony Vennard’s answer, I am not sure what version of python/django he is using but I could not get the generator to work in the curry method either. I am currently on python2.7.3 and django1.5.1. Instead of using a custom Generator, I ended up using the built-in iter()
on a list of things to create an iterator and passing the iterator itself in the curry method and calling next()
on it in the Form
__init__()
. Here is my solution:
# Build the Formset:
my_iterator = iter(my_list_of_things) # Each list item will correspond to a form.
Formset = formset_factory(MyForm, extra=len(my_list_of_things))
Formset.form = staticmethod(curry(MyForm, item_iterator=my_iterator))
And in the form:
# forms.py
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
# Calling next() on the iterator/generator here:
list_item = kwargs.pop('item_iterator').next()
# Now you can assign whatever you passed in to an attribute
# on one of the form elements.
self.fields['my_field'].initial = list_item
Some Key things I found were that you need to either specify an ‘extra’ value in the formset_factory
or use the initial
kwarg on the formset to specify a list that corresponds to the list you pass to the iterator (In above example I pass the len()
of the my_list_of_things list to ‘extra’ kwarg to formset_factory). This is necessary to actually create a number of forms in the formset.
- [Django]-Django rest framework: query parameters in detail_route
- [Django]-CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False
- [Django]-Trying to parse `request.body` from POST in Django
2👍
I had this problem and I made a new widget:
from django.forms.widgets import Select
from django.utils.safestring import mark_safe
class PrepolutatedSelect(Select):
def render(self, name, value, attrs=None, choices=()):
if value is None: value = ''
if value == '':
value = int(name.split('-')[1])+1
final_attrs = self.build_attrs(attrs, name=name)
output = [u'<select%s>' % flatatt(final_attrs)]
options = self.render_options(choices, [value])
if options:
output.append(options)
output.append('</select>')
return mark_safe(u'\n'.join(output))
Maybe this will work for you too.
- [Django]-How to compare dates in Django templates
- [Django]-Simple Subquery with OuterRef
- [Django]-OperationalError, no such column. Django
0👍
formset = BookFormset(request.GET or None,initial=[{'formfield1': x.modelfield_name1,'formfield2':x.modelfield_name2} for x in model])
formfield1,formfield2 are the names of the formfields.
modelfield_name1,modelfield_name2 are the modal field names.
model is name of your modal class in models.py file.
BookFormset is the form or formset name which is defined in your forms.py file
- [Django]-How to specify an IP address with Django test client?
- [Django]-Django get a QuerySet from array of id's in specific order
- [Django]-Django ModelForm for Many-to-Many fields
0👍
I countered this problem when I created one form for both creating and updating, and the following worked for me. For the form
class SomeForm(forms.ModelForm):
class Meta:
model = SomeModel
fields = ['some_field']
def __init__(self, *args, **kwargs):
# Check if an instnace exists, then set the initial values
if 'instance' in kwargs:
kwargs['initial'] = {'some_field': kwargs['instance'].some_field}
super().__init__(*args, **kwargs)
........
For the update view, I did the following:
FormSet = modelformset_factory(
SomeModel, form=SomeForm)
formset = FormSet(queryset=some_qs, data=request.POST or None)
- [Django]-Django – Circular model import issue
- [Django]-How do I deploy Django on AWS?
- [Django]-'function' object has no attribute 'as_view'