Search code examples
djangodjango-viewsdjango-formsdjango-templatesdjango-messages

Is there a special way of adding Django message to current template with multiple forms and calls to same page?


I have a message template:

messages.html
{% if messages %}
  <ul class="messages">
    {% for message in messages %}
        <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
            {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
            {{ message | safe }}
        </li>
    {% endfor %}
  </ul>
{% endif %}

that I include in my templates:

add_recipient.html
{% block content %}
    {% include 'myapp/messages.html' %}
    <div class="doc">
        <h2>Add Recipient</h2>
        <a class="btn btn-dark btn-lg" href="{% url 'myapp:recipient_list' 'A' %}">Back To List</a>
        <div class="form">
            <form method="post">
                {% csrf_token %}
                <table class="form form-table" style="font-size: x-large">
                    {{ recipient }}
                    {{ address }}
                    {{ demographics }}
                    {% if person_forms %}
                        {{ person_forms }}
                    {% endif %}
                </table>
                <div class="row d-flex justify-content-center m-4">
                    <button class="btn btn-primary btn-lg " type="submit">Add Recipient</button>
                </div>

            </form>
        </div>
    </div>

{% endblock content %}

and:

edit_recipient.html
{% block content %}
    {% include 'myapp/messages.html' %}
    <div class="doc">
        <h2>Edit Recipient Details</h2>
        <div class="container-fluid m-0">
            <div class="row ">
                <div class="col-lg">
                    <a class="btn btn-dark btn-lg" href="{% url 'myapp:recipient_detail' recipient_id=recipient_id back_to=back_to %} ">BACK</a>
                </div>
            </div>
        </div>
        <div class="d-flex flex-row">
            <div class="d-flex flex-column mx-auto" >
                <form method="post">
                    {% csrf_token %}
                    <table class="form form-table" style="font-size: x-large">
                        {{ recipient_form }}
                        {{ address_form }}
                        {{ demo_form}}
                        {{ formset }}
                    </table>
                    <button class="btn btn-lg btn-primary" type="submit">Submit</button>
                </form>
            </div>
        </div>
    </div>
{% endblock content %}

and I add it in the view like this:

add_recipient(request):
# in request.POST
                if person_forms.is_valid():

                    if get_total_num_forms(person_forms, operator.gt, 17) == demo_form_data[0]:
                        # Save forms
                        persons = person_forms.save(commit=False)
                        address.save()

                        # Apply address_id to and save recipient
                        recipient.recipient_address_id = address.id
                        recipient.phone = new_phone_number
                        recipient.save()
                        # Apply recipient_id to demo
                        demo.recipient_id = recipient.id
                        demo.save()

                        for person in persons:
                            person.recipient_id = recipient.id
                            person.save()

                        return redirect('myapp:recipient_list', 'A')

                    message = 'Form ages are WRONG!'
                    messages.error(request, message)

                    return render(request=request, template_name=template, context=context_dict)

                # Redirect back to add_recipient with forms
                return render(request=request, template_name=template, context=context_dict)
      

and

view edit_recipient
# in request.POST
 if demo_form_data[2] == len(formset):
    if check_ages_with_demographics(formset, demo_form_data):  # Forms where added and now need to be saved!!!!!!!!!
        # Need to check forms and save all
        update_object(recipient_form, recipient)
        update_object(AddressForm(request.POST or None), obj_models[1])
        update_object(DemographicsForm(request.POST or None), obj_models[2])
        # Need to check if adult and child forms match demo nums
        for i in range(len(formset)):
            if i < len(obj_models[3]):
                update_object(formset[i], obj_models[3][i])
            else:
                person = formset[i].save(commit=False)
                person.recipient_id = recipient_id
                person.save()

         return redirect('myapp:recipient_detail',
                          recipient_id=recipient.id,
                          back_to=back_to,)
    else:
        message = 'Added form age incorrect.'
        messages.error(request, message)
        forms = [recipient_form, address_form, demo_form, formset]
        return render(request=request, template_name=template,
                      context=get_render_context(form_names=form_names, forms=forms, kwargs=kwargs))
  

My problem is the message shows on add_recipient when the user inputs the wrong age for the form and it is still on the form page so they can fix it. But the edit page won't show the message, and yet when I back up a couple pages to any other page that includes the message template it shows there.

I realize this is not the entire view function but the implementation is the same as far as I can tell. The edit_recipient page is doing what it is supposed to by clearing form data and redisplaying the page to allow the user to fix form values but it is not showing the message. Any help is much appreciated!

I tried adding the code directly to the edit_recipient.html instead of including it and that didn't work. I even commented out the other templates include of the message.html and that didn't work either. I am trying to validate the form by age because I need to keep track of children and adults. So, if the user is adding an adult to demographics, after submit it adds another form for person with age, race, and gender, Then after submit again it checks to make sure new person is of adult age or vice versa. Forms are actually working as intended just not the message on the one page.


Solution

  • based on what you provided, the "edit_recipient.html" page might not have the necessary context data to display the messages. you should make sure to pass the messages context data to template as well.

    in view function for "edit_recipient" make sure to pass the message context data when rendering the template

    your views.py should looks like this:

    from django.contrib import messages
    
    def edit_recipient(request):
    
    
        if demo_form_data[2] == len(formset):
            if check_ages_with_demographics(formset, demo_form_data):
                # your logic
    
            else:
                message = 'Added form age incorrect.'
                messages.error(request, message)
                forms = [recipient_form, address_form, demo_form, formset]
                context_dict = get_render_context(form_names=form_names, forms=forms, kwargs=kwargs)
    
                # Pass the messages context data to the template
                context_dict['messages'] = messages.get_messages(request)
    
                return render(request=request, template_name=template, context=context_dict)
    
    def add_recipient(request):
    
        if person_forms.is_valid():
            if get_total_num_forms(person_forms, operator.gt, 17) == demo_form_data[0]:
                # your logic goes here again
    
            else:
                message = 'Form ages are WRONG!'
                messages.error(request, message)
    
                # Pass the messages context data to the template
                context_dict['messages'] = messages.get_messages(request)
    
                return render(request=request, template_name=template, context=context_dict)
    

    now both functions should be able to display the messages just make sure that the "edit_recipient.html" also rendering the messages by using:

    {% include 'myapp/messages.html'%}
    

    I hope this helps you.