| 1 | # Copyright (C) 2007 Samalyse SARL |
|---|
| 2 | # All rights reserved. |
|---|
| 3 | # |
|---|
| 4 | # This software is licensed as described in the file COPYING, which |
|---|
| 5 | # you should have received as part of this distribution. The terms |
|---|
| 6 | # are also available at http://svn.parisson.org/telemeta/TelemetaLicense. |
|---|
| 7 | # |
|---|
| 8 | # Author: Olivier Guilyardi <olivier@samalyse.com> |
|---|
| 9 | |
|---|
| 10 | from django.db import models |
|---|
| 11 | from django.db.models import Q |
|---|
| 12 | from django.core.exceptions import ObjectDoesNotExist |
|---|
| 13 | from django.core import validators |
|---|
| 14 | |
|---|
| 15 | import telemeta |
|---|
| 16 | from telemeta.core import * |
|---|
| 17 | from telemeta import dublincore as dc |
|---|
| 18 | |
|---|
| 19 | # Regular (sub) expression for matching/validating media objects IDs |
|---|
| 20 | media_id_regex = r'[0-9A-Za-z._:%?-]+' |
|---|
| 21 | |
|---|
| 22 | class MediaModel(Component): |
|---|
| 23 | pass |
|---|
| 24 | |
|---|
| 25 | class MediaCore: |
|---|
| 26 | def to_dict(self): |
|---|
| 27 | "Return model fields as a dict of name/value pairs" |
|---|
| 28 | fields_dict = {} |
|---|
| 29 | for field in self._meta.fields: |
|---|
| 30 | fields_dict[field.name] = getattr(self, field.name) |
|---|
| 31 | return fields_dict |
|---|
| 32 | |
|---|
| 33 | class PhysicalFormat(models.Model): |
|---|
| 34 | value = models.CharField(maxlength=250) |
|---|
| 35 | is_enumeration = True |
|---|
| 36 | def __str__(self): |
|---|
| 37 | return self.value |
|---|
| 38 | class Meta: |
|---|
| 39 | ordering = ['value'] |
|---|
| 40 | |
|---|
| 41 | class PublishingStatus(models.Model): |
|---|
| 42 | value = models.CharField(maxlength=250) |
|---|
| 43 | is_enumeration = True |
|---|
| 44 | def __str__(self): |
|---|
| 45 | return self.value |
|---|
| 46 | class Meta: |
|---|
| 47 | ordering = ['value'] |
|---|
| 48 | verbose_name_plural = "Publishing status" |
|---|
| 49 | |
|---|
| 50 | class MediaCollectionManager(models.Manager): |
|---|
| 51 | def quick_search(self, pattern): |
|---|
| 52 | return super(MediaCollectionManager, self).get_query_set().filter( |
|---|
| 53 | Q(id__icontains=pattern) | |
|---|
| 54 | Q(title__icontains=pattern) | |
|---|
| 55 | Q(creator__icontains=pattern) |
|---|
| 56 | ) |
|---|
| 57 | |
|---|
| 58 | class MediaCollection(models.Model, MediaCore): |
|---|
| 59 | "Group related media items" |
|---|
| 60 | |
|---|
| 61 | id_regex = media_id_regex |
|---|
| 62 | id_validator = validators.MatchesRegularExpression('^' + id_regex + '$') |
|---|
| 63 | |
|---|
| 64 | publisher_reference = models.CharField(maxlength=250, blank=True) |
|---|
| 65 | physical_format = models.CharField(maxlength=250, blank=True) |
|---|
| 66 | id = models.CharField(maxlength=250, primary_key=True, |
|---|
| 67 | verbose_name='identifier', validator_list=[id_validator]) |
|---|
| 68 | title = models.CharField(maxlength=250) |
|---|
| 69 | native_title = models.CharField(maxlength=250, blank=True) |
|---|
| 70 | physical_items_num = models.CharField(maxlength=250, blank=True) |
|---|
| 71 | publishing_status = models.CharField(maxlength=250, blank=True) |
|---|
| 72 | is_original = models.CharField(maxlength=250, blank=True) |
|---|
| 73 | is_full_copy = models.CharField(maxlength=250, blank=True) |
|---|
| 74 | copied_from = models.ForeignKey('self', null=True, blank=True) |
|---|
| 75 | creator = models.CharField(maxlength=250) |
|---|
| 76 | booklet_writer = models.CharField(maxlength=250, blank=True) |
|---|
| 77 | booklet_description = models.TextField(blank=True) |
|---|
| 78 | collector = models.CharField(maxlength=250, blank=True) |
|---|
| 79 | publisher = models.CharField(maxlength=250, blank=True) |
|---|
| 80 | date_published = models.CharField(maxlength=250, blank=True) |
|---|
| 81 | publisher_collection = models.CharField(maxlength=250, blank=True) |
|---|
| 82 | publisher_serial_id = models.CharField(maxlength=250, blank=True) |
|---|
| 83 | ref_biblio = models.TextField(blank=True) |
|---|
| 84 | acquisition_mode = models.CharField(maxlength=250, blank=True) |
|---|
| 85 | comment = models.TextField(blank=True) |
|---|
| 86 | record_author = models.CharField(maxlength=250, blank=True) |
|---|
| 87 | record_writer = models.CharField(maxlength=250, blank=True) |
|---|
| 88 | rights = models.CharField(maxlength=250, blank=True) |
|---|
| 89 | annee_enr = models.CharField(maxlength=250, blank=True) |
|---|
| 90 | terrain_ou_autre = models.CharField(maxlength=250, blank=True) |
|---|
| 91 | duree_approx = models.CharField(maxlength=250, blank=True) |
|---|
| 92 | tri_dibm = models.CharField(maxlength=250, blank=True) |
|---|
| 93 | travail = models.CharField(maxlength=250, blank=True) |
|---|
| 94 | compil_face_plage = models.TextField(blank=True) |
|---|
| 95 | deposant_cnrs = models.CharField(maxlength=250, blank=True) |
|---|
| 96 | fiches = models.CharField(maxlength=250, blank=True) |
|---|
| 97 | a_informer = models.CharField(maxlength=250, blank=True) |
|---|
| 98 | numerisation = models.CharField(maxlength=250, blank=True) |
|---|
| 99 | champ36 = models.CharField(maxlength=250, blank=True) |
|---|
| 100 | |
|---|
| 101 | objects = MediaCollectionManager() |
|---|
| 102 | |
|---|
| 103 | def to_dublincore(self): |
|---|
| 104 | if (self.date_published): |
|---|
| 105 | date = self.date_published |
|---|
| 106 | else: |
|---|
| 107 | date = self.annee_enr |
|---|
| 108 | |
|---|
| 109 | if (self.copied_from): |
|---|
| 110 | copied_from = self.copied_from.id |
|---|
| 111 | else: |
|---|
| 112 | copied_from = '' |
|---|
| 113 | |
|---|
| 114 | resource = dc.Resource( |
|---|
| 115 | dc.Element('identifier','id', self.id), |
|---|
| 116 | dc.Element('type', value='Collection'), |
|---|
| 117 | dc.Element('title', 'title', self.title), |
|---|
| 118 | dc.Element('title', 'native_title', self.native_title), |
|---|
| 119 | dc.Element('creator', 'creator', self.creator), |
|---|
| 120 | dc.Element('relation', 'copied_from', copied_from, |
|---|
| 121 | 'isVersionOf'), |
|---|
| 122 | dc.Element('contributor', 'booklet_writer', self.booklet_writer), |
|---|
| 123 | dc.Element('contributor', 'collector', self.collector), |
|---|
| 124 | dc.Element('publisher', 'publisher', self.publisher), |
|---|
| 125 | dc.Element('date', value=date), |
|---|
| 126 | dc.Element('rights', 'rights', self.rights), |
|---|
| 127 | ) |
|---|
| 128 | return resource |
|---|
| 129 | |
|---|
| 130 | def __str__(self): |
|---|
| 131 | #return self.title |
|---|
| 132 | return self.id |
|---|
| 133 | |
|---|
| 134 | class Meta: |
|---|
| 135 | ordering = ['title'] |
|---|
| 136 | db_table = 'telemeta_collection' |
|---|
| 137 | |
|---|
| 138 | class Admin: |
|---|
| 139 | pass |
|---|
| 140 | |
|---|
| 141 | class MediaItemManager(models.Manager): |
|---|
| 142 | def quick_search(self, pattern): |
|---|
| 143 | return super(MediaItemManager, self).get_query_set().filter( |
|---|
| 144 | Q(id__icontains=pattern) | |
|---|
| 145 | Q(_title__icontains=pattern) |
|---|
| 146 | ) |
|---|
| 147 | |
|---|
| 148 | class MediaItem(models.Model, MediaCore): |
|---|
| 149 | "Describe a item with metadata" |
|---|
| 150 | |
|---|
| 151 | id_regex = media_id_regex |
|---|
| 152 | id_validator = validators.MatchesRegularExpression('^' + id_regex + '$') |
|---|
| 153 | |
|---|
| 154 | ref = models.CharField(maxlength=250, blank=True) |
|---|
| 155 | format = models.CharField(maxlength=250, blank=True) |
|---|
| 156 | collection = models.ForeignKey(MediaCollection, related_name="items") |
|---|
| 157 | face_plage = models.CharField(maxlength=250, blank=True) |
|---|
| 158 | id = models.CharField(maxlength=250, primary_key=True, |
|---|
| 159 | verbose_name='identifier', validator_list=[id_validator]) |
|---|
| 160 | duree = models.CharField(maxlength=250, blank=True) |
|---|
| 161 | dates_enregistr = models.CharField(maxlength=250, blank=True) |
|---|
| 162 | etat = models.CharField(maxlength=250, blank=True) |
|---|
| 163 | region_village = models.CharField(maxlength=250, blank=True) |
|---|
| 164 | ethnie_grsocial = models.CharField(maxlength=250, blank=True) |
|---|
| 165 | titre_support = models.CharField(maxlength=250, blank=True) |
|---|
| 166 | _title = models.CharField(maxlength=250, db_column='title') |
|---|
| 167 | transcrip_trad = models.CharField(maxlength=250, blank=True) |
|---|
| 168 | auteur = models.CharField(maxlength=250, blank=True) |
|---|
| 169 | form_genr_style = models.CharField(maxlength=250, blank=True) |
|---|
| 170 | struct_modale = models.CharField(maxlength=250, blank=True) |
|---|
| 171 | struct_rythm = models.CharField(maxlength=250, blank=True) |
|---|
| 172 | comm_fonctusage = models.TextField(blank=True) |
|---|
| 173 | documentation = models.TextField(maxlength=250, blank=True) |
|---|
| 174 | remarques = models.TextField(maxlength=250, blank=True) |
|---|
| 175 | moda_execut = models.CharField(maxlength=250, blank=True) |
|---|
| 176 | copie_de = models.CharField(maxlength=250, blank=True) |
|---|
| 177 | enregistre_par = models.CharField(maxlength=250, blank=True) |
|---|
| 178 | aire_geo_cult = models.CharField(maxlength=250, blank=True) |
|---|
| 179 | annee_enreg = models.CharField(maxlength=250, blank=True) |
|---|
| 180 | formstyl_generi = models.CharField(maxlength=250, blank=True) |
|---|
| 181 | choixcollecteur = models.CharField(maxlength=250, blank=True) |
|---|
| 182 | repere_bande = models.CharField(maxlength=250, blank=True) |
|---|
| 183 | nroband_nropiec = models.CharField(maxlength=250, blank=True) |
|---|
| 184 | continent = models.CharField(maxlength=250, blank=True) |
|---|
| 185 | file = models.FileField(upload_to='items/%Y/%m/%d', blank=True) |
|---|
| 186 | |
|---|
| 187 | objects = MediaItemManager() |
|---|
| 188 | |
|---|
| 189 | def _get_title(self): |
|---|
| 190 | if self._title == "": |
|---|
| 191 | try: |
|---|
| 192 | title = self.collection.title + " - Face/Plage: " \ |
|---|
| 193 | + self.face_plage |
|---|
| 194 | except ObjectDoesNotExist: |
|---|
| 195 | title = self.id |
|---|
| 196 | else: |
|---|
| 197 | title = self._title |
|---|
| 198 | |
|---|
| 199 | return title |
|---|
| 200 | title = property(_get_title) |
|---|
| 201 | |
|---|
| 202 | def to_dublincore(self): |
|---|
| 203 | if self.auteur: |
|---|
| 204 | creator = self.auteur |
|---|
| 205 | else: |
|---|
| 206 | creator = self.collection.creator |
|---|
| 207 | |
|---|
| 208 | resource = dc.Resource( |
|---|
| 209 | dc.Element('identifier','id', self.id), |
|---|
| 210 | dc.Element('type', value='Sound'), |
|---|
| 211 | dc.Element('relation', 'collection', self.collection.id, 'isPartOf'), |
|---|
| 212 | dc.Element('title', 'title', self.title), |
|---|
| 213 | dc.Element('creator', value=creator), |
|---|
| 214 | dc.Element('publisher', value=self.collection.publisher), |
|---|
| 215 | ) |
|---|
| 216 | return resource |
|---|
| 217 | |
|---|
| 218 | def __str__(self): |
|---|
| 219 | return self.title |
|---|
| 220 | |
|---|
| 221 | class Admin: |
|---|
| 222 | pass |
|---|
| 223 | |
|---|
| 224 | class Meta: |
|---|
| 225 | ordering = ['_title'] |
|---|
| 226 | db_table = 'telemeta_item' |
|---|
| 227 | |
|---|
| 228 | |
|---|
| 229 | class MediaPart(models.Model, MediaCore): |
|---|
| 230 | "Describe the part of a media item" |
|---|
| 231 | |
|---|
| 232 | contributor = models.CharField(maxlength=250) |
|---|
| 233 | coverage = models.CharField(maxlength=250) |
|---|
| 234 | creator = models.CharField(maxlength=250) |
|---|
| 235 | date = models.DateField() |
|---|
| 236 | description = models.CharField(maxlength=250) |
|---|
| 237 | format = models.CharField(maxlength=250) |
|---|
| 238 | identifier = models.CharField(maxlength=250) |
|---|
| 239 | language = models.CharField(maxlength=250) |
|---|
| 240 | publisher = models.CharField(maxlength=250) |
|---|
| 241 | rights = models.CharField(maxlength=250) |
|---|
| 242 | source = models.CharField(maxlength=250) |
|---|
| 243 | subject = models.CharField(maxlength=250) |
|---|
| 244 | title = models.CharField(maxlength=250) |
|---|
| 245 | media_item = models.ForeignKey(MediaItem) |
|---|
| 246 | media_item.dublin_core = 'relation' |
|---|
| 247 | parent = models.ForeignKey('self', null=True, related_name='children') |
|---|
| 248 | media_item.dublin_core = 'relation' |
|---|
| 249 | start = models.FloatField(max_digits=11, decimal_places=3) |
|---|
| 250 | end = models.FloatField(max_digits=11, decimal_places=3) |
|---|
| 251 | |
|---|
| 252 | def __str__(self): |
|---|
| 253 | return self.title |
|---|
| 254 | |
|---|
| 255 | class Meta: |
|---|
| 256 | ordering = ['title'] |
|---|
| 257 | db_table = 'telemeta_part' |
|---|
| 258 | |
|---|
| 259 | class Admin: |
|---|
| 260 | pass |
|---|
| 261 | |
|---|