You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中将Excel或CSV文件转换为HTML表格?

Hey there! I totally get where you're coming from—manually iterating through Excel/CSV cells with openpyxl or xlrd can feel super tedious, especially when all you want to do is show the data in a template. Good news: there are way cleaner ways to handle this, and my go-to tool for this kind of task is pandas—it’s designed exactly for simplifying table data workflows like this.

Here’s how to implement this smoothly:

First, install the necessary packages (pandas handles the heavy lifting, and we need extra libraries for Excel support):

pip install pandas openpyxl xlrd

Next, update your Django view to use pandas for reading the uploaded file and preparing data for the template:

import pandas as pd
from django.shortcuts import render

def home(request):
    if request.method == 'POST':
        uploaded_file = request.FILES['my_excel']
        file_ext = uploaded_file.name.split('.')[-1].lower()
        
        try:
            # Read the file based on its extension
            if file_ext in ['xls', 'xlsx']:
                df = pd.read_excel(uploaded_file)  # Reads the first sheet by default
            elif file_ext == 'csv':
                # Adjust encoding if your CSV uses something like GBK instead of UTF-8
                df = pd.read_csv(uploaded_file, encoding='utf-8')
            else:
                return render(request, 'demo/index.html', {'error': 'Only Excel (.xls/.xlsx) or CSV files are supported.'})
            
            # Option 1: Convert to lists for manual template rendering (great for custom styling)
            table_headers = df.columns.tolist()
            table_data = df.values.tolist()
            
            # Option 2: Generate a ready-to-use HTML table (quickest for basic display)
            html_table = df.to_html(classes='table table-striped', index=False)
            
            # Pass data to the template
            context = {
                'headers': table_headers,
                'data': table_data,
                'html_table': html_table,
            }
            return render(request, 'demo/index.html', context)
        
        except Exception as e:
            return render(request, 'demo/index.html', {'error': f'Failed to read file: {str(e)}'})
    
    # For GET requests, return empty template
    return render(request, 'demo/index.html')

Now, update your template (demo/index.html) to display the data:

You can choose either option based on how much control you want over the table styling:

Option 1: Manual table rendering (full control)

{% if error %}
<div class="alert alert-danger">{{ error }}</div>
{% endif %}

{% if headers and data %}
<h3>Uploaded Data</h3>
<table class="table table-bordered">
    <thead>
        <tr>
            {% for header in headers %}
            <th>{{ header }}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {% for row in data %}
        <tr>
            {% for cell in row %}
            <td>{{ cell }}</td>
            {% endfor %}
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endif %}

Option 2: Render the auto-generated HTML table (quick and easy)

{% if error %}
<div class="alert alert-danger">{{ error }}</div>
{% endif %}

{% if html_table %}
<h3>Uploaded Data</h3>
{{ html_table|safe }}
{% endif %}

A few quick notes:

  • File size limits: Django defaults to a 2.5MB upload limit. If you need to handle larger files, adjust FILE_UPLOAD_MAX_MEMORY_SIZE in your settings.py.
  • Encoding: If your CSV files use non-UTF-8 encoding (like GBK for Chinese), update the encoding parameter in pd.read_csv() to match.
  • Customization: If you need advanced cell formatting (like highlighting specific rows/columns), you can still use openpyxl/xlrd for that part, but pandas will handle the bulk data reading to save you time.

内容的提问来源于stack exchange,提问作者Di437

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:06:12