如何访问 Django forms.FileField 文件(*不是 models.FileField*)?

How to access the Django forms.FileField file (*not models.FileField*)?

我正在运行 Django 1.7。

我有以下模型形式:

class DeckCreateForm(forms.ModelForm):
    csv_file = forms.FileField(required=False)
    class Meta:
        model = Deck
        fields = ['title', 'description']

请注意,文件字段不是模型的一部分(我希望保持这种状态)。此文件字段旨在提供构建模型 Deck 的替代方法。

我想知道如何访问上传的文件。我查看了我的媒体目录,但它不在那里。我尝试将 "upload_to" 添加到 csv_file 构造函数但出现错误:

TypeError: __init__() got an unexpected keyword argument 'upload_to'

编辑:

我想知道如何使它与基于 class 的通用创建视图一起使用,该视图使用上述模型形式 - 在 views.py 中我有:

class DeckCreateView(CreateView):
    model = Deck
    form_class = DeckCreateForm
    template_name = 'deck_create.html'

具体来说,我如何修改 http://docs.djangoproject.com/en/1.7/topics/http/file-uploads 之类的内容以使用上述基于 class 的视图。我的 urls.py 文件:

urlpatterns = patterns(
    ...
    url(r"^deck/create/$", views.DeckCreateView.as_view(), name="deck-create"),
    ...
)

有没有我可以在 DeckCreateView 中覆盖的方法来处理文件上传?

我发现有关文件上传的 Django 文档对于新的 Django 用户来说可能有点难以理解。但是,我认为下面的 link 提供了一个非常简洁且易于遵循的逐步设置文件上传表单的过程。

Need a minimal Django file upload example

我相信你会在那里找到你需要的一切。

编辑

作为对 OP 关于基于 class 视图的编辑和评论的回应,我相信它们比基于函数的视图更清晰,并且可以说 "cleaner" 看起来像代码。这是一个很棒的 link 讨论 CBV 和 FBV,其中包括一个简单但有效的 CBV 示例。

http://www.datalifebalance.com/2014/04/django-file-uploads-with-class-based-views.html

待编辑附录

为了完整起见,并限制答案对上述外部 link(可能有一天会消失)的依赖,我们添加了更多细节。为了实现他们的 objective,OP 可以覆盖 DeckCreateView 的 post 方法并保存,DeckCreateForm 的 __init__ 像这样:

views.py:

...

class DeckCreateView(CreateView):
    ...
    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect(self.success_url)
        else:
            return render(request, self.template_name, {'form': form})

forms.py

...

class DeckCreateForm(forms.ModelForm):
    ...
    def __init__(self, post_data, files_data):
        self.csv_file = files_data.get('csv_file', None)
        return super(DeckCreateForm, self).__init__(post_data, files_data)

    def save(self, *args, **kwargs):
        deck = super(DeckCreateForm, self).save(*args, **kwargs)
        self.handle_csv_file(self.csv_file, deck)
        return deck

    def handle_csv_file(f, deck):
        ...
        for chunk in f.chunks():
            ... 
        ...

提交表单后,请求会发送到 DeckCreateView::post。文件处理在调用 DeckCreateForm::save 时发生。