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?
You can create two forms:
django.forms.Form
which is used to get the file from requestThen 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With