【问题标题】:Attribute Error in Uploading Excel File to Django将 Excel 文件上传到 Django 时出现属性错误
【发布时间】:2019-03-03 18:37:32
【问题描述】:

我无法将 excel 文件上传到我的 django 应用程序。这是一个非常简单的应用程序,它应该允许用户上传一个包含 3 列的 excel 文件。应用程序将读取该文件的内容并将其处理成一堆计算

这是我的 forms.py

class InputForm(forms.Form):
FileLocation = forms.FileField(label='Import Data',required=True,widget=forms.FileInput(attrs={'accept': ".xlsx"}))

settings.py

FILE_UPLOAD_HANDLERS = ["django_excel.ExcelMemoryFileUploadHandler",
                    "django_excel.TemporaryExcelFileUploadHandler"]

views.py

import xlrd
from django.shortcuts import render_to_response, render
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.template.context_processors import csrf
from io import TextIOWrapper
from WebApp.forms import *
from django.core.mail import send_mail
from django.utils.safestring import mark_safe
from django.db import connection
import os
import csv
def analyze(request):
     if request.method == 'POST':
        form = InputForm(request.POST,request.FILES['FileLocation'])


     if form.is_valid():
         book = xlrd.open_workbook(request.FILES('FileLocation'))
         for sheet in book.sheets():
             number_of_rows = sheet.nrows
             number_of_columns = sheet.ncols
             print(number_of_rows)

我在表单中上传文件,它给了我一个错误:

    AttributeError at /app/analyze/

    'ExcelInMemoryUploadedFile' object has no attribute 'get'

Request Method:     POST
Request URL:    http://127.0.0.1:8000/data/analyze/
Django Version:     1.11
Exception Type:     AttributeError
Exception Value:    

Exception Location:     C:\Python36\lib\site-packages\django\forms\widgets.py in value_from_datadict, line 367
    Python Executable:  C:\Python36\python.exe
    Python Version:     3.6.4

我还可以使用以下 views.py 代码成功上传 .csv 文件:

def analyze(request):
    c={}
    context = RequestContext(request)
    c.update(csrf(request))
    abc=['a','b','c']
    if request.method == 'POST':
        form = InputForm(request.POST,request.FILES)
        dataType = request.POST.get("DataType")
        print(dataType)
        if form.is_valid():
            cd = form.cleaned_data            #print (cd)

            a =  TextIOWrapper(request.FILES['FileLocation'].file,encoding='ascii',errors='replace')

        #print (request.FILES.keys())
        data = csv.reader(a)
        row1csv = next(data)
        region = row1csv[0]
        metric = row1csv[2]

我尝试过 django-excel 时出现同样的错误。

【问题讨论】:

  • 我认为显示InputForm 的代码会有所帮助,看来这就是问题所在。
  • 这个代码也是错误的:book = xlrd.open_workbook(request.FILES('FileLocation')),它应该是request.FILES['FileLocation']的方括号。但这是一个不同的错误,它不会在表单的小部件中产生错误。
  • 感谢您的审阅。 (1) 你是指 InputForm 的 HTML 代码吗? (2) 我尝试在语句中将我的代码更改为request.FILES['FileLocation']。同样的错误。
  • 是的,正如我所说,您的错误与方括号无关,但是在修复第一个错误后您会收到一个新错误 :-) 对不起,我的错,错过了 InputForm代码在顶部。
  • 您没有正确初始化表单:form = InputForm(request.POST, request.FILES['FileLocation']) 应该是 form = InputForm(request.POST, request.FILES)。这里需要一个字典 (QueryDict),而不是上传的文件。

标签: django excel python-3.x file-upload


【解决方案1】:

您正确地为 .CSV 案例初始化表单,但不是在 Excel 案例中:

form = InputForm(request.POST, request.FILES)

不要使用request.FILES['FileLocation'] 进行初始化,因为这会将错误的类型传递给表单。它期待上传文件的 MultiValueDict,而不是单个上传文件。这就是调用 get 时失败的原因。

接下来,您不能将ExcelInMemoryUploadedFile 传递给xlrd.get_workbook()。您需要先将文件保存到磁盘,然后将其路径传递给get_workbook() 方法。 django-excel 的documentation 提供了一些更简单的方法:

book = request.FILES['FileLocation'].get_book()  # note the square brackets!

或直接访问工作表:

sheet = request.FILES['FileLocation'].get_sheet('sheet1')

【讨论】:

  • 我在request.FILES 中尝试了该更改。我得到了下一个错误:expected str, bytes or os.PathLike object, not MultiValueDict
  • 什么??这很奇怪。它在哪一行给出这个错误?你能显示完整的痕迹吗?我希望在您的代码中的不同位置出现此类错误,可能是 book = xlrd.open_workbook(request.FILES['FileLocation'])
  • book = xlrd.open_workbook(request.FILES) C:\Python36\lib\site-packages\xlrd\__init__.py in open_workbook with open(filename, "rb") as f: 我认为错误在xlrd.openworkbookfile_contents filename {'FileLocation': <ExcelInMemoryUploadedFile: filename.xlsx (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)>} <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
  • xlrd.open_workbook() 需要一个路径或字节流,您不能将它传递给您的 request.FILESrequest.FILES['FileLocation']。检查 xlrd 的文档。将文件保存到先上传的磁盘,然后将文件路径传递给xlrd.open_workshop()
  • ExcelMixin好像有个函数get_book()get_sheet(),所以可以直接在上传的文件对象上获取book = request.FILES['FileLocation'].get_book()。见here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 2021-11-08
  • 2018-01-16
  • 2022-01-23
  • 2010-10-08
  • 1970-01-01
  • 2021-01-05
相关资源
最近更新 更多