开发者

Django: Upload a file and read its content to populate a model?

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,开发者_JS百科 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?


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


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


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