From a33d4ff020fa16e0359991023a2cd031831e9ec4 Mon Sep 17 00:00:00 2001 From: Marcin Koziej Date: Thu, 2 Aug 2012 14:18:36 +0200 Subject: [PATCH] OAI catalogue, started implementation + tests --- apps/api/models.py | 4 +- apps/oai/__init__.py | 1 + apps/oai/handlers.py | 58 ++++++++++++++++++ apps/oai/tests/__init__.py | 1 + apps/oai/tests/files/lubie-kiedy-kobieta.xml | 63 ++++++++++++++++++++ apps/oai/tests/oaipmhapi.py | 20 +++++++ requirements.txt | 9 ++- wolnelektury/settings/__init__.py | 3 +- 8 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 apps/oai/__init__.py create mode 100644 apps/oai/handlers.py create mode 100644 apps/oai/tests/__init__.py create mode 100755 apps/oai/tests/files/lubie-kiedy-kobieta.xml create mode 100644 apps/oai/tests/oaipmhapi.py diff --git a/apps/api/models.py b/apps/api/models.py index 2cdc74a4b..20dd12985 100644 --- a/apps/api/models.py +++ b/apps/api/models.py @@ -5,12 +5,14 @@ from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models.signals import pre_delete +from django.utils.translation import ugettext_lazy as _ from catalogue.models import Book, Tag class Deleted(models.Model): object_id = models.IntegerField() + slug = models.SlugField(_('slug'), max_length=120, blank=True, db_index=True) content_type = models.ForeignKey(ContentType) category = models.CharField(max_length=64, null=True, blank=True, db_index=True) created_at = models.DateTimeField(editable=False, db_index=True) @@ -33,5 +35,5 @@ def _pre_delete_handler(sender, instance, **kwargs): category = None content_type = ContentType.objects.get_for_model(sender) Deleted.objects.create(content_type=content_type, object_id=instance.id, - created_at=instance.created_at, category=category) + created_at=instance.created_at, category=category, slug=instance.slug) pre_delete.connect(_pre_delete_handler) diff --git a/apps/oai/__init__.py b/apps/oai/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/apps/oai/__init__.py @@ -0,0 +1 @@ + diff --git a/apps/oai/handlers.py b/apps/oai/handlers.py new file mode 100644 index 000000000..db4365730 --- /dev/null +++ b/apps/oai/handlers.py @@ -0,0 +1,58 @@ + +from oaipmh import server, common +from catalogue.models import Book, Tag +from api.models import Deleted +from librarian.dcparser import BookInfo +from django.contrib.contenttypes.models import ContentType + + +class Catalogue(common.ResumptionOAIPMH): + def __init__(self): + super(Catalogue, self).__init__() + + def metadata(self, book): + bi = BookInfo.from_file(book.xml_file) + meta = {} + for field in bi.FIELDS: + dc_field = field.uri.split('}')[1] + value = getattr(bi, dc_field.name) + if isinstance(value,list): + value = ';'.join(map(unicode, value)) + else: + value = unicode(value) + meta["dc:"+dc_field] = value + return meta + + def record_for_book(self, book): + header = common.Header(book.slug, book.changed_at, [], False) + meta = common.Metadata(self.metadata(book)) + about = None + return header, meta, about + + def getRecord(self, record, **kw): + """ +Returns (header, metadata, about) for given record. + """ + slug = kw['record'] + try: + book = Book.objects.get(slug=slug) + return self.record_for_book(book) + except Book.DoesNotExist, e: + book_type = ContentType.objects.get_for_model(Book) + deleted_book = Deleted.objects.filter(content_type=book_type, + slug=slug) + header = common.Header(deleted_book.slug, + deleted_book.deleted_at, + [], True) + meta = common.Metadata({}) + return header, meta, None # None for about. + + + + def listRecords(self, **kw): + """ +can get a resumptionToken kw. +returns result, token + """ + return [self.record_for_book(book) for book in Book.objects.all()] + diff --git a/apps/oai/tests/__init__.py b/apps/oai/tests/__init__.py new file mode 100644 index 000000000..08a39d7ba --- /dev/null +++ b/apps/oai/tests/__init__.py @@ -0,0 +1 @@ +from oai.tests.oaipmhapi import * diff --git a/apps/oai/tests/files/lubie-kiedy-kobieta.xml b/apps/oai/tests/files/lubie-kiedy-kobieta.xml new file mode 100755 index 000000000..7ea6f44b0 --- /dev/null +++ b/apps/oai/tests/files/lubie-kiedy-kobieta.xml @@ -0,0 +1,63 @@ + + + +Przerwa-Tetmajer, Kazimierz +Lubię, kiedy kobieta... +Kozioł, Paweł +Niedziałkowska, Marta +Fundacja Nowoczesna Polska +Modernizm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Śląską z egzemplarza pochodzącego ze zbiorów BŚ. +http://wolnelektury.pl/katalog/lektura/lubie-kiedy-kobieta +Kazimierz Przerwa-Tetmajer, Wybór poezji, nakł. Gebethnera i Wolffa, Warszawa-Kraków 1897 +Domena publiczna - Kazimierz Przerwa-Tetmajer zm. 1940 +1940 +xml +text +text +2010-10-12 +L +pol + + + + +Kazimierz Przerwa-Tetmajer + +Lubię, kiedy kobieta... + +Lubię, kiedy kobieta omdlewa w objęciu,/ +Kiedy w lubieżnym zwisa przez ramię przegięciu,/ +PożądanieGdy jej oczy zachodzą mgłą, twarz cała blednie,/ +I wargi się wilgotne rozchylą bezwiednie. + + + +Lubię, kiedy ją rozkosz i żądza oniemi,/ +Gdy wpija się w ramiona palcami drżącemi,/ +Gdy krótkim, urywanym oddycha oddechem,/ +I oddaje się cała z mdlejącym uśmiechem. + + + +WstydI lubię ten wstyd, co się kobiecie zabrania/ +Przyznać, że czuje rozkosz, że moc pożądania/ +Zwalcza ją, a sycenie żądzy oszaleniaoszaleniać (neol.) --- czynić szalonym.,/ +Gdy szuka ust, a lęka się słów i spojrzenia. + + + +Poeta, MizoginiaLubię to --- i tę chwilę lubię, gdy koło mnie/ +Wyczerpana, zmęczona leży nieprzytomnie,/ +A myśl moja już od niej wybiega skrzydlata/ +W nieskończone przestrzenie nieziemskiego świata. + + + + + + + + \ No newline at end of file diff --git a/apps/oai/tests/oaipmhapi.py b/apps/oai/tests/oaipmhapi.py new file mode 100644 index 000000000..ae5e543d7 --- /dev/null +++ b/apps/oai/tests/oaipmhapi.py @@ -0,0 +1,20 @@ + +import sys +print sys.path + +from catalogue.test_utils import WLTestCase +from catalogue import models +from nose.tools import raises +from os import path +from oai.handlers import Catalogue + +class BookMetadataTest(WLTestCase): + def setUp(self): + super(BookMetadata, self).setUp() + xml = path.join(path.dirname(__file__), 'files/lubie-kiedy-kobieta.xml') + self.book = models.Book.from_xml_file(xml) + self.catalogue = Catalogue() + + def test_get_record(self): + r = self.catalogue.getRecord(record='lubie-kiedy-kobieta') + print r diff --git a/requirements.txt b/requirements.txt index 037fa76ea..70cf8b993 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,11 +6,11 @@ South>=0.7 # migrations for django django-pipeline>=1.2 django-pagination>=1.0 django-maintenancemode>=0.10 -django-piston +django-piston<=0.2.3 #django-jsonfield -e git+git://github.com/bradjasper/django-jsonfield.git@2f427368ad70bf8d9a0580df58ec0eb0654d62ae#egg=django-jsonfield django-picklefield -django-allauth +django-allauth<=0.4.0 django-honeypot django-uni-form @@ -38,3 +38,8 @@ django-kombu # spell checking pyenchant + +# OAI-PMH +pyoai + + diff --git a/wolnelektury/settings/__init__.py b/wolnelektury/settings/__init__.py index 15126b9a4..de1b44237 100644 --- a/wolnelektury/settings/__init__.py +++ b/wolnelektury/settings/__init__.py @@ -64,6 +64,7 @@ INSTALLED_APPS_OUR = [ 'social', 'waiter', 'search', + 'oai', ] INSTALLED_APPS_CONTRIB = [ @@ -85,7 +86,7 @@ INSTALLED_APPS_CONTRIB = [ 'djcelery', 'djkombu', 'honeypot', - # 'django_nose', + 'django_nose', #allauth stuff 'emailconfirmation', -- 2.20.1