215👍
You want to have a look at FileField and FieldFile in the Django docs, and especially FieldFile.save().
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:
self.license_file.save(new_name, new_contents)
where 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.File
or django.core.files.base.ContentFile
(see given links to manual for the details).
The two choices boil down to:
from django.core.files.base import ContentFile, File
# Using File
with open('/path/to/file') as f:
self.license_file.save(new_name, File(f))
# Using ContentFile
self.license_file.save(new_name, ContentFile('A string with the file content'))
32👍
Accepted answer is certainly a good solution, but here is the way I went about generating a CSV and serving it from a view.
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).
Django 1.4.1
Python 2.7.3
#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
- [Django]-How to check Django version
- [Django]-Is there a way to loop over two lists simultaneously in django?
- [Django]-Django gives Bad Request (400) when DEBUG = False
11👍
It’s good practice to use a context manager or call close()
in case of exceptions during the file saving process. Could happen if your storage backend is down, etc.
Any overwrite behavior should be configured in your storage backend. For example S3Boto3Storage has a setting AWS_S3_FILE_OVERWRITE
. If you’re using FileSystemStorage
you can write a custom mixin.
You might also want to call the model’s save method instead of the FileField’s save method if you want any custom side-effects to happen, like last-updated timestamps. If that’s the case, you can also set the name attribute of the file to the name of the file – which is relative to MEDIA_ROOT
. It defaults to the full path of the file which can cause problems if you don’t set it – see File.__init__() and File.name.
Here’s an example where self
is the model instance where my_file
is the FileField / ImageFile, calling save()
on the whole model instance instead of just FileField:
import os
from django.core.files import File
with open(filepath, 'rb') as fi:
self.my_file = File(fi, name=os.path.basename(fi.name))
self.save()
- [Django]-Itertools.groupby in a django template
- [Django]-How to change site title, site header and index title in Django Admin?
- [Django]-How to get Django and ReactJS to work together?
0👍
As an alternative for doing this in save()
, I overrode form_valid()
‘s CreateView
to achieve this (i.e. creating a file and saving it to a FileField
).
In the example below I’m generating a PDF with Weasyprint and am saving it to the model’s request_pdf
field upon form submission.
def form_valid(self, form):
html_template = get_template('request_pdf.html')
pdf_dict = {}
pdf_dict['something'] = form.instance.something
rendered_html = html_template.render(pdf_dict).encode(encoding="UTF-8")
base_url = self.request.build_absolute_uri("/")
pdf_file_bytes = HTML(string=rendered_html, base_url=base_url).write_pdf()
form.instance.request_pdf = ContentFile(pdf_file_bytes)
# We need to specify the filename, else the file won't be saved
form.instance.request_pdf.name = "my_filename"
return super(MyCreateView, self).form_valid(form)
- [Django]-How to merge consecutive database migrations in django 1.9+?
- [Django]-How do I use django rest framework to send a file in response?
- [Django]-How to add superuser in Django from fixture