Django:上传文件并读取其内容以填充模型?

Posted

技术标签:

【中文标题】Django:上传文件并读取其内容以填充模型?【英文标题】:Django: Upload a file and read its content to populate a model? 【发布时间】:2011-08-30 19:43:49 【问题描述】:

我是 Django 新手,想知道 Django 在数据库中添加元素的方式是什么,不是通过从 html 表单输入每个字段(就像默认情况下那样)而是上传单个文件(例如一个 json 文件)将用于填充数据库?

假设模型只有三个字段:标题、描述、数量。 我有一个文本文件(myFile.txt),里面写着“myTitle:myDesc”。

我想要的只是一个接受文本文件的 FileField,这样我就可以上传 myFile.txt 并且将从该文件中读取标题和描述。 同时,将在文本输入中“正常”询问数量,就像默认情况下一样(仅从文件中读取标题和描述)。

当然,将对文件进行验证以接受/拒绝上传的文件。 我面临的问题是,如果我将 FileField 添加到模型中,该文件将存储在本地存储中。 我希望读取上传文件的内容,用于在模型中创建条目,然后删除。

即使是管理员也不能手动添加在 HTML 表单中输入标题和描述的元素,而只能通过上传文件来添加。 有人可以以 Django 的方式帮助我吗?

【问题讨论】:

【参考方案1】:

您可以创建两种形式:

    基于django.forms.Form的表单,用于从请求中获取文件 用于验证模型字段和创建模型对象的模型表单

然后你可以从第一个表单调用第二个表单,像这样:

class MyModelForm(ModelForm):

    class Meta:
        model = MyModel


class FileUploadForm(forms.Form):

    file = forms.FileField()

    def clean_file(self):
        data = self.cleaned_data["file"]
        # read and parse the file, create a Python dictionary `data_dict` from it
        form = MyModelForm(data_dict)
        if form.is_valid():
            # we don't want to put the object to the database on this step
            self.instance = form.save(commit=False) 
        else:
            # You can use more specific error message here
            raise forms.ValidationError(u"The file contains invalid data.")
        return data

    def save(self):
        # We are not overriding the `save` method here because `form.Form` does not have it. 
        # We just add it for convenience.
        instance = getattr(self, "instance", None)
        if instance:
            instance.save()
        return instance

def my_view(request):
    form = FileUploadForm(request.POST, request.FILES)
    if form.is_valid():
        form.save()
    else:
        # display errors

【讨论】:

【参考方案2】:

您可以使用form wizard 来完成此类任务。基本思想是创建两种形式;一个带有FileField,另一个带有标题、描述数量字段的表单。

用户首先使用FileField 查看表单。用户上传文件并提交请求后,您可以使用从文件中读取的初始值渲染另一个表单(您也可以在此步骤delete the file)。

关于管理员功能,您可以阅读有关如何将表单向导与管理员集成here

【讨论】:

重要提示。第一个表单(带有 FileField 的表单)是基于 django.form.Form 的表单,not 基于 django.forms.models.ModelForm【参考方案3】:

我找到了另一种在保存模型之前填充模型的方法。

如果我们使用 admin.ModelAdmin,我们可以简单地重新定义 save_model() 方法,而不是使用 pre_save,或者使用 2 种不同的形式:

def save_model(self, request, obj, form, change):
  obj.user = request.user
  # populate the model
  obj.save()
  # post actions if needed

【讨论】:

【参考方案4】:

要实现这一点,您必须编写一些自定义代码。每个 FileField 都有一个connected File object。您可以像在 Python 中处理文件一样读取此文件对象的内容。

当然,您可以在不同的位置执行此操作。您可以覆盖包含 FileField 的表单/模型保存方法。如果你有模型,你也可以使用 pre_save/post_save 信号。

【讨论】:

我在使用 pre/post_save 信号时遇到了一些麻烦。我更喜欢 Andrey 和 Konstant 的解决方案,但感谢您的帮助。

以上是关于Django:上传文件并读取其内容以填充模型?的主要内容,如果未能解决你的问题,请参考以下文章

在Django中读取使用html表单上传的Excel文件

Django 应用程序:必须将图像上传到的目录名称,应自动填充

django 在模型自定义保存中访问上传的文件,最佳实践?

使用文件字段编辑 Django 模型而不重新上传文件

加快 Django 表单以将大型(500k obs)CSV 文件上传到 MySQL 数据库

django上传文件并读取存入数据库