34

クライアント システムからファイルをアップロードするフォームを使用して、CSV ファイルをインポートしようとしています。ファイルを取得したら、その一部を取得して、アプリにモデルを設定します。ただし、アップロードされたファイルの行を反復処理すると、「イテレータはバイトではなく文字列を返す必要があります」というエラーが表示されます。私は何時間もかけてさまざまなことを試し、これで見つけたすべてのものを読みましたが、それを解決できないようです(注意してください、私はDjango-1.5を実行しており、python-3.3を実行しています)。エラーだけを取得するために物事を取り除き、このように実行して、エラーがまだ存在することを確認しました。tools_clubs_import() で「for clubs in 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')

以下は、私が提出したものの元のバージョンです (フォームを生成する 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 %}

例外値:

イテレータは、バイトではなく文字列を返す必要があります (ファイルをテキスト モードで開きましたか?)

例外の場所: フィールド名の /usr/lib/python3.3/csv.py、96 行目

4

3 に答える 3