9

I have what I think should be a simple problem. I have an inline model formset, and I'd like to make a select field have a default selected value of the currently logged in user. In the view, I'm using Django's Authentication middleware, so getting the user is a simple matter of accessing request.user.

What I haven't been able to figure out, though, is how to set that user as the default selected value in a select box (ModelChoiceField) containing a list of users. Can anyone help me with this?

Jeff
  • 14,831
  • 15
  • 49
  • 59

3 Answers3

6

This does the trick. It works by setting the initial values of all "extra" forms.

formset = MyFormset(instance=myinstance)
user = request.user
for form in formset.forms:
    if 'user' not in form.initial:
        form.initial['user'] = user.pk
Rune Kaagaard
  • 6,643
  • 2
  • 38
  • 29
5

I'm not sure how to handle this in inline formsets, but the following approach will work for normal Forms and ModelForms:

You can't set this as part of the model definition, but you can set it during the form initialization:

def __init__(self, logged_in_user, *args, **kwargs):
    super(self.__class__, self).__init__(*args, **kwargs)
    self.fields['my_user_field'].initial = logged_in_user

...

form = MyForm(request.user)
Billy Herren
  • 671
  • 5
  • 4
  • Not sure how this would work with the inline formset. I'm using inlineformset_factory to create my formset and passing it the form class, not an instance. So I'm not directly instantiating a form object anywhere and don't know how I'd pass it that constructor parameter. – Jeff Oct 01 '09 at 00:06
  • Hmmm... I believe ModelForms will take the 'default' value, won't they? And standard form fields use initial as you show, but as far as I know there's no reason to go super() on it. – monkut Oct 01 '09 at 08:02
  • This is great! I was looking for a way to send data from the form to the view so that I can send status that will be displayed using the messages framework. In the form I used the initial keyword, and then in the view I did this on validate: cur_key_status = form.cleaned_data['key_status'] messages.success(request, cur_key_status) – radtek Jan 28 '14 at 15:00
0

I'm using Rune Kaagaard's idea above, except I noticed that formsets provide an extra_forms property: django.forms.formsets code

@property
def extra_forms(self):
    """Return a list of all the extra forms in this formset."""
    return self.forms[self.initial_form_count():]

So, sticking with the example above:

formset = MyFormset(instance=myinstance)
user = request.user
for form in formset.extra_forms:
    form.initial['user'] = user.pk

Saves having to test any initial forms, just provide default for extra forms.

Chris McGinlay
  • 285
  • 2
  • 10