src/iconolab_mcc/management/commands/updatecollection.py
author ymh <ymh.work@gmail.com>
Tue, 26 Jun 2018 16:22:54 +0200
changeset 21 631f70f55fed
parent 5 cfd40849d24c
permissions -rw-r--r--
Use the new generic "get_natural_key" method
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     1
# -*- coding: UTF-8 -*-
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     2
from django.core.management.base import BaseCommand, CommandError
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     3
from django.core.management import call_command
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     4
from django.conf import settings
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     5
from iconolab.models import Collection, Item, ItemMetadata, MetaCategory
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     6
from sorl.thumbnail import get_thumbnail
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     7
import os, csv, pprint, re, json, shutil
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     8
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
     9
class Command(BaseCommand):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    10
    help = "import images from a directory into the media folder and creates item and image objects"
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    11
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    12
    def add_arguments(self, parser):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    13
        parser.add_argument("csv_path")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    14
        parser.add_argument(
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    15
            '--encoding',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    16
            dest='encoding',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    17
            default='utf-8',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    18
            help='CSV file encoding'
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    19
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    20
        )
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    21
        parser.add_argument(
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    22
            '--collection-id',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    23
            dest='collection_id',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    24
            default=False,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    25
            help='insert extracted data into the specified collection instead of trying to load a collection fixture',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    26
        )
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    27
        parser.add_argument(
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    28
            '--delimiter',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    29
            dest='csv_delimiter',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    30
            default=';',
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    31
            help='csv file delimiter'
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    32
        )
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    33
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    34
    def handle(self, *args, **options):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    35
        try:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    36
            # Check we have a collection to store data into:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    37
            source_dir = os.path.dirname(os.path.realpath(options.get("csv_path")))
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    38
            print("# Checking collection args")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    39
            if options.get("collection_id"):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    40
                print("## Finding collection with id "+options.get("collection_id"))
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    41
                try:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    42
                    collection = Collection.objects.get(pk=options.get("collection_id"))
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    43
                except Collection.DoesNotExist:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    44
                    raise ValueError("!!! Collection with primary key "+options.get("collection_id")+" was not found, aborting !!!")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    45
            else:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    46
                raise ValueError("!!! No collection id, aborting because we don't know which collection to update. !!!")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    47
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    48
            # We read the csv
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    49
            delimiter = options.get('csv_delimiter')
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    50
            if delimiter == "#9":
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    51
                delimiter = chr(9)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    52
            if delimiter == "#29":
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    53
                delimiter = chr(29)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    54
            if delimiter == "#30":
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    55
                delimiter = chr(30)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    56
            if delimiter == "#31":
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    57
                delimiter = chr(31)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    58
            csvreader = csv.DictReader(open(options.get("csv_path"), encoding=options.get("encoding")), delimiter=delimiter)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    59
            print("# Extracting data from csv file and storing it in standardized format")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    60
            # We store data using the Jocondelab keys, as defined in settings.IMPORT_FIELDS_DICT
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    61
            cleaned_csv_data=[]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    62
            for row in csvreader:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    63
                cleaned_row_data = {}
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    64
                for key in settings.IMPORT_FIELDS_DICT.keys():
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    65
                    cleaned_row_data[key] = ""
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    66
                    for row_key in row.keys():
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    67
                        if row_key in settings.IMPORT_FIELDS_DICT[key]:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    68
                            # Handling the multiple natural keys exports nonsense
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    69
                            if key == "REF":
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    70
                                natural_key_number, _, _ = row[row_key].partition(";")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    71
                                cleaned_row_data[key] = natural_key_number.rstrip()
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    72
                            else:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    73
                                cleaned_row_data[key] = row[row_key]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    74
                            break
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    75
                cleaned_csv_data.append(cleaned_row_data)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    76
            # Listing image files in csv directory
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    77
            filtered_csv_data = []
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    78
            # Now we trim the cleaned_csv_data dict to keep only entries that already exist in the database in Item form (using the natural key)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    79
            for item in cleaned_csv_data:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    80
                if item.get("REF", "") and ItemMetadata.objects.filter(item__collection = collection, natural_key=item.get("REF")).exists():
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    81
                    filtered_csv_data.append(item)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    82
            print("## found " + str(len(filtered_csv_data))+" items to update")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    83
            print("# Updating data from Iconolab")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    84
            for item in filtered_csv_data:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    85
                item_metadatas = ItemMetadata.objects.filter(item__collection = collection, natural_key=item.get("REF")).first()
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    86
                if not item["REF"]:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    87
                    print("#### No Natural key, skipping")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    88
                    continue
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    89
                item_authors = item["AUTR"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    90
                item_school = item["ECOLE"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    91
                item_designation = ""
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    92
                if item.get("TITR", ""):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    93
                    item_designation = item["TITR"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    94
                elif item.get("DENO", ""):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    95
                    item_designation = item["DENO"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    96
                elif item.get("APPL", ""):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    97
                    item_designation = item["APPL"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    98
                item_datation = ""
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
    99
                if item.get("PERI", ""):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   100
                    item_datation = item["PERI"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   101
                elif item.get("MILL", ""):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   102
                    item_datation = item["MILL"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   103
                elif item.get("EPOQ", ""):
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   104
                    item_datation = item["EPOQ"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   105
                item_technics = item["TECH"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   106
                item_field = item["DOM"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   107
                item_measurements = item["DIMS"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   108
                item_create_or_usage_location = item["LIEUX"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   109
                item_discovery_context = item["DECV"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   110
                item_conservation_location = item["LOCA"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   111
                item_photo_credits = item["PHOT"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   112
                item_inventory_number = item["INV"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   113
                item_joconde_ref = item["REF"]
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   114
                # Updating metadatas
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   115
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   116
                new_metadata = {
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   117
                    "authors" : item_authors,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   118
                    "school" : item_school,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   119
                    "designation" : item_designation,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   120
                    "field" : item_field,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   121
                    "datation" : item_datation,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   122
                    "technics" : item_technics,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   123
                    "measurements" : item_measurements,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   124
                    "create_or_usage_location" : item_create_or_usage_location,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   125
                    "discovery_context" : item_discovery_context,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   126
                    "conservation_location" : item_conservation_location,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   127
                    "photo_credits" : item_photo_credits,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   128
                    "inventory_number" : item_inventory_number,
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   129
                    "joconde_ref" : item_joconde_ref
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   130
                }
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   131
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   132
                item_metadatas.metadata = json.dumps(new_metadata)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   133
                item_metadatas.natural_key = item_joconde_ref
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   134
                item_metadatas.save()
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   135
                print('### Generating thumbnails for item '+item['REF'])
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   136
                for image in item_metadatas.item.images.all():
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   137
                    for size in settings.PREGENERATE_THUMBNAILS_SIZES:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   138
                        print('#### Thumbnail for size '+size)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   139
                        get_thumbnail(image.media, size, crop=False)
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   140
            print("# All done!")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   141
        except FileNotFoundError:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   142
            print("!!! File "+options.get("csv_path")+" does not exist. !!!")
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   143
        except ValueError as e:
cfd40849d24c Turning iconolab-mcc into App to add specific import commands
Riwad Salim
parents:
diff changeset
   144
            print(str(e))