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

发布于 2024-11-08 20:55:44 字数 476 浏览 0 评论 0原文

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

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

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

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

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

I am new to Django and would like to know what is the Django-way to add elements in a database not by entering each field from an html form (like it is done by default) but uploading a single file (for example a json file) that will be used to populate the database?

So let say the model has only three fields: title,description,quantity.
And I have a text file (myFile.txt) with "myTitle:myDesc" written in it.

What I want is just a FileField that will accept a text file so I can upload myFile.txt and the title and description will be read from this file.
And at the same time the quantity will be asked "normally" in a text input as it would be by default (only title and description are read from the file).

Of course, validation on the file will be done to accept/deny the uploaded file.
The problem I am facing is that if I add a FileField to the model, the file will be stored in the local storage.
I want the content of the uploaded file to be read, used to create an entry in the model, and then deleted.

Even the admin should not be able to manually add an element entering the title and description in a HTML form but only by uploading a file.
Can someone help me in a Django-way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

月亮是我掰弯的 2024-11-15 20:55:44

您可以创建两种表单:

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

然后您可以调用第一种形式的第二种形式,如下所示:

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

You can create two forms:

  1. A form based on django.forms.Form which is used to get the file from request
  2. A model form which is used to validate model fields and create a model object

Then you can call the second form from the first one, like this:

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
街道布景 2024-11-15 20:55:44

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

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

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

You can use form wizard to achieve such tasks. The basic idea is to create two forms; one with the FileField and the other form with the title, description quantity fields.

The user views the form with FileField first. Once the user uploads the file and submits the request, you can render the other form with initial values read from the file (you can also delete the file at this step).

Regarding the admin functionality, you can read about how to integrate form wizard with admin here

沙与沫 2024-11-15 20:55:44

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

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

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

I found another way of populating a model before saving it.

Instead of using pre_save, or using 2 different forms, if we are using the admin.ModelAdmin, we can simply redefine the save_model() method:

def save_model(self, request, obj, form, change):
  obj.user = request.user
  # populate the model
  obj.save()
  # post actions if needed
终弃我 2024-11-15 20:55:44

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

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

To achieve this you have to write some custom code. Each FileField has a connected File object. You can read the content of this file object like you would when dealing with files in Python.

There are of course different locations you could do that. You can overwrite the forms/models save method which contains the FileField. If you have model you could use pre_save/post_save signals as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文