Django Wagtail CSV and photo “upload” - management command

戏子无情 提交于 2021-02-20 02:20:48

问题


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 extra CharField 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!