Context dictionary not passing to template from CBV POST function

I have a generic CBV that allows users to upload a CSV file. The GET function of the CBV just displays the form for the upload. The POST function takes the CSV, parses it into useable data. After the CSV has been parsed, I want a page rendered that displays the data in an HTML list.

Here is my generic CBV for uploading and parsing

class timeEntry(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        return render(request, "timeEntryFile.html")

    def post(self, request, *args, **kwargs):
        context = {}
        csv_file_input = request.FILES["file_input"]
        rows = TextIOWrapper(csv_file_input, encoding="utf-8", newline="")
        for row in DictReader(rows):
            context_name = row['Textbox_1']
            start_date_formatted = datetime.strptime(row['PeriodFrom'], '%m/%d/%Y')
            end_date_formatted = datetime.strptime(row['PeriodTo'], '%m/%d/%Y')
            time_period_first_day = start_date_formatted  - timedelta(days=start_date_formatted.weekday() % 7)
            journal_name = row['Textbox_60']
            time_period = TimePeriod.objects.get(start_date=start_date_formatted, end_date=end_date_formatted)
            date = time_period_first_day + timedelta(days=int(row['Textbox_11']))
            approval_status = row['Textbox_32']
            customer = row['Textbox_42']
            project = row['Textbox_59']
            activity = row['Textbox_34'] + ' - ' + row['ActivityTxt'].split(' - ', 1)[1]
            line_property = 'Billable' if row['LinePropertyName'] == 'Billable' else 'Non billable'
            time_hour = float(row['Textbox_86'])
            context[context_name] = {'d365_journal_name': journal_name, 'time_period': time_period, 'date': date, 'approval_status': approval_status, 'customer': customer, 'project': project, 'activity': activity, 'line_property': line_property, 'time_hour': time_hour}
        return render(request, "timeEntryReview.html", context)

However, every time, the timeEntryReview.html template does not render the context.

Here is my html template:

{% extends 'base.html' %}
{% block nav_item_time_entry %}bg-indigo-500{% endblock nav_item_time_entry %}
{% load static %}
{% block content %}

<section>
    {% if messages %}
        <ul class="max-w-3xl mx-5 mb-4 px-9">
            {% for message in messages %}
            <li class="text-center py-2 px-5">{{ message|safe }}</li>
            {% endfor %}
        </ul>
    {% endif %} 
</section>

<main class="flex-1 overflow-x-hidden overflow-y-auto">
    <div class="container mx-auto px-6 py-8">

        <div class="flex flex-col mt-8">
            <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
                <div
                    class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200">
                    <table class="min-w-full">
                        <thead>
                            <tr>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Journal Num</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Time Period</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Date</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Approval Status</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Customer</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Project</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Activity</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Property</th>
                                <th
                                    class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
                                    Time</th>
                            </tr>
                        </thead>

                        <tbody class="bg-white">
                            {% for line in context %}
                                <tr>
                                    <td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
                                        <div class="flex items-center">
                                            <div class="ml-4">
                                                <div class="text-sm leading-5 font-medium text-gray-900">12</div>
                                            </div>
                                        </div>
                                    </td>
                                </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</main>


{% endblock content %}

(Note, right now I am just trying to get anything to show in the template so I do not have the entire table built out.)

Is it possible to pass the context from the render of the post function to the template or not?

Much thanks

You have:

but you don’t have a key in the context dict named context.

Since you’re inherting from View and not one of the more specific views, you can create anything for the context in post.

Thank you.

2 questions come to mind:

  1. How would I loop through my dict in the template then?
  2. Is there a better way to do what I am trying to achieve using one of the more specific views?

I’m sorry, I must confess that I can’t really figure out what you’re trying to do here.

In general, the context is a dict. You reference the members of the dict using the double-brace (e.g. {{ some_key }}) notation. That key can be just about any object or data structure such as a list, dict, queryset, set, etc.

The best I can suggest at the moment is that you review the docs about variables in templates in the docs at Templates | Django documentation | Django, along with the section on variables at The Django template language | Django documentation | Django

I guess then my question boils down to how would I loop through a dictionary like this (which is what I am passing to the template) in my HTML template?

{
    'day_2': {
        'journal_name': 'PJT-002094',
        'time_period': < TimePeriod: 02 - 01 - 2023 - 02 - 05 - 2023 > ,
        'date': datetime.datetime(2023, 2, 1, 0, 0),
        'approval_status': 'Draft',
        'customer': 'Customer 1, LLC',
        'project': 'Implementation',
        'activity': 'Implementation #1',
        'line_property': '4525',
        'time_hour': 1.0
    },
    'day_6': {
        'journal_name': 'PJT-002094',
        'time_period': < TimePeriod: 02 - 01 - 2023 - 02 - 05 - 2023 > ,
        'date': datetime.datetime(2023, 2, 5, 0, 0),
        'approval_status': 'Draft',
        'customer': 'Customer 2, LLC',
        'project': 'Assess',
        'activity': 'Assess #1',
        'line_property': '9283',
        'time_hour': 1.0
    }
}

My understanding was that when I pass this dict called “context” that I could loop through each nested dict.

EDIT: Or is there a better way to structure my data to loop through it in a django template when passing it as context?

You can - see the example in the Behind the scenes example at the second link above.
The issue is that you didn’t pass a dict called context. The dict named context is the context, not something in the context.

It’s possible that there is. That depends upon what you’re trying to produce in your template.

If I understand correctly, the issue is that I am trying to loop through a dict called context, but the dict I am passing does not have a key called context. Is that correct?

If so, how would I give the “parent” dict that has all the nested dicts the name “context”? Currently I am just adding dicts to a “parent” dict (see my above example).

100% correct.

My suggestion is to change the dict that you are creating with this data to a different name - it’s not required, but it will help avoid confusion. For my purpose here, I’m going to call it “data”. You will also still have your dict named context, but you’re not going to put anything in it (yet).

After data has been fully populated, add it to your context dict. e.g. context['data'] = data. You can now do whatever you want with the context variable named data. For example, if you were to render it as {{ data }}, you should see everything that you accumulated from your file.

1 Like

That worked, thank you