Django: generate a CSV file and store it into FileField
Asked Answered
B

2

9

In my Django View file, I need to generate a CSV file from a list of tuples and store the CSV file into the FileField of my model.

class Bill(models.Model):
    billId = models.IntegerField()
    bill = models.FileField(upload_to='bills')

I searched on this site, and found some posts such as Django - how to create a file and save it to a model's FileField?, but the solutions can help me.

I need the CSV file to be stored in 'media/bills/' fold, and I hope the CSV file can be deleted together with the Bill object in the database.

I tried the following codes, but it cannot meet my requirements. For each file, it will generate two files 'output.csv' and 'output_xxesss.csv'. At the two files cannot be deleted by calling 'Bill.objects.all().delete()'.

path = join(settings.MEDIA_ROOT, 'bills', 'output.csv')
print path
f = open(path, 'w+b')
f.truncate()
csvWriter = csv.writer(f)
csvWriter.writerow(('A', 'B', 'C'))
for r in rs:
    print r
    csvWriter.writerow(convert(r))

bill = Bill()
bill.billId = 14
bill.bill.save('output.csv', File(f))
bill.save()

Thanks

I tried the following codes, but it can not delete the file by calling 'Bill.objects.all().delete()'.

bill = Bill()
bill.billId = 14
bill.bill.name = 'bills/output.csv'
bill.save()
Bever answered 12/3, 2017 at 16:11 Comment(0)
C
-6

Deleting an instance would not delete the associated file. You may consider using signals to be precise pre_delete. You can write a receiver where in you can delete the associated file.

from django.dispatch import receiver
from django.db.models.signals import pre_delete 

@receiver(pre_delete)
def func_name(sender, instance, **kwargs):
    your logic

You can find documentation here.

Cara answered 12/3, 2017 at 16:40 Comment(1)
This is not the answerRooftree
I
16

If anyone comes to this post like me and is wondering how to save a csv file directly into a models.FileField i recommend this way:

import csv
from io import StringIO
from django.core.files.base import ContentFile

row = ["Name", "Location", "Price"]

csv_buffer = StringIO()
csv_writer = csv.writer(csv_buffer)
csv_writer.writerow(row)

csv_file = ContentFile(csv_buffer.getvalue().encode('utf-8'))

bill.bill.save('output.csv', csv_file)

Ivories answered 24/1, 2020 at 11:24 Comment(1)
I had to add .encode('utf-8') to csv_buffer.getvalue() otherwise I got Unicode-objects must be encoded before hashingAbilene
C
-6

Deleting an instance would not delete the associated file. You may consider using signals to be precise pre_delete. You can write a receiver where in you can delete the associated file.

from django.dispatch import receiver
from django.db.models.signals import pre_delete 

@receiver(pre_delete)
def func_name(sender, instance, **kwargs):
    your logic

You can find documentation here.

Cara answered 12/3, 2017 at 16:40 Comment(1)
This is not the answerRooftree

© 2022 - 2024 — McMap. All rights reserved.