Here's my model. What I want to do is generate a new file and overwrite the existing one whenever a model instance is saved:
class Kitten(models.Model): claw_size = ... license_file = models.FileField(blank=True, upload_to='license') def save(self, *args, **kwargs): #Generate a new license file overwriting any previous version #and update file path self.license_file = ??? super(Request,self).save(*args, **kwargs)
I see lots of documentation about how to upload a file. But how do I generate a file, assign it to a model field and have Django store it in the right place?
Basically, a field declared as a
FileField, when accessed, gives you an instance of class
FieldFile, which gives you several methods to interact with the underlying file. So, what you need to do is:
new_name is the filename you wish assigned and
new_contents is the content of the file. Note that
new_contents must be an instance of either
django.core.files.base.ContentFile (see given links to manual for the details). The two choices boil down to:
# Using File f = open('/path/to/file') self.license_file.save(new_name, File(f)) # Using ContentFile self.license_file.save(new_name, ContentFile('A string with the file content'))
Accepted answer is certainly a good solution, but here is the way I went about generating a CSV and serving it from a view.
#Model class MonthEnd(models.Model): report = models.FileField(db_index=True, upload_to='not_used') import csv from os.path import join #build and store the file def write_csv(): path = join(settings.MEDIA_ROOT, 'files', 'month_end', 'report.csv') f = open(path, "w+b") #wipe the existing content f.truncate() csv_writer = csv.writer(f) csv_writer.writerow(('col1')) for num in range(3): csv_writer.writerow((num, )) month_end_file = MonthEnd() month_end_file.report.name = path month_end_file.save() from my_app.models import MonthEnd #serve it up as a download def get_report(request): month_end = MonthEnd.objects.get(file_criteria=criteria) response = HttpResponse(month_end.report, content_type='text/plain') response['Content-Disposition'] = 'attachment; filename=report.csv' return response
Thought it was worth while putting this here as it took me a little bit of fiddling to get all the desirable behaviour (overwrite existing file, storing to the right spot, not creating duplicate files etc).