'Django - Adding initial value to a formset

I have a many-to-many relationship between two classes (Lesson and Student), with an intermediary class (Evaluation).

I am trying to set up a form which will allow me to add a lesson with students and the related evaluation data. I can get all of the fields I want to display correctly, however I also need to set an initial value behind the scenes (the current user), as it does not make sense to have it in the form.

I have tried following the docs but I think I have a syntax error in the way I am passing the data to the formset.

The error I receive is as follows:

__init__() got an unexpected keyword argument 'initial'

My actual view (with my attempt at adding the initial data removed) looks like this:

def addlesson(request):
LessonFormset = inlineformset_factory(Lesson, Evaluation, exclude=('user',), max_num=5)
if request.method == 'POST':
    lesson = Lesson(user=request.user)
    form = LessonForm(request.POST, instance=lesson, user = request.user)
    formset = LessonFormset(request.POST, instance = lesson)
    if form.is_valid() and formset.is_valid():
        form.save()
        formset.save()
        return HttpResponseRedirect("/")
else:
    form = LessonForm(user = request.user)
    formset = LessonFormset()
return render_to_response("addlesson.html", {
    'form': form,
    'formset' : formset,
}, context_instance=RequestContext(request))

Could anyone show me to correct syntax to use to set the current user in the formset? This is what I had before but it was giving me the error at the start of my post:

initial={'user': request.user},

Any advice appreciated

Thanks



Solution 1:[1]

It's not clear to me why you are using a formset when it looks like you only want to add one row. A regular form would have been how I would do it if there was only one row. But, here's how I set the default value in a formset.

I exclude the field, just like you already have in your code. Then:

if form.is_valid() and formset.is_valid():
    form.save()
    models = formset.save(commit=False)
    for i in models:
        i.user = request.user
        i.save()
    return HttpResponseRedirect("/")

Solution 2:[2]

I tried Umang's answer and it didn't work good for when you want to change a value with a specific index. When you save the formset it will change the values that was changed.

But if you change models = formset.save(commit=False) to models = formset

and then you also need to change i.user = request.user to i.instance.user = request.user

 if form.is_valid() and formset.is_valid():
        form.save()

        # changed to formset instead of formset.save(commit=False)
        models = formset

        for model in models:
           
            # changed to i.instance.user instead of i.user, except renamed i to model.
            model.instance.user = request.user

            model.save()

            # save the formset
            formset.save()

        return HttpResponseRedirect("/")

Now when you want to change an index it will include all the forms, not only the ones that was changed when you save.

Example:

views.py

if form.is_valid() and formset.is_valid():
        form.save()

        models = formset
        index = 0
           
        # This will only change the first form in the formset.
        models[index].instance.user = request.user

        models.save()

        formset.save()
        return HttpResponseRedirect("/")

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Umang
Solution 2 AnonymousUser