'django redirect to form view and autofill with previously entered values

I have following scenario.

  1. User fills out a form
  2. If the user clicks the "continue" button and the form is valid the user will be redirected to a summary view
  3. In the summary view the user checks the input again. He can either continue or go back.
  4. If he continues the data will be saved in the database, if he goes back he can edit the form.

Since in step 4 the user is at the view summary I have to redirect him to the home view. I don´t want the user to fill out the entire form again, the previously entered data should be autofilled if he goes back.

Something special: I am using django-tagify2 for one input in the form to get tags rather then text. If the user goes back the tags should be rendered correctly in the tagify specific form.

So here are my files:

home.html

{% extends "messenger/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="message-container">
    <form method="POST" autocomplete="off">
        {% csrf_token %}
        {{ form|crispy }}
        <button name="sendmessage" class="btn btn-outline-info" type="submit">Continue</button>
    </form>
    </div>
{% endblock content %}

summary.html

{% extends "messenger/base.html" %}
{% block content %}
    <h4>Zusammenfassung</h4>
    <p><b>Empfänger: </b>{{ receiver }}</p>
    <br>
    <p><b>Betreff: </b>{{ subject }}</p>
    <br>
    <p><b>Nachricht: </b>{{ message }}</p>
    <button><a href="/">Edit</a></button>
    <button><a href="/send_message">Continue</a></button>
{% endblock content %}

home view

@login_required(login_url='login')
def home(request):
    if request.method == 'POST' and 'sendmessage' in request.POST:
        message_form = MessageForm(request.POST)
        if message_form.is_valid():
            receiver_list = message_form['receiver'].value().split(';')
            subject = message_form['subject'].value()
            message = message_form['textmessage'].value()

            #create sessions and send data to next view
            session_receiver = receiver_list
            request.session['session_receiver'] = session_receiver
            session_subject = subject
            request.session['session_subject'] = session_subject
            session_message = message
            request.session['session_message'] = session_message


            return redirect('summary')




    else:
        message_form = MessageForm()

    return render(request, 'messenger/home.html', {'form': message_form})

summary view

def summary(request):
    receiver = request.session.get('session_receiver')
    subject = request.session.get('session_subject')
    message = request.session.get('session_message')

    return render(request, 'messenger/summary.html', {'receiver':receiver,
                                                      'subject':subject,
                                                      'message':message})

So what is the best way to do this? Can I use the session variables to set the fields in the form?

I don´t want to change the logic in the app. I want a home/summary/success view/template where I can loop as long is I want between home and summary until the user is happy with his entered form data



Solution 1:[1]

I played around with the session values and views and finally got a way to redirect to other views with prefilled form fields based on session values.

@login_required(login_url='login')
def home(request):
    if request.method == 'POST' and 'sendmessage' in request.POST:
        message_form = MessageForm(request.POST)
        if message_form.is_valid():
            ad_group = message_form['ad_group'].value().split(';')
            ad_user = message_form['ad_user'].value().split(';')
            subject = message_form['subject'].value()
            message = message_form['textmessage'].value()

            #create sessions and send data to next view
            session_ad_group = ad_group
            request.session['session_ad_group'] = session_ad_group
            session_ad_user = ad_user
            request.session['session_ad_user'] = session_ad_user
            session_subject = subject
            request.session['session_subject'] = session_subject
            session_message = message
            request.session['session_message'] = session_message

            return redirect('summary')

    else:
        if request.session.get('session_subject'):
            message_form = MessageForm(initial={'ad_group': request.session.get('session_ad_group'),
                                                'ad_user': request.session.get('session_ad_user'),
                                                'subject': request.session.get('session_subject'),
                                                'textmessage': request.session.get('session_message')})
            return render(request, 'messenger/home.html', {'form': message_form})
        else:
            message_form = MessageForm()

    return render(request, 'messenger/home.html', {'form': message_form})


def summary(request):
    ad_group = request.session.get('session_ad_group')
    ad_user = request.session.get('session_ad_user')
    subject = request.session.get('session_subject')
    message = request.session.get('session_message')

    if request.method == 'POST' and 'edit' in request.POST:
        message_form = MessageForm(initial={'ad_group':ad_group, 'ad_user': ad_user,
                                            'subject':subject, 'textmessage':message})
        return render(request, 'messenger/home.html', {'form': message_form})



    return render(request, 'messenger/summary.html', {'ad_group':ad_group,
                                                      'ad_user': ad_user,
                                                      'subject':subject,
                                                      'message':message})

Template

{% extends "messenger/base.html" %}
{% block content %}
    <h2>Zusammenfassung</h2>
    <div class="border-top pt-3">
        <p><b>AD-Gruppe: </b>{{ ad_group }}</p>
        <p><b>AD-User: </b>{{ ad_user }}</p>
        <br>
        <p><b>Betreff: </b>{{ subject }}</p>
        <br>
        <p><b>Nachricht: </b>{{ message }}</p>
        <div class="buttoncontainer">
            <form name="edit" action="" method="post">
                {% csrf_token %}
                <button class="btn edit_btn" formaction="{% url 'messenger-home' %}">Zurück</button>
            </form>
            <form name="senden" action="" method="post">
                {% csrf_token %}
                <button class="btn continue_btn" formaction="{% url 'send_messages' %}">Nachricht senden</button>
            </form>
        </div>
    </div>
{% endblock content %}

Solution 2:[2]

How about checking request.session when there is get request to home view? Then you can bind message_form = MessageForm() to session data.

You can check out htmx and django-htmx. You can do what you want easily without session by swapping HTML with context.

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 adama
Solution 2 Huy