问题
I am working on a django/wagtail management command (let's call it "file_upload") that does roughly the following:
- take "csv" argument, which is a full path to a CSV file.
- parse and open the result using
csv
- for each row, create and save a custom Wagtail Image model object (inheriting from
AbstractImage
, with a few extraCharField
that I do not think prevent me from doing what I want to do)
The (currently simplified) CSV looks like this:
1.jpg,Title 1
2.jpg,Title 2
Does not complicated at all, even straightforward ... but this Wagtail aspect of things does not seem to be heavily documented. The following does not work:
import csv
import argparse
import os, sys
from django.core.files import File
from django.core.management.base import BaseCommand
from django.utils import timezone
from django.conf import settings
from custom_photo.models import CustomPhoto
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--csv', nargs='?', type=argparse.FileType('r'))
def handle(self, *args, **options):
path = os.path.dirname(os.path.realpath(options['csv'].name))
with options['csv'] as csvfile:
readCSV = csv.reader(csvfile, delimiter=',')
for row in readCSV:
# the file full path assumes everything is flat in the same folder
with open('%s/%s' %(path, row[0]), 'rb') as f:
django_file = File(open)
print(django_file)
photo = CustomPhoto()
photo.title=row[1]
# three arguments:
# 1) relative path inside MEDIA_ROOT
# 2) the django File object
# 3) Whether or not we want to save the photo object after the image is saved
photo.file.save(row[0], django_file, True)
print(photo.__dict__)
is run like this:
python manage.py cca_photo_import --csv=C:\path\to\file\list.csv
And throw the following error:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "<snip>env\lib\site-packages\django\core\management\__init__.py", line 371, in execute_from_command_line
utility.execute()
File "<snip>env\lib\site-packages\django\core\management\__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "<snip>env\lib\site-packages\django\core\management\base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "<snip>env\lib\site-packages\django\core\management\base.py", line 335, in execute
output = self.handle(*args, **options)
File "<snip>cca\cca_photo\management\commands\cca_photo_import.py", line 43, in handle
photo.file.save(row[0], django_file, True)
File "<snip>env\lib\site-packages\django\db\models\fields\files.py", line 87, in save
self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "<snip>env\lib\site-packages\django\core\files\storage.py", line 49, in save
return self._save(name, content)
File "<snip>env\lib\site-packages\django\core\files\storage.py", line 268, in _save
for chunk in content.chunks():
File "<snip>env\lib\site-packages\django\core\files\base.py", line 71, in chunks
data = self.read(chunk_size)
File "<snip>env\lib\site-packages\django\core\files\utils.py", line 16, in <lambda>
read = property(lambda self: self.file.read)
AttributeError: 'builtin_function_or_method' object has no attribute 'read'
Many thanks
回答1:
Thanks to gasman, this is now working. Duh.
import csv
import argparse
import os, sys
from django.core.files import File
from django.core.management.base import BaseCommand
from django.utils import timezone
from django.conf import settings
from custom_photo.models import CustomPhoto, CustomPhotoPlate, CustomPhotoType
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--csv', nargs='?', type=argparse.FileType('r'))
def handle(self, *args, **options):
path = os.path.dirname(os.path.realpath(options['csv'].name))
with options['csv'] as csvfile:
readCSV = csv.reader(csvfile, delimiter=',')
for row in readCSV:
photo_path = '%s/%s' %(path, row[0])
with open(photo_path, 'rb') as f:
django_file = File(f)
photo = CustomPhoto()
photo.title=row[1]
photo.file = django_file
photo.save()
print(photo.__dict__)
The photo
object is saved, etc, etc. All good.
However, the file
field for that object is now populated with:
original_images/CFolderSubFolderSubSubFolderSubSubSubFolder1.jpg
Where CFolderSubFolderSubSubFolderSubSubSubFolder is apparently the cleaned version of C:\Folder\SubFolder\SubSubFolder\SubSubSubFolder
Any way to get rid of this (useless) path? Which is apparently the full path to the JPG file.
Thanks!
来源:https://stackoverflow.com/questions/50063542/django-wagtail-csv-and-photo-upload-management-command