Reputation: 5237
I get data in from POST and validate it via this standard snippet:
entry_formset = EntryFormSet(request.POST, request.FILES, prefix='entries')
if entry_formset.is_valid():
....
The EntryFormSet modelform overrides a foreign key field widget to present a text field. That way, the user can enter an existing key (suggested via an Ajax live search), or enter a new key, which will be seamlessly added.
I use this try-except block to test if the object exists already, and if it doesn't, I add it.
entity_name = request.POST['entries-0-entity']
try:
entity = Entity.objects.get(name=entity_name)
except Entity.DoesNotExist:
entity = Entity(name=entity_name)
entity.slug = slugify(entity.name)
entity.save()
However, I now need to get that entity
back into the entry_formset
. It thinks that entries-0-entity
is a string (that's how it came in); how can I directly access that value of the entry_formset
and get it to take the object reference instead?
Upvotes: 1
Views: 1451
Reputation: 878
I would suggest writing a helper factory function for your form set so that you can customize the display widget according to the data. Something like the following:
def make_entry_formset(initial_obj=None, custom_widget=forms.Textarea):
# these will be passed as keyword arguments to the ModelChoiceField
field_kwargs={'widget': custom_widget,
'queryset': Entity.objects.all()}
if initial_obj is not None:
field_kwargs.update({'initial': initial_obj})
class _EntryForm(forms.ModelForm):
entity = forms.ModelChoiceField(**field_kwargs)
class Meta:
model = Entry
return modelformset_factory(Entry, form=_EntryForm)
Then in your view code you can specify the widget you want and whether to bind to an initial Entity
object. For the initial rendering of the formset, where you just want a Textarea
widget and no initial choice, you can use this:
formset_class = make_entry_formset(custom_widget=forms.Textarea)
entry_formset = formset_class()
Then if you want to render it again (after the is_valid()
block) with the Entity
object already defined, you can use this:
formset_class = make_entry_formset(initial_obj=entity,
custom_widget=forms.HiddenInput)
entry_formset = formset_class(request.POST, request.FILES)
You can use any widget you like, of course, but using a HiddenInput
would prevent the end user from interacting with this field (which you seem to want to bind to the entity
variable you looked up).
Upvotes: 2