From 9de0474386c96c7b38c4eab08631284b9bb216d3 Mon Sep 17 00:00:00 2001 From: eric Date: Fri, 17 Oct 2014 17:14:02 -0400 Subject: [PATCH] start moving marc code to its own package --- core/models.py | 8 ++ marc/__init__.py | 0 marc/management/__init__.py | 0 marc/management/commands/__init__.py | 0 marc/management/commands/migrate_records.py | 28 +++++ marc/migrations/0001_initial.py | 73 ++++++++++++ marc/migrations/__init__.py | 0 marc/models.py | 68 ++++++++++++ marc/tests.py | 116 ++++++++++++++++++++ 9 files changed, 293 insertions(+) create mode 100755 marc/__init__.py create mode 100644 marc/management/__init__.py create mode 100644 marc/management/commands/__init__.py create mode 100644 marc/management/commands/migrate_records.py create mode 100644 marc/migrations/0001_initial.py create mode 100644 marc/migrations/__init__.py create mode 100644 marc/models.py create mode 100644 marc/tests.py diff --git a/core/models.py b/core/models.py index cdfa1527..e66b2f19 100755 --- a/core/models.py +++ b/core/models.py @@ -1646,6 +1646,14 @@ class Edition(models.Model): self.publisher_name = pub_name self.save() + # for compatibility with marc outputter + def downloads(self): + return self.ebooks.all() + + # for compatibility with marc outputter + def download_via_url(self): + return settings.BASE_URL_SECURE + reverse('download', args=[self.work.id]) + class Publisher(models.Model): created = models.DateTimeField(auto_now_add=True) name = models.ForeignKey('PublisherName', related_name='key_publisher') diff --git a/marc/__init__.py b/marc/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/marc/management/__init__.py b/marc/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/marc/management/commands/__init__.py b/marc/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/marc/management/commands/migrate_records.py b/marc/management/commands/migrate_records.py new file mode 100644 index 00000000..a627f9f1 --- /dev/null +++ b/marc/management/commands/migrate_records.py @@ -0,0 +1,28 @@ +from django.core.management.base import BaseCommand +from django.core.files.storage import default_storage + +from regluit.marc.models import MARCRecord +from regluit.core.models import MARCRecord as OldRecord + +class Command(BaseCommand): + help = "migrate records from files" + args = "" + + def handle(self, **options): + editions=[] + for old_record in OldRecord.objects.all().order_by('-id'): + if old_record.edition.pk not in editions: + new_record, created = MARCRecord.objects.get_or_create(id=old_record.pk) + try: + xml_file = default_storage.open(old_record.xml_record) + xml_data = xml_file.read() + new_record.guts = xml_data + new_record.edition = old_record.edition + editions.append(old_record.edition.pk) + xml_file.close() + new_record.save() + print 'record %s updated' % new_record.id + except IOError: + if created: + new_record.delete() + print 'failed opening %s' % old_record.xml_record diff --git a/marc/migrations/0001_initial.py b/marc/migrations/0001_initial.py new file mode 100644 index 00000000..c6d7e82f --- /dev/null +++ b/marc/migrations/0001_initial.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'MARCRecord' + db.create_table('marc_marcrecord', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('guts', self.gf('django.db.models.fields.TextField')()), + ('edition', self.gf('django.db.models.fields.related.ForeignKey')(related_name='MARCRecords', null=True, to=orm['core.Edition'])), + )) + db.send_create_signal('marc', ['MARCRecord']) + + + def backwards(self, orm): + # Deleting model 'MARCRecord' + db.delete_table('marc_marcrecord') + + + models = { + 'core.edition': { + 'Meta': {'object_name': 'Edition'}, + 'cover_image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'publication_date': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'publisher_name': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.PublisherName']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), + 'unglued': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"}) + }, + 'core.publisher': { + 'Meta': {'object_name': 'Publisher'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_publisher'", 'to': "orm['core.PublisherName']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}) + }, + 'core.publishername': { + 'Meta': {'object_name': 'PublisherName'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'publisher': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alternate_names'", 'null': 'True', 'to': "orm['core.Publisher']"}) + }, + 'core.work': { + 'Meta': {'ordering': "['title']", 'object_name': 'Work'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}), + 'earliest_publication': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'featured': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '5', 'db_index': 'True'}), + 'num_wishes': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}), + 'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'selected_edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'selected_works'", 'null': 'True', 'to': "orm['core.Edition']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}) + }, + 'marc.marcrecord': { + 'Meta': {'object_name': 'MARCRecord'}, + 'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'MARCRecords'", 'null': 'True', 'to': "orm['core.Edition']"}), + 'guts': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['marc'] \ No newline at end of file diff --git a/marc/migrations/__init__.py b/marc/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/marc/models.py b/marc/models.py new file mode 100644 index 00000000..20c7eaa8 --- /dev/null +++ b/marc/models.py @@ -0,0 +1,68 @@ +import pymarc +import logging +from datetime import datetime +from StringIO import StringIO + +from django.conf import settings +from django.db import models + +# weak coupling +EDITION_MODEL = "core.Edition" + +class Edition: + # define the methods an edition should have + + # the edition should be able to report ebook downloads, with should have format and url attributes + def downloads(self): + return [] + + # the edition should be able to report "ebook via" url + def download_via_url(self): + return [] + +class MARCRecord(models.Model): + # the record goes here + guts = models.TextField() + + # note capitalization of related_name + edition = models.ForeignKey(EDITION_MODEL, related_name="MARCRecords", null=True) + + @property + def accession(self): + zeroes = 9 - len(str(self.id)) + return 'ung' + zeroes*'0' + str(self.id) + + # the record without 856 + def _record(self): + the_record = pymarc.parse_xml_to_array(StringIO(self.guts))[0] + fields856 = the_record.get_fields('856') + if fields856: + the_record.remove_field(fields856) + return the_record + + def direct_record(self): + the_record = self._record() + for book in self.edition.downloads(): + field856 = pymarc.Field( + tag='856', + indicators = ['4', '0'], + subfields = [ + '3', book.format + ' version', + 'q', settings.CONTENT_TYPES[book.format], + 'u', book.url, + ] + ) + the_record.add_ordered_field(field856) + return the_record + + def via_record(self): + the_record = self._record() + field856_via = pymarc.Field( + tag='856', + indicators = ['4', '0'], + subfields = [ + 'u', self.edition.download_via_url(), + ] + ) + the_record.add_ordered_field(field856_via) + return the_record diff --git a/marc/tests.py b/marc/tests.py new file mode 100644 index 00000000..73e2ee85 --- /dev/null +++ b/marc/tests.py @@ -0,0 +1,116 @@ +""" +django imports +""" +from django.test import TestCase +from django.test.client import Client +from django.db.models import get_model + +""" +regluit imports +""" +from . import models + +a_marc_record = ''' + 01021cam a2200301 a 4500 + 3057297 + 19970108080513.5 + 960131r19761970ke b b 000 0 eng + + (DLC) 96109467 + + + 7 + cbc + orignew + u + ncip + 19 + y-gencatlg + + + 082 done aa11 + + + 96109467 + + + 0195724135 + + + DLC + DLC + DLC + + + f------ + + + PL8010 + .F5 1976 + + + 398.2/096 + 20 + + + Finnegan, Ruth H. + + + Oral literature in Africa / + Ruth Finnegan. + + + Nairobi : + Oxford University Press, + 1976 (1994 printing). + + + xviii, 558 p. : + map ; + 21 cm. + + + Oxford library of African literature + + + Originally published: Oxford : Clarendon Press, 1970. + + + Includes index and bibliographical references (p. [522]-536). + + + Folk literature, African + History and criticism. + + + Oral tradition + Africa. + + + ap + + + c-GenColl + PL8010 + .F5 1976 + Copy 1 + BOOKS + +''' + +class MarcTests(TestCase): + work_id=None + + def test_records(self): + w = get_model('core','Work').objects.create(title="Work 1") + e = get_model('core','Edition').objects.create(title=w.title,work=w) + eb = get_model('core','Ebook').objects.create(url = "http://example.org",edition = e,format = 'epub') + + mr = models.MARCRecord.objects.create(guts=a_marc_record, edition=e ) + + print mr.direct_record() + print mr.via_record() + print mr.direct_record_xml() + print mr.direct_record_mrc() + print mr.via_record_xml() + print mr.vi_record_mrc()