Search code examples
pythondjangodjango-formsdjango-sessionsdjango-1.9

Django 1.9 using django sessions in two page forms


How can I use Django sessions to have a user be able to start a form on one page, and move to the next page and have them complete the form?

I have looked into pagination and wizard forms, but I don't get them at all.

When I have one page with a small portion of a model I'm using - in forms - and another page with the rest of the model - forms.py with the rest of the model info - I can use the first form perfectly.

But when I move to the next page, I get an error saying (1048, "Column 'user_id' cannot be null").

My best guess is to use Django sessions to fix this issue. I don't want the user to have to put in their username and password a second time to get this to work. Any ideas?

my models/forms.py:

class Contact(models.Model):
    user = models.OneToOneField(User)
    subject = models.CharField(max_length=100, blank=True)
    sender = models.EmailField(max_length=100, blank=True)
    message = models.CharField(max_length=100, blank=True)

    def __str__(self):
        return self.user.username


class UserForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model = Contact
        fields = ('username', 'password', 'email')


class ContactForm1(forms.Form):
    class Meta:
        model = Contact
        fields = ('subject', 'sender')


class ContactForm2(forms.Form):
    message = forms.CharField(widget=forms.Textarea)

    class Meta:
        model = Contact
        fields = ('message',)

views:

def contact(request):
    registered = False
    if request.method =='POST':
        user = UserForm(request.POST)
        contact = ContactForm1(request.POST)
        if user.is_valid() and contact.is_valid():
            user = user.save()
            user.set_password(user.password)
            user.save()
            contact = contact.save(commit=False)
            contact.user = user
            registered = True
    return render(request, 'mysite/contact.html', {'user': user, 'contact': contact, 'registered': registered})

def contact_second(request):
    if request.method =='POST':
        contact = ContactForm2(request.POST)
        if contact.is_valid():
            contact = contact.save(commit=False)
            contact.save()
    return render(request, 'mysite/contact_two.html', {'contact': contact}

Solution

  • I think it's a good idea to use sessions to store the forms because you don't want on each page to store the user input into the database because what if s/he change mind in the 3rd page and s/he wants to discard the registration or whatever it is?

    I think is better to store the forms in session until you get in the last page, you ensure that everything is valid and then save the data in the database.

    So let's say that the bellow code is in one of the view that will serve the first form/page. You retrieve the data from the POST request and you check if the given data are valid using the form.is_valid(), you then store the form.cleaned_data (which contains the user's validated data) to a session variable.

    form = CustomForm(request.POST)
    ...
    if form.is_valid():
        request.session['form_data_page_1'] = form.cleaned_data
    

    Note here that you may need to add code to redirect the user to the next page if form.is_valid() is true, something like this:

    if form.is_valid():
        request.session['form_data_page_1'] = form.cleaned_data
        return HttpResponseRedirect(reverse('url-name-of-second-page'))
    

    Then in any other view let's say in the view that is going to serve the second page you can retreive the from data from the first page like this:

    first_page_data = request.session['form_data_page_1']
    

    And you can do whatever you want with them as if it was after you executed the form.is_valid() in the first view.