views:

647

answers:

2

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?

A: 

Is EntryFormSet a modelform or a modelformset?

jpic
This is not an answer - it should be a comment on the question. Please delete this answer and add your request for clarification to the question.
Vinay Sajip
Not only this is a pragmatic answer "are you sure that you are using a modelformset which should do what you want for you" but also i can't comment the question with less than 50 points.
jpic
It's a modelformset.
Matt Hampel
A: 

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).

jdl2003