Reputation: 693
Building an application to list reports for inspections. The actual inspection report is going to be made available for download. Saving the reports to the database using django-db-file-storage.
Lots of records to process, so writing a script to do everything in bulk. Testing in the manage.py shell throws an error.
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from inspections.models import InspectionInformation, RestaurantInformation
file = open('/docs/Data/2011/12/12-07-11_1498.pdf', 'r').read()
InspectionInformation(
insp_rest_permit=RestaurantInformation.objects.get(rest_permit=int('1814')),
insp_date='2011-12-12',
insp_score='100',
insp_inspector='Philip',
insp_report=default_storage.save('report.pdf', ContentFile(file))
).save()
Traceback
Traceback (most recent call last):
File "<console>", line 6, in <module>
File "/venv/lib/python2.7/site-packages/django/core/files/storage.py", line 48, in save
name = self.get_available_name(name)
File "/venv/lib/python2.7/site-packages/django/core/files/storage.py", line 74, in get_available_name
while self.exists(name):
File "/venv/lib/python2.7/site-packages/db_file_storage/storage.py", line 77, in exists
model_class_path, content_field, filename_field, mimetype_field, filename = name.split('/')
ValueError: need more than 1 value to unpack
Models
from django.db import models
class RestaurantInformation(models.Model):
rest_permit = models.IntegerField(unique=True, verbose_name='Permit')
rest_name = models.CharField(max_length=200, verbose_name='Name')
rest_address = models.CharField(max_length=200, verbose_name='Address')
rest_city = models.CharField(max_length=100, verbose_name='City')
rest_zip = models.IntegerField(verbose_name='Zip Code')
rest_owner = models.CharField(max_length=200, verbose_name='Owner')
rest_latitude = models.CharField(max_length=40, verbose_name='Latitude')
rest_longitude = models.CharField(max_length=40, verbose_name='Longitude')
class Meta:
ordering = ['rest_name']
def __unicode__(self):
return self.rest_name + ', ' + self.rest_address + ', ' + self.rest_city
class InspectionInformation(models.Model):
insp_rest_permit = models.ForeignKey(RestaurantInformation, null=False, to_field='rest_permit')
insp_score = models.DecimalField(verbose_name='Score', decimal_places=2, max_digits=5)
insp_date = models.DateField(verbose_name='Date')
insp_inspector = models.CharField(max_length=200, verbose_name='Inspector')
insp_report = models.FileField(upload_to='restaurants.InspectionFile/bytes/filename/mimetype',
blank=True, null=True, verbose_name='Inspection Report')
class Meta:
unique_together = ("insp_rest_permit", "insp_score", "insp_date")
ordering = ['insp_date']
class InspectionFile(models.Model):
bytes = models.TextField()
filename = models.CharField(max_length=255)
mimetype = models.CharField(max_length=50)
Upvotes: 0
Views: 965
Reputation: 2271
1.It looks like db_file_storage.storage.save() expects their custom format specified to be used with the model plus the filename e.g. "console.ConsolePicture/bytes/filename/mimetype" + filename.
So for your example instead of
'report.pdf'
it would be
'restaurants.InspectionFile/bytes/filename/mimetype/report.pdf'
I looked at the documentation and it isn't clear why it's being done this way as this violates DRY by making you enter the same thing twice, but they use the same format throughout the DatabaseFileStorage class.
2.It also looks like there's a bug in the save method (line 60) where
mimetype = content.file.content_type
should be changed to
mimetype = content.content_type
And the file you pass it should be something with a content_type attribute so probably a Django SimpleUploadedFile:
from django.core.files.uploadedfile import SimpleUploadedFile
file_ = SimpleUploadedFile('report.pdf', open('/docs/Data/2011/12/12-07-11_1498.pdf', 'r').read())
The reason I think this is a bug is that when I tried passing in a mock object that looked like "content.file.content_type" I got a Python core library exception later on.
Upvotes: 1