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

时间:2011-05-23 01:20:32

标签: django file-upload django-admin

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

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

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

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

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

4 个答案:

答案 0 :(得分:8)

您可以创建两种形式:

  1. 基于django.forms.Form的表单,用于从请求中获取文件
  2. 用于验证模型字段和创建模型对象的模型表单
  3. 然后你可以从第一个表单调用第二个表单,如下所示:

    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
    

答案 1 :(得分:2)

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

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

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

集成的信息

答案 2 :(得分:1)

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

如果我们使用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

答案 3 :(得分:0)

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

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