]> git.parisson.com Git - telemeta.git/commitdiff
- rename MediaCollection.location_name to location as it should have been
authorolivier <>
Tue, 19 Jan 2010 17:05:33 +0000 (17:05 +0000)
committerolivier <>
Tue, 19 Jan 2010 17:05:33 +0000 (17:05 +0000)
- let all models descend from ModelCore and media models from MediaCore
- implement model-level required fields validation
- consolidate unit tests

telemeta/models/crem.py
telemeta/models/cremquery.py
telemeta/tests/model_tests.py

index 58c4ccb23109f2130afcf8d6b088b9f79c8c9222..3e5820a006540c3626e1e33b6eb8073722f03bd1 100755 (executable)
 from django.db import models
 import cremquery as query
 
-class MediaCore(object):
+class ModelCore(models.Model):
+
+    @classmethod
+    def required_fields(cls):
+        required = []
+        for field in cls._meta.fields:
+            if (field != cls._meta.pk and field.default == models.fields.NOT_PROVIDED and
+                    not field.null and not getattr(field, 'auto_now_add', False)):
+                required.append(field)
+        return required
+
+    def save(self, force_insert=False, force_update=False, using=None):
+        required = self.required_fields()
+        for field in required:
+            if not getattr(self, field.name):
+                raise RequiredFieldError(self, field)
+        super(ModelCore, self).save(force_insert, force_update, using)
+
+    class Meta:
+        abstract = True
+
+class MediaCore(ModelCore):
     "Base class of all media objects"
 
     def to_dict(self):  
@@ -83,18 +104,21 @@ class MediaCore(object):
             return False
     is_well_formed_id = classmethod(is_well_formed_id)
 
+    class Meta:
+        abstract = True
+
 class MetaCore:
     app_label = 'telemeta'
 
-class MediaCollection(models.Model):
+class MediaCollection(MediaCore):
     "Describe a collection of items"
     PUBLIC_ACCESS_CHOICES = (('none', 'none'), ('metadata', 'metadata'), ('metadata', 'full'))
 
     reference             = models.CharField(unique=True, max_length=250,
                                              null=True)
     physical_format       = models.ForeignKey('PhysicalFormat', related_name="collections", 
-                                              null=True)
-    old_code              = models.CharField(unique=True, max_length=250)
+                                              null=True, default=None)
+    old_code              = models.CharField(unique=True, max_length=250, null=True)
     code                  = models.CharField(unique=True, max_length=250)
     title                 = models.CharField(max_length=250)
     alt_title             = models.CharField(max_length=250, default="")
@@ -127,7 +151,7 @@ class MediaCollection(models.Model):
     recorded_to_year      = models.IntegerField(default=0)
     recording_context     = models.ForeignKey('RecordingContext', related_name="collections",
                                               null=True)
-    approx_duration       = models.TimeField(default=0)
+    approx_duration       = models.TimeField(default='00:00')
     doctype_code          = models.IntegerField(default=0)
     travail               = models.CharField(max_length=250, default="")
     state                 = models.TextField(default="")
@@ -143,29 +167,29 @@ class MediaCollection(models.Model):
     def __unicode__(self):
         return self.code
 
-    def save(self, force_insert=False, force_update=False):
+    def save(self, force_insert=False, force_update=False, using=None):
         raise MissingUserError("save() method disabled, use save_by_user()")
 
-    def save_by_user(self, user, force_insert=False, force_update=False):
+    def save_by_user(self, user, force_insert=False, force_update=False, using=None):
         "Save a collection and add a revision"
-        super(MediaCollection, self).save(force_insert, force_update)
+        super(MediaCollection, self).save(force_insert, force_update, using)
         Revision(element_type='collection', element_id=self.id, user=user).touch()    
 
     class Meta(MetaCore):
         db_table = 'media_collections'
 
-class MediaItem(models.Model):
+class MediaItem(MediaCore):
     "Describe an item"
     PUBLIC_ACCESS_CHOICES = (('none', 'none'), ('metadata', 'metadata'), ('full', 'full'))
 
     collection            = models.ForeignKey('MediaCollection', related_name="items")
     track                 = models.CharField(max_length=250, default="")
