source: telemeta/models/crem.py @ dcb9160

cremcrem2crem3devdev2diademsdj1.6feature/breadcrumbsfeature/ts-0.5feature/ts-0.5.4feature/writecacheformagenericinstru_searchlamlam2mapsv3mergenlivemultiprobproductionrelease/1.4.4sabiodsearchsecurityserversocialstoragetelecastertestvideo
Last change on this file since dcb9160 was dcb9160, checked in by olivier <>, 5 years ago

add MediaCollection?.is_published field

  • Property mode set to 100755
File size: 21.3 KB
Line 
1# -*- coding: utf-8 -*-
2# Copyright (C) 2007-2010 Samalyse SARL
3
4# This software is a computer program whose purpose is to backup, analyse,
5# transcode and stream any audio content with its metadata over a web frontend.
6
7# This software is governed by the CeCILL  license under French law and
8# abiding by the rules of distribution of free software.  You can  use,
9# modify and/ or redistribute the software under the terms of the CeCILL
10# license as circulated by CEA, CNRS and INRIA at the following URL
11# "http://www.cecill.info".
12
13# As a counterpart to the access to the source code and  rights to copy,
14# modify and redistribute granted by the license, users are provided only
15# with a limited warranty  and the software's author,  the holder of the
16# economic rights,  and the successive licensors  have only  limited
17# liability.
18
19# In this respect, the user's attention is drawn to the risks associated
20# with loading,  using,  modifying and/or developing or reproducing the
21# software by the user in light of its specific status of free software,
22# that may mean  that it is complicated to manipulate,  and  that  also
23# therefore means  that it is reserved for developers  and  experienced
24# professionals having in-depth computer knowledge. Users are therefore
25# encouraged to load and test the software's suitability as regards their
26# requirements in conditions enabling the security of their systems and/or
27# data to be ensured and,  more generally, to use and operate it in the
28# same conditions as regards security.
29
30# The fact that you are presently reading this means that you have had
31# knowledge of the CeCILL license and that you accept its terms.
32#
33# Authors: Olivier Guilyardi <olivier@samalyse.com>
34#          David LIPSZYC <davidlipszyc@gmail.com>
35
36from django.db import models
37import cremquery as query
38from xml.dom.minidom import getDOMImplementation
39
40class ModelCore(models.Model):
41
42    @classmethod
43    def required_fields(cls):
44        required = []
45        for field in cls._meta.fields:
46            if (field != cls._meta.pk and field.default == models.fields.NOT_PROVIDED and
47                    not field.null and not getattr(field, 'auto_now_add', False)):
48                required.append(field)
49        return required
50
51    def save(self, force_insert=False, force_update=False, using=None):
52        required = self.required_fields()
53        for field in required:
54            if not getattr(self, field.name):
55                raise RequiredFieldError(self, field)
56        super(ModelCore, self).save(force_insert, force_update, using)
57
58    class Meta:
59        abstract = True
60
61class MediaCore(ModelCore):
62    "Base class of all media objects"
63
64    def to_dict(self): 
65        "Return model fields as a dict of name/value pairs"
66        fields_dict = {}
67        for field in self._meta.fields:
68            fields_dict[field.name] = getattr(self, field.name)
69        return fields_dict
70
71    def to_list(self): 
72        "Return model fields as a list"
73        fields_list = []
74        for field in self._meta.fields:
75            fields_list.append({'name': field.name, 'value': getattr(self, field.name)})
76        return fields_list
77
78    @classmethod
79    def get_dom_name(cls):
80        "Convert the class name to a DOM element name"
81        clsname = cls.__name__
82        return clsname[0].lower() + clsname[1:]
83
84    @staticmethod
85    def get_dom_field_name(field_name):
86        "Convert the class name to a DOM element name"
87        tokens = field_name.split('_')
88        name = tokens[0]
89        for t in tokens[1:]:
90            name += t[0].upper() + t[1:]
91        return name
92
93    def to_dom(self):
94        "Return the DOM representation of this media object"
95        impl = getDOMImplementation()
96        root = self.get_dom_name()
97        doc = impl.createDocument(None, root, None)
98        top = doc.documentElement
99        top.setAttribute("id", str(self.id))
100        fields = self.to_dict()
101        for name, value in fields.iteritems():
102            element = doc.createElement(self.get_dom_field_name(name))
103            if isinstance(value, models.Model):
104                element.setAttribute('key', str(value.pk))
105            value = unicode(value)
106            element.appendChild(doc.createTextNode(value))
107            top.appendChild(element)
108        return doc
109   
110    def is_well_formed_id(cls, value):
111        "Check if the media id is well formed"
112        regex = re.compile(r"^" + media_id_regex + r"$")
113        if regex.match(value):
114            return True 
115        else:
116            return False
117    is_well_formed_id = classmethod(is_well_formed_id)
118
119    class Meta:
120        abstract = True
121
122class MetaCore:
123    app_label = 'telemeta'
124
125class MediaCollection(MediaCore):
126    "Describe a collection of items"
127    PUBLIC_ACCESS_CHOICES = (('none', 'none'), ('metadata', 'metadata'), ('metadata', 'full'))
128
129    reference             = models.CharField(unique=True, max_length=250,
130                                             null=True)
131    physical_format       = models.ForeignKey('PhysicalFormat', related_name="collections", 
132                                              null=True, default=None)
133    old_code              = models.CharField(unique=True, max_length=250, null=True)
134    code                  = models.CharField(unique=True, max_length=250)
135    title                 = models.CharField(max_length=250)
136    alt_title             = models.CharField(max_length=250, default="")
137    physical_items_num    = models.IntegerField(default=0)
138    publishing_status     = models.ForeignKey('PublishingStatus', related_name="collections",
139                                              null=True)
140    creator               = models.CharField(max_length=250, default="")
141    booklet_author        = models.CharField(max_length=250, default="")
142    booklet_description   = models.TextField(default="")
143    collector             = models.CharField(max_length=250, default="")
144    collector_is_creator  = models.BooleanField(default="")
145    publisher             = models.ForeignKey('Publisher', related_name="collections",
146                                              null=True)     
147    is_published          = models.BooleanField(default="")
148    year_published        = models.IntegerField(default=0)
149    publisher_collection  = models.ForeignKey('PublisherCollection', related_name="collections",
150                                              null=True)
151    publisher_serial      = models.CharField(max_length=250, default="")
152    external_references   = models.TextField(default="")
153    acquisition_mode      = models.ForeignKey('AcquisitionMode', related_name="collections",
154                                              null=True)
155    comment               = models.TextField(default="")
156    metadata_author       = models.ForeignKey('MetadataAuthor', related_name="collections",
157                                              null=True)
158    metadata_writer       = models.ForeignKey('MetadataWriter', related_name="collections",
159                                              null=True)
160    legal_rights          = models.ForeignKey('LegalRight', related_name="collections",
161                                              null=True)
162    alt_ids               = models.CharField(max_length=250, default="")
163    recorded_from_year    = models.IntegerField(default=0)
164    recorded_to_year      = models.IntegerField(default=0)
165    recording_context     = models.ForeignKey('RecordingContext', related_name="collections",
166                                              null=True)
167    approx_duration       = models.TimeField(default='00:00')
168    doctype_code          = models.IntegerField(default=0)
169    travail               = models.CharField(max_length=250, default="")
170    state                 = models.TextField(default="")
171    cnrs_contributor      = models.CharField(max_length=250, default="")
172    items_done            = models.CharField(max_length=250, default="")
173    a_informer_07_03      = models.CharField(max_length=250, default="")
174    ad_conversion         = models.ForeignKey('AdConversion', related_name='collections',
175                                              null=True)
176    public_access         = models.CharField(choices=PUBLIC_ACCESS_CHOICES, max_length=16, default="metadata")
177
178    objects               = query.MediaCollectionManager()
179
180    def __unicode__(self):
181        return self.code
182
183    def save(self, force_insert=False, force_update=False, using=None):
184        raise MissingUserError("save() method disabled, use save_by_user()")
185
186    def save_by_user(self, user, force_insert=False, force_update=False, using=None):
187        "Save a collection and add a revision"
188        super(MediaCollection, self).save(force_insert, force_update, using)
189        Revision(element_type='collection', element_id=self.id, user=user).touch()   
190
191    class Meta(MetaCore):
192        db_table = 'media_collections'
193
194class MediaItem(MediaCore):
195    "Describe an item"
196    PUBLIC_ACCESS_CHOICES = (('none', 'none'), ('metadata', 'metadata'), ('full', 'full'))
197
198    collection            = models.ForeignKey('MediaCollection', related_name="items")
199    track                 = models.CharField(max_length=250, default="")
200    old_code              = models.CharField(unique=True, max_length=250, null=True)
201    code                  = models.CharField(unique=True, max_length=250, null=True)
202    approx_duration       = models.TimeField(default='00:00')
203    recorded_from_date    = models.DateField(default=0)
204    recorded_to_date      = models.DateField(default=0)
205    location              = models.ForeignKey('Location', related_name="items",
206                                              db_column='location_name', null=True, default="")
207    location_comment      = models.CharField(max_length=250, default="")
208    ethnic_group          = models.ForeignKey('EthnicGroup', related_name="items",
209                                              null=True)
210    title                 = models.CharField(max_length=250)
211    alt_title             = models.CharField(max_length=250, default="")
212    author                = models.CharField(max_length=250, default="")
213    vernacular_style      = models.ForeignKey('VernacularStyle', related_name="items",
214                                              null=True)
215    context_comment       = models.TextField(default="")
216    external_references   = models.TextField(default="")
217    moda_execut           = models.CharField(max_length=250, default="")
218    copied_from_item      = models.ForeignKey('self', related_name="copies",
219                                              null=True)
220    collector             = models.CharField(max_length=250, default="")
221    cultural_area         = models.CharField(max_length=250, default="")
222    generic_style         = models.ForeignKey('GenericStyle', related_name="items",
223                                              null=True)
224    collector_selection   = models.CharField(max_length=250, default="")
225    creator_reference     = models.CharField(max_length=250, default="")
226    comment               = models.TextField(default="")
227    filename              = models.CharField(max_length=250, default="")
228    public_access         = models.CharField(choices=PUBLIC_ACCESS_CHOICES, 
229                                             max_length=16, default="metadata")
230
231    objects               = query.MediaItemManager()
232
233    class Meta(MetaCore):
234        db_table = 'media_items'
235
236    def __unicode__(self):
237        if self.code:
238            return self.code
239        return self.old_code
240
241    def save(self, force_insert=False, force_update=False):
242        raise MissingUserError("save() method disabled, use save_by_user()")
243
244    def save_by_user(self, user, force_insert=False, force_update=False):
245        "Save an item and add a revision"
246        super(MediaItem, self).save(force_insert, force_update)
247        Revision(element_type='item', element_id=self.id, user=user).touch()   
248
249class MediaPart(MediaCore):
250    "Describe an item part"
251    item  = models.ForeignKey('MediaItem', related_name="parts")
252    title = models.CharField(max_length=250)
253    start = models.FloatField()
254    end   = models.FloatField()
255   
256    class Meta(MetaCore):
257        db_table = 'media_parts'
258
259    def __unicode__(self):
260        return self.title
261
262class PhysicalFormat(ModelCore):
263    "Collection physical format"
264    value = models.CharField(max_length=250, unique=True)
265   
266    class Meta(MetaCore):
267        db_table = 'physical_formats'
268
269class PublishingStatus(ModelCore):
270    "Collection publishing status"
271    value = models.CharField(max_length=250, unique=True)
272
273    class Meta(MetaCore):
274        db_table = 'publishing_status'
275
276class AcquisitionMode(ModelCore):
277    "Mode of acquisition of the collection"
278    value = models.CharField(max_length=250, unique=True)
279
280    class Meta(MetaCore):
281        db_table = 'acquisition_modes'
282
283class MetadataAuthor(ModelCore):
284    "Collection metadata author"
285    value = models.CharField(max_length=250, unique=True)
286
287    class Meta(MetaCore):
288        db_table = 'metadata_authors'
289
290class MetadataWriter(ModelCore): 
291    "Collection metadata writer"
292    value = models.CharField(max_length=250, unique=True)
293
294    class Meta(MetaCore):
295        db_table = 'metadata_writers'
296
297class LegalRight(ModelCore):
298    "Collection legal rights" 
299    value = models.CharField(max_length=250, unique=True)
300
301    class Meta(MetaCore):
302        db_table = 'legal_rights'
303
304class RecordingContext(ModelCore):
305    "Collection recording context"
306    value = models.CharField(max_length=250, unique=True)
307
308    class Meta(MetaCore):
309        db_table = 'recording_contexts'
310
311class AdConversion(ModelCore):
312    "Collection digital to analog conversion status"
313    value = models.CharField(max_length=250, unique=True)
314
315    class Meta(MetaCore):
316        db_table = 'ad_conversions'
317
318class VernacularStyle(ModelCore):
319    "Item vernacular style"
320    value = models.CharField(max_length=250, unique=True)
321
322    class Meta(MetaCore):
323        db_table = 'vernacular_styles'
324
325class GenericStyle(ModelCore):
326    "Item generic style"
327    value = models.CharField(max_length=250, unique=True)
328
329    class Meta(MetaCore):
330        db_table = 'generic_styles'
331
332class Instrument(ModelCore):
333    "Instrument used in the item"
334    name    = models.CharField(max_length=250)
335
336    class Meta(MetaCore):
337        db_table = 'instruments'
338
339class InstrumentAlias(ModelCore):
340    "Instrument other name"
341    name = models.CharField(max_length=250)
342
343    class Meta(MetaCore):
344        db_table = 'instrument_aliases'
345
346class InstrumentRelation(ModelCore):
347    "Instrument family"
348    instrument        = models.ForeignKey('Instrument', related_name="parent_relation")
349    parent_instrument = models.ForeignKey('Instrument', related_name="child_relation")
350
351    class Meta(MetaCore):
352        db_table = 'instrument_relations'
353        unique_together = (('instrument', 'parent_instrument'),)
354
355class InstrumentAliasRelation(ModelCore):
356    "Instrument family other name"
357    alias      = models.ForeignKey('InstrumentAlias', related_name="other_name")
358    instrument = models.ForeignKey('InstrumentAlias', related_name="relation")
359
360    class Meta(MetaCore):
361        db_table = 'instrument_alias_relations'
362        unique_together = (('alias', 'instrument'),)
363
364class MediaItemPerformance(ModelCore):
365    "Item performance"
366    media_item      = models.ForeignKey('MediaItem', related_name="performances")
367    instrument      = models.ForeignKey('Instrument', related_name="performances",
368                                        null=True)
369    alias           = models.ForeignKey('InstrumentAlias', related_name="performances",
370                                        null=True)
371    instruments_num = models.CharField(max_length=250, default="")
372    musicians       = models.CharField(max_length=250, default="")
373
374    class Meta(MetaCore):
375        db_table = 'media_item_performances'
376
377class User(ModelCore):
378    "Telemeta user"
379    LEVEL_CHOICES = (('user', 'user'), ('maintainer', 'maintainer'), ('admin', 'admin'))   
380
381    username   = models.CharField(primary_key=True, max_length=64)
382    level      = models.CharField(choices=LEVEL_CHOICES, max_length=250)
383    first_name = models.CharField(max_length=250, default="")
384    last_name  = models.CharField(max_length=250, default="")
385    phone      = models.CharField(max_length=250, default="")
386    email      = models.CharField(max_length=250, default="")
387
388    class Meta(MetaCore):
389        db_table = 'users'
390
391class Playlist(ModelCore):
392    "Item or collection playlist"
393    owner_username = models.ForeignKey('User', related_name="playlists", db_column="owner_username") 
394    name           = models.CharField(max_length=250)
395
396    class Meta(MetaCore):
397        db_table = 'playlists'
398
399class PlaylistResource(ModelCore):
400    "Playlist components"
401    RESOURCE_TYPE_CHOICES = (('item', 'item'), ('collection', 'collection'))
402
403    playlist              = models.ForeignKey('Playlist', related_name="resources")
404    resource_type         = models.CharField(choices=RESOURCE_TYPE_CHOICES, max_length=250)
405    resource              = models.IntegerField()
406
407    class Meta(MetaCore):
408        db_table = 'playlist_resources'
409
410class Location(ModelCore):
411    "Item location"
412    TYPE_CHOICES     = (('country', 'country'), ('continent', 'continent'), ('other', 'other'))
413
414    name             = models.CharField(primary_key=True, max_length=150)
415    type             = models.CharField(choices=TYPE_CHOICES, max_length=16)
416    complete_type    = models.ForeignKey('LocationType', related_name="types")
417    current_name     = models.ForeignKey('self', related_name="past_names", 
418                                         db_column="current_name", null=True) 
419    is_authoritative = models.BooleanField(default=0)
420
421    class Meta(MetaCore):
422        db_table = 'locations'
423
424    def __unicode__(self):
425        return self.name
426
427class LocationType(ModelCore):
428    "Location type of an item location"
429    id   = models.CharField(max_length=64, primary_key=True)
430    name = models.CharField(max_length=150)
431
432    class Meta(MetaCore):
433        db_table = 'location_types'
434
435class LocationAlias(ModelCore):
436    "Location other name"
437    location_name    = models.ForeignKey('Location', related_name="aliases",
438                                          db_column="location_name", max_length=150)
439    alias            = models.CharField(max_length=150)
440    is_authoritative = models.BooleanField(default=0)
441
442    class Meta(MetaCore):
443        db_table = 'location_aliases'
444        unique_together = (('location_name', 'alias'),)
445   
446class LocationRelation(ModelCore):
447    "Location family"
448    location_name        = models.ForeignKey('Location', related_name="parent_relations",
449                                              db_column="location_name", max_length=150)
450    parent_location_name = models.ForeignKey('Location', related_name="child_relations",
451                                              db_column="parent_location_name", null=True, max_length=150)
452    is_authoritative     = models.BooleanField()
453
454    class Meta(MetaCore):
455        db_table = 'location_relations'
456   
457class ContextKeyword(ModelCore):
458    "Keyword"
459    value = models.CharField(max_length=250)
460
461    class Meta(MetaCore):
462        db_table = 'context_keywords'
463
464class MediaItemKeyword(ModelCore):
465    "Item keyword"
466    item    = models.ForeignKey('MediaItem')
467    keyword = models.ForeignKey('ContextKeyword')
468
469    class Meta(MetaCore):
470        db_table = 'media_item_keywords'
471        unique_together = (('item', 'keyword'),)
472
473class Publisher(ModelCore): 
474    "Collection publisher"
475    value = models.CharField(max_length=250, unique=True)
476
477    class Meta(MetaCore):
478        db_table = 'publishers'
479
480class PublisherCollection(ModelCore):
481    "Collection which belongs to publisher"
482    publisher = models.ForeignKey('Publisher', related_name="publisher_collections")
483    value     = models.CharField(max_length=250)
484
485    class Meta(MetaCore):
486        db_table = 'publisher_collections'
487
488class Revision(ModelCore):
489    "Revision made by user"
490    ELEMENT_TYPE_CHOICES = (('collection', 'collection'), ('item', 'item'), ('part', 'part'))
491    CHANGE_TYPE_CHOICES  = (('import', 'import'), ('create', 'create'), ('update', 'update'), ('delete','delete'))
492
493    element_type         = models.CharField(choices=ELEMENT_TYPE_CHOICES, max_length=16)
494    element_id           = models.IntegerField()
495    change_type          = models.CharField(choices=CHANGE_TYPE_CHOICES, max_length=16)
496    time                 = models.DateTimeField(auto_now_add=True)
497    user                 = models.ForeignKey('User', db_column='username', related_name="revisions")
498   
499    def touch(self):   
500        "Create or update a revision"
501        q = Revision.objects.filter(element_type=self.element_type, element_id=self.element_id)
502        if q.count():
503            self.change_type = 'update'
504        else:
505            self.change_type = 'create'
506        self.save()
507
508    class Meta(MetaCore):
509        db_table = 'revisions'
510   
511class EthnicGroup(ModelCore):
512    "Item ethnic group"
513    name = models.CharField(max_length=250)
514
515    class Meta(MetaCore):
516        db_table = 'ethnic_groups'
517
518    def __unicode__(self):
519        return self.name
520
521class EthnicGroupAlias(ModelCore):
522    "Item ethnic group other name" 
523    ethnic_group = models.ForeignKey('EthnicGroup', related_name="aliases")
524    name         = models.CharField(max_length=250)
525
526    class Meta(MetaCore):
527        db_table = 'ethnic_group_aliases'
528
529
530class MissingUserError(Exception):
531    pass
532
533class RequiredFieldError(Exception):
534    def __init__(self, model, field):
535        self.model = model
536        self.field = field
537        super(Exception, self).__init__('%s.%s is required' % (model._meta.object_name, field.name))
Note: See TracBrowser for help on using the repository browser.