Psyferre
Psyferre

Reputation: 135

Override values in Django ModelForm instance during get_form()

I have a model "SavedSearch" with a generic UpdateView. Each site user can have one Saved Search. When running a search on the site, I want to give them the ability to click a "Save this Search" button that will take them to the edit form for their current SavedSearch model and replace their values with the ones from their search (saved in request.session.params).

So, I'm trying to catch the bound form on the way to the template and replace some values without saving, so that the user has a chance to edit the options or change their mind and cancel.

I've tried updating the instance fields in get_form():

def get_form(self, form_class):
    form = super(SavedSearchUpdateView, self).get_form(form_class)
    # if request is coming from a search form "save" click,
    # replace form context data with options from search form.
    if self.request.GET.get('ss_override') and self.request.session.get('params', None):
        params = self.request.session["params"]
        if params.get('location', None): form.instance.location_keywords = params.get('location')
        # ... etc.

    return form

I've also tried passing request to the form's __init__ via get_form_kwargs() and then doing pretty much the same as above within the form's init. Both tactics result in no change whatsoever to the form data.

I also tried passing request to get_form_kwargs() and then in __init__:

def __init__(self, *args, **kwargs):
    request = kwargs.pop('request')

    super(DreamHomePreferenceForm, self).__init__(*args, **kwargs)

    # if request is coming from a property search form "save" click,
    # replace form context data with options from search form.
    if request.GET.get('ehf_override') and request.session.get('params', None):
        params = request.session["params"]
        new_data = {}
        if params.get('location', None): new_data['location_keywords'] = params.get('location')

        self.data = self.data.update(new_data)

This also yields no change in the form display. I also tried to override the data kwarg completely, in get_form_kwargs(), but then the form tries to validate right away and any fields not in the new data show errors.

If anyone can give a push in the right direction, I'd be grateful.

Upvotes: 6

Views: 3064

Answers (2)

tufelkinder
tufelkinder

Reputation: 1256

I believe the correct method is to use self.object per the documentation on UpdateView to access attributes about the object being edited. Then, you can set values on the form like this:

def get_form(self, form_class=None):
    form = super(UpdateView, self).get_form(form_class)
    form.fields['location'].queryset = Location.objects.filter(foo=self.object.foo)
    return form

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 599600

This is pretty hard to understand - it would have been helpful to have more details about the user flow.

But I think what you want to do is to provide initial data for the form, rather than changing field instances. This can be done by overriding the get_initial method of your view, to return a dictionary. This will be passed in to the form returned from get_form automatically, so there would be no need to override that method.

def get_initial(self):
    if self.request.GET.get('ehf_override') and self.request.session.get('params'):
        initial_data = {}
        ...
    else:
        initial_data = super(SavedSearchUpdateView, self).get_initial()
    return initial_data

Upvotes: 0

Related Questions