-    old_code              = models.CharField(unique=True, max_length=250)
+    old_code              = models.CharField(unique=True, max_length=250, null=True)
     code                  = models.CharField(unique=True, max_length=250, null=True)
-    approx_duration       = models.TimeField(default=0)
+    approx_duration       = models.TimeField(default='00:00')
     recorded_from_date    = models.DateField(default=0)
     recorded_to_date      = models.DateField(default=0)
-    location_name         = models.ForeignKey('Location', related_name="items",
+    location              = models.ForeignKey('Location', related_name="items",
                                               db_column='location_name', null=True, default="")
     location_comment      = models.CharField(max_length=250, default="")
     ethnic_group          = models.ForeignKey('EthnicGroup', related_name="items",
@@ -209,7 +233,7 @@ class MediaItem(models.Model):
         super(MediaItem, self).save(force_insert, force_update)
         Revision(element_type='item', element_id=self.id, user=user).touch()    
 
-class MediaPart(models.Model):
+class MediaPart(MediaCore):
     "Describe an item part"
     item  = models.ForeignKey('MediaItem', related_name="parts")
     title = models.CharField(max_length=250)
@@ -222,91 +246,91 @@ class MediaPart(models.Model):
     def __unicode__(self):
         return self.title
 
-class PhysicalFormat(models.Model):
+class PhysicalFormat(ModelCore):
     "Collection physical format"
     value = models.CharField(max_length=250, unique=True)
     
     class Meta(MetaCore):
         db_table = 'physical_formats'
 
-class PublishingStatus(models.Model):
+class PublishingStatus(ModelCore):
     "Collection publishing status"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'publishing_status'
 
-class AcquisitionMode(models.Model):
+class AcquisitionMode(ModelCore):
     "Mode of acquisition of the collection"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'acquisition_modes'
 
-class MetadataAuthor(models.Model):
+class MetadataAuthor(ModelCore):
     "Collection metadata author"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'metadata_authors'
 
-class MetadataWriter(models.Model):  
+class MetadataWriter(ModelCore):  
     "Collection metadata writer"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'metadata_writers'
 
-class LegalRight(models.Model):
+class LegalRight(ModelCore):
     "Collection legal rights" 
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'legal_rights'
 
-class RecordingContext(models.Model):
+class RecordingContext(ModelCore):
     "Collection recording context"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'recording_contexts'
 
-class AdConversion(models.Model):
+class AdConversion(ModelCore):
     "Collection digital to analog conversion status"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'ad_conversions'
 
-class VernacularStyle(models.Model):
+class VernacularStyle(ModelCore):
     "Item vernacular style"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'vernacular_styles'
 
-class GenericStyle(models.Model):
+class GenericStyle(ModelCore):
     "Item generic style"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'generic_styles'
 
-class Instrument(models.Model):
+class Instrument(ModelCore):
     "Instrument used in the item"
     name    = models.CharField(max_length=250)
 
     class Meta(MetaCore):
         db_table = 'instruments'
 
-class InstrumentAlias(models.Model):
+class InstrumentAlias(ModelCore):
     "Instrument other name"
     name = models.CharField(max_length=250)
 
     class Meta(MetaCore):
         db_table = 'instrument_aliases'
 
-class InstrumentRelation(models.Model):
+class InstrumentRelation(ModelCore):
     "Instrument family"
     instrument        = models.ForeignKey('Instrument', related_name="parent_relation")
     parent_instrument = models.ForeignKey('Instrument', related_name="child_relation")
@@ -315,7 +339,7 @@ class InstrumentRelation(models.Model):
         db_table = 'instrument_relations'
         unique_together = (('instrument', 'parent_instrument'),)
 
-class InstrumentAliasRelation(models.Model):
+class InstrumentAliasRelation(ModelCore):
     "Instrument family other name"
     alias      = models.ForeignKey('InstrumentAlias', related_name="other_name")
     instrument = models.ForeignKey('InstrumentAlias', related_name="relation")
@@ -324,7 +348,7 @@ class InstrumentAliasRelation(models.Model):
         db_table = 'instrument_alias_relations'
         unique_together = (('alias', 'instrument'),)
 
-class MediaItemPerformance(models.Model):
+class MediaItemPerformance(ModelCore):
     "Item performance"
     media_item      = models.ForeignKey('MediaItem', related_name="performances")
     instrument      = models.ForeignKey('Instrument', related_name="performances",
@@ -337,7 +361,7 @@ class MediaItemPerformance(models.Model):
     class Meta(MetaCore):
         db_table = 'media_item_performances'
 
-class User(models.Model):
+class User(ModelCore):
     "Telemeta user"
     LEVEL_CHOICES = (('user', 'user'), ('maintainer', 'maintainer'), ('admin', 'admin'))    
 
@@ -351,7 +375,7 @@ class User(models.Model):
     class Meta(MetaCore):
         db_table = 'users'
 
-class Playlist(models.Model):
+class Playlist(ModelCore):
     "Item or collection playlist"
     owner_username = models.ForeignKey('User', related_name="playlists", db_column="owner_username") 
     name           = models.CharField(max_length=250)
@@ -359,7 +383,7 @@ class Playlist(models.Model):
     class Meta(MetaCore):
         db_table = 'playlists'
 
-class PlaylistResource(models.Model):
+class PlaylistResource(ModelCore):
     "Playlist components"
     RESOURCE_TYPE_CHOICES = (('item', 'item'), ('collection', 'collection'))
 
@@ -370,7 +394,7 @@ class PlaylistResource(models.Model):
     class Meta(MetaCore):
         db_table = 'playlist_resources'
 
-class Location(models.Model):
+class Location(ModelCore):
     "Item location"
     TYPE_CHOICES     = (('country', 'country'), ('continent', 'continent'), ('other', 'other'))
 
@@ -387,7 +411,7 @@ class Location(models.Model):
     def __unicode__(self):
         return self.name
 
-class LocationType(models.Model):
+class LocationType(ModelCore):
     "Location type of an item location"
     id   = models.CharField(max_length=64, primary_key=True)
     name = models.CharField(max_length=150)
@@ -395,7 +419,7 @@ class LocationType(models.Model):
     class Meta(MetaCore):
         db_table = 'location_types'
 
-class LocationAlias(models.Model):
+class LocationAlias(ModelCore):
     "Location other name"
     location_name    = models.ForeignKey('Location', related_name="aliases",
                                           db_column="location_name", max_length=150)
@@ -406,7 +430,7 @@ class LocationAlias(models.Model):
         db_table = 'location_aliases'
         unique_together = (('location_name', 'alias'),)
     
-class LocationRelation(models.Model):
+class LocationRelation(ModelCore):
     "Location family"
     location_name        = models.ForeignKey('Location', related_name="parent_relations",
                                               db_column="location_name", max_length=150)
@@ -417,14 +441,14 @@ class LocationRelation(models.Model):
     class Meta(MetaCore):
         db_table = 'location_relations'
     
-class ContextKeyword(models.Model):
+class ContextKeyword(ModelCore):
     "Keyword"
     value = models.CharField(max_length=250)
 
     class Meta(MetaCore):
         db_table = 'context_keywords'
 
-class MediaItemKeyword(models.Model):
+class MediaItemKeyword(ModelCore):
     "Item keyword"
     item    = models.ForeignKey('MediaItem')
     keyword = models.ForeignKey('ContextKeyword')
@@ -433,14 +457,14 @@ class MediaItemKeyword(models.Model):
         db_table = 'media_item_keywords'
         unique_together = (('item', 'keyword'),)
 
-class Publisher(models.Model): 
+class Publisher(ModelCore): 
     "Collection publisher"
     value = models.CharField(max_length=250, unique=True)
 
     class Meta(MetaCore):
         db_table = 'publishers'
 
-class PublisherCollection(models.Model):
+class PublisherCollection(ModelCore):
     "Collection which belongs to publisher"
     publisher = models.ForeignKey('Publisher', related_name="publisher_collections")
     value     = models.CharField(max_length=250)
@@ -448,7 +472,7 @@ class PublisherCollection(models.Model):
     class Meta(MetaCore):
         db_table = 'publisher_collections'
 
-class Revision(models.Model):
+class Revision(ModelCore):
     "Revision made by user"
     ELEMENT_TYPE_CHOICES = (('collection', 'collection'), ('item', 'item'), ('part', 'part'))
     CHANGE_TYPE_CHOICES  = (('import', 'import'), ('create', 'create'), ('update', 'update'), ('delete','delete'))
@@ -471,7 +495,7 @@ class Revision(models.Model):
     class Meta(MetaCore):
         db_table = 'revisions'
     
-class EthnicGroup(models.Model):
+class EthnicGroup(ModelCore):
     "Item ethnic group"
     name = models.CharField(max_length=250)
 
@@ -481,7 +505,7 @@ class EthnicGroup(models.Model):
     def __unicode__(self):
         return self.name
 
-class EthnicGroupAlias(models.Model):
+class EthnicGroupAlias(ModelCore):
     "Item ethnic group other name" 
     ethnic_group = models.ForeignKey('EthnicGroup', related_name="aliases")
     name         = models.CharField(max_length=250)
@@ -492,3 +516,9 @@ class EthnicGroupAlias(models.Model):
 
 class MissingUserError(Exception):
     pass
+
+class RequiredFieldError(Exception):
+    def __init__(self, model, field):
+        self.model = model
+        self.field = field
+        super(Exception, self).__init__('%s.%s is required' % (model._meta.object_name, field.name))
index 1436347d5a57c11bacc38511fdc2a7552585e586..c46a309a347ca6f19e89511a76dbe936260c2522 100644 (file)
@@ -86,11 +86,11 @@ class MediaCollectionQuerySet(CoreQuerySet):
 
     def by_country(self, country):
         "Find collections by country"
-        return self.filter(items__location_name__type="country", items__location_name=country).distinct()
+        return self.filter(items__location__type="country", items__location=country).distinct()
     
     def by_continent(self, continent):
         "Find collections by continent"
-        return self.filter(items__location_name__type="continent", items__location_name=continent).distinct()
+        return self.filter(items__location__type="continent", items__location=continent).distinct()
 
     def by_recording_year(self, from_year, to_year=None):
         "Find collections by recording year"
index 5dd793c14e3be976ed7c34eb8a2de06aa15fb4a0..e90729950d6e9ffc0c548f8a5819686a7f7a7aa6 100644 (file)
@@ -34,7 +34,7 @@
 #          David LIPSZYC <davidlipszyc@gmail.com>
 
 import unittest
-from telemeta.models import MediaCollection, MediaItem, Location, EthnicGroup, LocationType, User, Revision
+from telemeta.models import MediaCollection, MediaItem, Location, EthnicGroup, LocationType, User, Revision, RequiredFieldError
 from datetime import datetime, timedelta
 
 class CollectionItemTestCase(unittest.TestCase):
@@ -42,21 +42,19 @@ class CollectionItemTestCase(unittest.TestCase):
         "Create a test database based on objects created in Django"
    
         User.objects.all().delete() 
-        self.david   = User.objects.create(username="david", level="user", first_name="david", last_name="aaa", phone="0156565656",
-                       email="david@a.com")
-        self.olivier = User.objects.create(username="olivier", level="admin", first_name="olivier", last_name="bbb", 
-                       phone="0155555555", email="olivier@a.com")    
+        self.david   = User.objects.create(username="david", level="user")
+        self.olivier = User.objects.create(username="olivier", level="admin")    
 
         LocationType.objects.all().delete()
-        self.country = LocationType.objects.create(id="country", name="country")
-        self.continent = LocationType.objects.create(id="continent", name="continent")
-        self.city = LocationType.objects.create(id="city", name="city")
+        self.country = LocationType.objects.create(id="country", name="Country")
+        self.continent = LocationType.objects.create(id="continent", name="Continent")
+        self.city = LocationType.objects.create(id="city", name="City")
 
         Location.objects.all().delete()        
-        self.paris = Location.objects.create(name="Paris", type="other", complete_type=self.city, is_authoritative=0)
-        self.france = Location.objects.create(name="France", type="country", complete_type=self.country, is_authoritative=0)
-        self.europe = Location.objects.create(name="Europe", type="continent", complete_type=self.continent, is_authoritative=0)
-        self.belgique = Location.objects.create(name="Belgique", type="country", complete_type=self.country, is_authoritative=0)
+        self.paris = Location.objects.create(name="Paris", type="other", complete_type=self.city)
+        self.france = Location.objects.create(name="France", type="country", complete_type=self.country)
+        self.europe = Location.objects.create(name="Europe", type="continent", complete_type=self.continent)
+        self.belgique = Location.objects.create(name="Belgique", type="country", complete_type=self.country)
 
         EthnicGroup.objects.all().delete()
         self.a = EthnicGroup.objects.create(name="a")
@@ -65,126 +63,64 @@ class CollectionItemTestCase(unittest.TestCase):
         self.d = EthnicGroup.objects.create(name="d")
 
         MediaCollection.objects.all().delete()
-        self.persepolis = MediaCollection(id=1, reference="A1", physical_format_id=1111, old_code="10", code="100",                                                          title="persepolis", alt_title="bjr", creator="Abraham LINCOLN", 
-                                          booklet_author="Maria BALTHAZAR", 
-                                          booklet_description="compilation de mots français", 
-                                          collector="Friedrich HEINZ", collector_is_creator=0, publisher_id=1442, 
-                                          year_published=2009, publisher_collection_id=1234, 
-                                          publisher_serial="123456", external_references="Larousse", 
-                                          acquisition_mode_id=1, comment="chants", metadata_author_id=1, 
-                                          metadata_writer_id=1, legal_rights_id=1, alt_ids="89", 
-                                          recorded_from_year=1970, recorded_to_year=1980, recording_context_id=1, 
-                                          approx_duration="5:00:00", doctype_code=1357, travail="travail", 
-                                          state="etat", cnrs_contributor="Jean PETIT", items_done="fiches", 
-                                          a_informer_07_03="a informer", ad_conversion_id=9, public_access="full")
+        self.persepolis = MediaCollection(id=1, code="100", reference="A1", title="persepolis", 
+            creator="Abraham LINCOLN", collector="Friedrich HEINZ", year_published=2009,  
+            recorded_from_year=1970, recorded_to_year=1980)
         
         self.persepolis.save_by_user(self.david)
 
-        self.volonte = MediaCollection(id=2, reference="A2", physical_format_id=222, old_code="20", code="200", 
-                                       title="Volonté de puissance", alt_title="ar", creator="Friedrich NIETZSCHE", 
-                                       booklet_author="George POMPIDOU", booklet_description="notice numero 2", 
-                                       collector="Jean AMORA", collector_is_creator=0, publisher_id=2884, 
-                                       year_published=1999, publisher_collection_id=2345, 
-                                       publisher_serial="234567", external_references="dico", 
-                                       acquisition_mode_id=2, comment="commentaire 2", metadata_author_id=2, 
-                                       metadata_writer_id=2, legal_rights_id=2, alt_ids="78", 
-                                       recorded_from_year=1960, recorded_to_year=2000, recording_context_id=2, 
-                                       approx_duration="1:00:00", doctype_code=2468, travail="travail 2", 
-                                       state="etat 2", cnrs_contributor="Richard LIONHEART", items_done="fiches 2", 
-                                       a_informer_07_03="a informer 2", ad_conversion_id=8, 
-                                       public_access="metadata")
+        self.volonte = MediaCollection(id=2, reference="A2",  code="200", title="Volonté de puissance", 
+            creator="Friedrich NIETZSCHE", collector="Jean AMORA", year_published=1999,  
+            recorded_from_year=1960, recorded_to_year=2000)
 
         self.volonte.save_by_user(self.olivier)
 
-        self.nicolas = MediaCollection(id=3, reference="A3", physical_format_id=333, old_code="30", code="300", 
-                                       title="petit nicolas", alt_title="slt", creator="Georgette McKenic", 
-                                       booklet_author="Francesca DICORTO", booklet_description="notice 3", 
-                                       collector="Paul MAILLE", collector_is_creator=0, publisher_id=3773, 
-                                       year_published=1999, publisher_collection_id=7890, publisher_serial="8764", 
-                                       external_references="ref externes", acquisition_mode_id=3, 
-                                       comment="commentaire 3", metadata_author_id=3, metadata_writer_id=3, 
-                                       legal_rights_id=3, alt_ids="56", recorded_from_year=1967, 
-                                       recorded_to_year=1968, recording_context_id=3, approx_duration="0:00:00", 
-                                       doctype_code=5790, travail="travail 3", state="etat 3", 
-                                       cnrs_contributor="Gerard MICKAEL", items_done="fiches 3", 
-                                       a_informer_07_03="a informer 3", ad_conversion_id=8, public_access="none")
+        self.nicolas = MediaCollection(id=3, reference="A3",  code="300", title="petit nicolas", 
+            creator="Georgette McKenic", collector="Paul MAILLE",  year_published=1999,  
+            recorded_from_year=1967, recorded_to_year=1968)
                                    
         self.nicolas.save_by_user(self.olivier)
      
         MediaItem.objects.all().delete()        
-        self.item_1 = MediaItem(id=1, collection=self.persepolis, track="1111", old_code="101", code="1010", 
-                                approx_duration="00:01:00", recorded_from_date="1971-01-12", 
-                                recorded_to_date="1971-02-24", location_name=self.paris, 
-                                location_comment="capital de la France", ethnic_group=self.a, 
-                                title="item 1", alt_title="I1", author="Mickael SHEPHERD", 
-                                context_comment="contexte ethno 1", external_references="ext ref 1", 
-                                moda_execut="moda exec 1",copied_from_item_id=99, 
-                                collector="Charles PREMIER", cultural_area="Ile de France", generic_style_id=1, 
-                                collector_selection="collec sel 1", creator_reference="ref du deposant 1", 
-                                comment="comment 1", filename="item 1.item", public_access="full") 
+        self.item_1 = MediaItem(id=1, collection=self.persepolis, code="1010", 
+            recorded_from_date="1971-01-12", recorded_to_date="1971-02-24", location=self.paris, 
+            ethnic_group=self.a, title="item 1", author="Mickael SHEPHERD", collector="Charles PREMIER",  
+            comment="comment 1") 
 
         self.item_1.save_by_user(self.david)
 
-        self.item_2 = MediaItem(id=2, collection=self.volonte, track="2222", old_code="202", code="2020", 
-                                approx_duration="00:02:00", recorded_from_date="1981-01-12", 
-                                recorded_to_date="1991-02-24", location_name=self.france, 
-                                location_comment="loc comment 2", ethnic_group=self.a, title="item 2",
-                                alt_title="I2", author="Rick ROLL", context_comment="contexte ethno 2", 
-                                external_references="ext ref 2", moda_execut="moda exec 2", 
-                                copied_from_item_id=98, collector="Gerard LENORMAND", 
-                                cultural_area="Nord de la France", generic_style_id=1,
-                                collector_selection="collec sel 2", creator_reference="ref du deposant 2", 
-                                comment="comment 2", filename="item 2.item", public_access="metadata") 
+        self.item_2 = MediaItem(id=2, collection=self.volonte, code="2020", 
+            recorded_from_date="1981-01-12", recorded_to_date="1991-02-24", location=self.france, 
+            ethnic_group=self.a, title="item 2", author="Rick ROLL", comment="comment 2") 
 
         self.item_2.save_by_user(self.david)
 
-        self.item_3 = MediaItem(id=3, collection=self.nicolas, track="3333", old_code="303", code="3030", 
-                                approx_duration="00:03:00", recorded_from_date="1968-01-12", 
-                                recorded_to_date="1968-02-24", location_name=self.belgique, 
-                                location_comment="en Europe", ethnic_group=self.b, title="item 3", 
-                                alt_title="I3", author="John SMITH", context_comment="contexte ethno 3", 
-                                external_references="ext ref 3", moda_execut="moda exec 3", copied_from_item_id=97, 
-                                collector="Paul CARLOS", cultural_area="Europe occidentale", generic_style_id=1,
-                                collector_selection="collec sel 3", creator_reference="ref du deposant 3", 
-                                comment="comment 3", filename="item 3.item", public_access="none")
+        self.item_3 = MediaItem(id=3, collection=self.nicolas, code="3030", 
+            recorded_from_date="1968-01-12", recorded_to_date="1968-02-24", location=self.belgique, 
+            ethnic_group=self.b, title="item 3", author="John SMITH", collector="Paul CARLOS",
+            comment="comment 3",  )
 
         self.item_3.save_by_user(self.olivier)
 
-        self.item_4 = MediaItem(id=4, collection=self.persepolis, track="4444", old_code="404", code="4040", 
-                                approx_duration="00:04:00", recorded_from_date="1972-01-12", 
-                                recorded_to_date="1972-02-24", location_name=self.europe, 
-                                location_comment="loc comm 4", ethnic_group=self.a, title="item 4", 
-                                alt_title="I4", author="Keanu REAVES", context_comment="contexte ethno 4", 
-                                external_references="ext ref 4", moda_execut="moda exec 4", copied_from_item_id=96, 
-                                collector="Christina BARCELONA", cultural_area="aire culturelle 4", 
-                                generic_style_id=1, collector_selection="collec sel 4", 
-                                creator_reference="ref du deposant 4", comment="comment 4", filename="item 4.item",
-                                public_access="none")
+        self.item_4 = MediaItem(id=4, collection=self.persepolis, code="4040", 
+            recorded_from_date="1972-01-12", recorded_to_date="1972-02-24", location=self.europe, 
+            ethnic_group=self.a, title="item 4", alt_title="I4", author="Keanu REAVES", 
+            collector="Christina BARCELONA", comment="comment 4")
 
         self.item_4.save_by_user(self.olivier)
 
-        self.item_5 = MediaItem(id=5, collection=self.volonte, track="5555", old_code="505", code="5050", 
-                                approx_duration="00:05:00", recorded_from_date="1978-01-12", 
-                                recorded_to_date="1978-02-24", location_name=self.belgique, 
-                                location_comment="loc comm 5", ethnic_group=self.a, title="item 5", 
-                                alt_title="I5", author="Simon PAUL", context_comment="contexte ethno 5", 
-                                external_references="ext ref 5", moda_execut="moda exec 5", copied_from_item_id=95, 
-                                collector="Javier BARDEM", cultural_area="aire culturelle 5", generic_style_id=1,
-                                collector_selection="collec sel 5", creator_reference="ref du deposant 5", 
-                                comment="comment 5", filename="item 5.item", public_access="metadata")
+        self.item_5 = MediaItem(id=5, collection=self.volonte,code="5050", 
+            approx_duration="00:05:00", recorded_from_date="1978-01-12", recorded_to_date="1978-02-24", 
+            location=self.belgique, ethnic_group=self.a, title="item 5", alt_title="I5", 
+            author="Simon PAUL", collector="Javier BARDEM", 
+            comment="comment 5")
 
         self.item_5.save_by_user(self.olivier)
 
-        self.item_6 = MediaItem(id=6, collection=self.persepolis, track="10000", old_code="1111111", 
-                                code="6060", approx_duration="10:03:00", recorded_from_date="1968-01-12", 
-                                recorded_to_date="1968-02-11", location_name=self.france, 
-                                location_comment="loc comment 10000", ethnic_group=self.b, 
-                                title="item 6", alt_title="I10000", author="Paul ANDERSON", 
-                                context_comment="contexte ethno 10000", external_references="ext ref 10000", 
-                                moda_execut="moda exec 10000", copied_from_item_id=11111, collector="Jim CARLSON", 
-                                cultural_area="cul area 10000", generic_style_id=1, 
-                                collector_selection="collec sel 10000", creator_reference="ref du deposant 10000", 
-                                comment="comment 10000", filename="item 10000.item", public_access="none")
+        self.item_6 = MediaItem(id=6, collection=self.persepolis, code="6060", 
+            recorded_from_date="1968-01-12", recorded_to_date="1968-02-11", location=self.france, 
+            ethnic_group=self.b, title="item 6", author="Paul ANDERSON", 
+            collector="Jim CARLSON", comment="comment 10000")
         
         self.item_6.save_by_user(self.david)
 
@@ -309,3 +245,13 @@ class CollectionItemTestCase(unittest.TestCase):
     def testWithoutCollection(self):
         "Test without_collection property of MediaItem class"
         self.assertEquals(self.items.without_collection().count(), 0)
+
+    def testCodeRequired(self):
+        c = MediaCollection()
+        try:
+            c.save_by_user(self.olivier)
+        except RequiredFieldError, e:
+            self.assertEquals(e.field.name, 'code')
+        else:
+            self.fail("No exception raised")
+