Showing the uploaded csv file on Django template

I have a project that accepts an uploaded .csv file and shows it on the admin via the models.py. What I want to happen is to show these uploaded .csv file on the template.

my views are:

def data_upload(request):
    template = "home.html"

    if request.method == 'GET':
        return render(request, template)

    csv_file = request.FILES['file']
    if not csv_file.name.endswith('.csv'):
        messages.error(request, 'Please upload a .csv file.')

    data_set = csv_file.read().decode('ISO-8859-1')
    io_string = io.StringIO(data_set)
    next(io_string)
    for column in csv.reader(io_string, delimiter=','):
        _, created = Table.objects.update_or_create(
            page=column[0], 
            keyword=column[1], 
            interval=column[2], 
            email=column[3], 
            notes=column[4], 
            billing=column[5],
        )
    context = {
    'tables': Table.objects.all()
    }
    return render(request, template, context)

The views are already working when I upload the .csv file.

On the home.html file, this is what I did:

                       <table class="table table-condensed">
                        <thead>
                        <tr>
                            <th>...</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr>
                            <th class="center-align" scope="row"><i class="small material-icons green">check</i></th>
                            {% for t in tables %}
                            <td class="center-align">{{t.page}}</td>
                            <td class="center-align">{{t.keyword}}</td>
                            <td class="center-align">{{t.interval}}</td>
                            <td class="center-align">{{t.email}}</td>
                            <td class="center-align">{{t.notes}} </td>
                            <td class="center-align">{{t.billing}}</td>
                            {% endfor %}
                        </tr>
                       </table>

How do I properly iterate on the template to show what I uploaded on my html file?

Upvotes: 0

Views: 2567

Answers (1)

Matthew Gaiser
Matthew Gaiser

Reputation: 4763

If you don't upload a file, the code doesn't go past the first return

Unless a CSV is uploaded, the code stops here and thus no data is sent to the template. That is why {{ tables }} returned blank. While the data is in the database, the {{tables}} in the template is never populated in this render.

    if request.method == 'GET':
        return render(request, template)

Only if a CSV is actually uploaded does this output anything and fill out the table. Any request which is not from the big green upload button does not run code which would give the {{tables}} in the template any data.

The code below only runs if the CSV is uploaded that time.

csv_file = request.FILES['file']
    if not csv_file.name.endswith('.csv'):
        messages.error(request, 'Please upload a .csv file.')

    data_set = csv_file.read().decode('ISO-8859-1')
    io_string = io.StringIO(data_set)
    next(io_string)
    for column in csv.reader(io_string, delimiter=','):
        _, created = Table.objects.update_or_create(
            page=column[1], 
            keyword=column[2], 
            interval=column[3], 
            email=column[4], 
            notes=column[5], 
            billing=column[6],
        )
    context = {
        'tables': Table.objects.all()
    }
    print(Table.objects.all())
    return render(request, template, context)

Does this work?

context = {'tables': Table.objects.all()}

This assumes that the only elements in Table are elements from the CSV.

Edit, how to fix the template

Change this

                            <tr>
                                <th class="center-align" scope="row"><i class="small material-icons green">check</i></th>
                                {% for t in tables %}
                                <td class="center-align">{{t.page}}</td>
                                <td class="center-align">{{t.keyword}}</td>
                                <td class="center-align">{{t.interval}}</td>
                                <td class="center-align">{{t.email}}</td>
                                <td class="center-align">{{t.notes}} </td>
                                <td class="center-align">{{t.billing}}</td>
                                {% endfor %}
                            </tr>
{% for t in tables %}
                            <tr>
                                <th class="center-align" scope="row"><i class="small material-icons green">check</i></th>

                                <td class="center-align">{{t.page}}</td>
                                <td class="center-align">{{t.keyword}}</td>
                                <td class="center-align">{{t.interval}}</td>
                                <td class="center-align">{{t.email}}</td>
                                <td class="center-align">{{t.notes}} </td>
                                <td class="center-align">{{t.billing}}</td>

                            </tr>
                            {% endfor %}

to this in home.html

Basically, make the <tr></tr> tags go inside the for loop and not outside.

Upvotes: 3

Related Questions