Mea*_*rdo 27 python django iterator python-3.x
我正在尝试导入CSV文件,使用表单从客户端系统上传文件.收到文件后,我将采取部分内容并在我的应用中填充模型.但是,当我继续迭代上传文件中的行时,我得到一个"迭代器应该返回字符串,而不是字节"错误.我花了好几个小时尝试不同的东西并阅读我能找到的所有东西,但似乎无法解决它(注意,我对Django来说相对较新 - 运行1.5-和python - 运行3.3).我删除了一些事情来解决错误并像这样运行以确保它仍然存在.在tools_clubs_import()中执行"club_list中的俱乐部"行时显示错误:
以下是根据下面标记的答案修正后的views.py:
import csv
from io import TextIOWrapper
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from rank.forms import ClubImportForm
def tools_clubs_import(request):
if request.method == 'POST':
form = ClubImportForm(request.POST, request.FILES)
if form.is_valid():
# the following 4 lines dumps request.META to a local file
# I saw a lot of questions about this so thought I'd post it too
log = open("/home/joel/meta.txt", "w")
for k, v in request.META.items():
print ("%s: %s\n" % (k, request.META[k]), file=log)
log.close()
# I found I didn't need errors='replace', your mileage may vary
f = TextIOWrapper(request.FILES['filename'].file,
encoding='ASCII')
club_list = csv.DictReader(f)
for club in club_list:
# do something with each club dictionary entry
pass
return HttpResponseRedirect(reverse('rank.views.tools_clubs_import_show'))
else:
form = ClubImportForm()
context = {'form': form, 'active_menu_item': 4,}
return render(request, 'rank/tools_clubs_import.html', context)
def tools_clubs_import_show(request):
return render(request, 'rank/tools_clubs_import_show.html')
Run Code Online (Sandbox Code Playgroud)
以下是我提交的内容的原始版本(生成表单的html包含在此代码列表的底部:
views.py
--------
import csv
from django.shortcuts import render
from django.http import HttpResponseRedirect
from rank.forms import ClubImportForm
def tools(request):
context = {'active_menu_item': 4,}
return render(request, 'rank/tools.html', context)
def tools_clubs(request):
context = {'active_menu_item': 4,}
return render(request, 'rank/tools_clubs.html', context)
def tools_clubs_import(request):
if request.method == 'POST':
form = ClubImportForm(request.POST, request.FILES)
if form.is_valid():
f = request.FILES['filename']
club_list = csv.DictReader(f)
for club in club_list:
# error occurs before anything here is executed
# process here... not included for brevity
return HttpResponseRedirect(reverse('rank.views.tools_clubs_import_show'))
else:
form = ClubImportForm()
context = {'form': form, 'active_menu_item': 4,}
return render(request, 'rank/tools_clubs_import.html', context)
def tools_clubs_import_show(request):
return render(request, 'rank/tools_clubs_import_show.html')
forms.py
--------
from django import forms
class ClubImportForm(forms.Form):
filename = forms.FileField(label='Select a CSV to import:',)
urls.py
-------
from django.conf.urls import patterns, url
from rank import views
urlpatterns = patterns('',
url(r'^tools/$', views.tools, name='rank-tools'),
url(r'^tools/clubs/$', views.tools_clubs, name='rank-tools_clubs'),
url(r'^tools/clubs/import$',
views.tools_clubs_import,
name='rank-tools_clubs_import'),
url(r'^tools/clubs/import/show$',
views.tools_clubs_import_show,
name='rank-tools_clubs_import_show'),
)
tools_clubs_import.html
-----------------------
{% extends "rank/base.html" %}
{% block title %}Tools/Club/Import{% endblock %}
{% block center_col %}
<form enctype="multipart/form-data" method="post" action="{% url 'rank-tools_clubs_import' %}">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)
例外价值:
迭代器应该返回字符串,而不是字节(你是否在文本模式下打开文件?)
异常位置:/usr/lib/python3.3/csv.py in fieldnames,第96行
Mar*_*ers 45
request.FILES为您提供二进制文件,但该csv模块希望改为使用文本模式文件.
您需要将文件包装在一个io.TextIOWrapper()实例中,并且需要弄清楚编码:
from io import TextIOWrapper
f = TextIOWrapper(request.FILES['filename'].file, encoding=request.encoding)
Run Code Online (Sandbox Code Playgroud)
如果charset从Content-Type头部获取参数,可能会更好;如果提供的话; 这就是客户端告诉你字符集的内容.
您无法解决需要知道文件数据的正确编码的问题; 您可以强制解释为ASCII,例如,通过提供errors关键字(将其设置为'replace'或'ignore'),但这会导致数据丢失:
f = TextIOWrapper(request.FILES['filename'].file, encoding='ascii', errors='replace')
Run Code Online (Sandbox Code Playgroud)
使用TextIOWrapper只能在使用Django 1.11及更高版本时工作(因为此变更集添加了所需的支持).在早期版本中,您可以在以下事实中修补支持:
from django.core.files.utils import FileProxyMixin
if not hasattr(FileProxyMixin, 'readable'):
# Pre-Django 1.11, add io.IOBase support, see
# https://github.com/django/django/commit/4f474607de9b470f977a734bdd47590ab202e778
def readable(self):
if self.closed:
return False
if hasattr(self.file, 'readable'):
return self.file.readable()
return True
def writable(self):
if self.closed:
return False
if hasattr(self.file, 'writable'):
return self.file.writable()
return 'w' in getattr(self.file, 'mode', '')
def seekable(self):
if self.closed:
return False
if hasattr(self.file, 'seekable'):
return self.file.seekable()
return True
FileProxyMixin.closed = property(
lambda self: not self.file or self.file.closed)
FileProxyMixin.readable = readable
FileProxyMixin.writable = writable
FileProxyMixin.seekable = seekable
Run Code Online (Sandbox Code Playgroud)
小智 17
在python 3中,我用过:
import csv
from io import StringIO
csvf = StringIO(xls_file.read().decode())
reader = csv.reader(csvf, delimiter=',')
Run Code Online (Sandbox Code Playgroud)
xls_file是从POST表单获取的文件.我希望它有所帮助.
| 归档时间: |
|
| 查看次数: |
13873 次 |
| 最近记录: |