Merge branch 'master' of github.com:Gluejar/regluit into payment

pull/1/head
Raymond Yee 2011-12-19 13:23:40 -05:00
commit f1875201b3
25 changed files with 933 additions and 162 deletions

View File

@ -1,5 +1,6 @@
import json
import logging
import datetime
import requests
from xml.etree import ElementTree
@ -12,6 +13,7 @@ from regluit.core import models
logger = logging.getLogger(__name__)
def add_by_oclc(oclc):
logger.info("adding book by oclc %s", oclc)
for edition in models.Edition.objects.filter(oclc=oclc):
@ -107,10 +109,6 @@ def add_by_googlebooks_id(googlebooks_id, work=None):
a, created = models.Author.objects.get_or_create(name=a)
a.editions.add(e)
for s in d.get('categories', []):
s, created = models.Subject.objects.get_or_create(name=s)
s.editions.add(e)
access_info = item.get('accessInfo')
if access_info:
e.public_domain = item.get('public_domain', None)
@ -192,6 +190,47 @@ def merge_works(w1, w2):
w2.delete()
def add_openlibrary(work):
work.openlibrary_lookup = datetime.datetime.now()
work.save()
# find the first ISBN match in OpenLibrary
logger.info("looking up openlibrary data for work %s", work.id)
found = False
e = None # openlibrary edition json
w = None # openlibrary work json
# get the 1st openlibrary match by isbn that has an associated work
url = "http://openlibrary.org/api/books"
params = {"format": "json", "jscmd": "details"}
for edition in work.editions.all():
isbn_key = "ISBN:%s" % edition.isbn_10
params['bibkeys'] = isbn_key
e = _get_json(url, params)
if e.has_key(isbn_key) and e[isbn_key]['details'].has_key('works'):
work_key = e[isbn_key]['details']['works'].pop(0)['key']
logger.info("got openlibrary work %s for isbn %s", work_key, isbn_key)
w = _get_json("http://openlibrary.org" + work_key)
if w.has_key('subjects'):
found = True
break
if not found:
logger.warn("unable to find work %s at openlibrary", work.id)
return
# add the subjects to the Work
for s in w.get('subjects', []):
logger.info("adding subject %s to work %s", s, work.id)
subject, created = models.Subject.objects.get_or_create(name=s)
work.subjects.add(subject)
work.openlibrary_id = w['key']
work.save()
# TODO: add authors here once they are moved from Edition to Work
# TODO: add LCCN, LibraryThing, GoodReads to appropriate models
def _get_json(url, params={}):
# TODO: should X-Forwarded-For change based on the request from client?
headers = {'User-Agent': settings.USER_AGENT,

View File

@ -285,13 +285,12 @@ def load_goodreads_shelf_into_wishlist(user, shelf_name='all', goodreads_user_id
if match:
edition.goodreads_id = match.group(1)
edition.save()
regluit.core.tasks.populate_edition.delay(edition)
user.wishlist.add_work(edition.work, 'goodreads')
logger.info("Work with isbn %s added to wishlist.", isbn)
else:
logger.error("unable to extract goodreads id from %s", link)
# let's not trigger too much traffic to Google books for now
# regluit.core.tasks.add_related.delay(isbn)
user.wishlist.add_work(edition.work, 'goodreads')
logger.info("Work with isbn %s added to wishlist.", isbn)
except Exception, e:
logger.info ("Exception adding ISBN %s: %s", isbn, e)

View File

@ -217,8 +217,7 @@ def load_librarything_into_wishlist(user, lt_username, max_books=None):
edition.work.librarything_id = book['work_id']
edition.work.save()
# let's not trigger too much traffic to Google books for now
# regluit.core.tasks.add_related.delay(isbn)
regluit.core.tasks.populate_edition.delay(edition)
user.wishlist.add_work(edition.work, 'librarything')
logger.info("Work with isbn %s added to wishlist.", isbn)
except Exception, e:

View File

@ -0,0 +1,10 @@
from django.core.management.base import BaseCommand
from regluit.core import models
from regluit.core import bookloader
class Command(BaseCommand):
def handle(self, *args, **options):
for work in models.Work.objects.filter(openlibrary_lookup__isnull=True):
bookloader.add_openlibrary(work)

View File

@ -1,13 +0,0 @@
from django.core.management.base import BaseCommand
from regluit.core import tasks, models
class Command(BaseCommand):
help = "queues add related books for works that have only one edition"
def handle(self, **options):
for work in models.Work.objects.all():
if work.editions.all().count() == 1:
sole_edition = work.editions.all()[0]
tasks.add_related.delay(sole_edition.isbn_10)

View File

@ -0,0 +1,220 @@
# encoding: 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):
# Removing M2M table for field editions on 'Subject'
db.delete_table('core_subject_editions')
# Adding M2M table for field works on 'Subject'
db.create_table('core_subject_works', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('subject', models.ForeignKey(orm['core.subject'], null=False)),
('work', models.ForeignKey(orm['core.work'], null=False))
))
db.create_unique('core_subject_works', ['subject_id', 'work_id'])
def backwards(self, orm):
# Adding M2M table for field editions on 'Subject'
db.create_table('core_subject_editions', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('subject', models.ForeignKey(orm['core.subject'], null=False)),
('edition', models.ForeignKey(orm['core.edition'], null=False))
))
db.create_unique('core_subject_editions', ['subject_id', 'edition_id'])
# Removing M2M table for field works on 'Subject'
db.delete_table('core_subject_works')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.author': {
'Meta': {'object_name': 'Author'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
'core.campaign': {
'Meta': {'object_name': 'Campaign'},
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
},
'core.campaignaction': {
'Meta': {'object_name': 'CampaignAction'},
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['core.Campaign']"}),
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '15'})
},
'core.celerytask': {
'Meta': {'object_name': 'CeleryTask'},
'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 12, 15, 22, 25, 4, 967842)', 'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}),
'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"})
},
'core.claim': {
'Meta': {'object_name': 'Claim'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}),
'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"})
},
'core.ebook': {
'Meta': {'object_name': 'Ebook'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}),
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
},
'core.edition': {
'Meta': {'object_name': 'Edition'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
'goodreads_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'googlebooks_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'oclc': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True'}),
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
},
'core.premium': {
'Meta': {'object_name': 'Premium'},
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
},
'core.rightsholder': {
'Meta': {'object_name': 'RightsHolder'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}),
'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
},
'core.subject': {
'Meta': {'object_name': 'Subject'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'facebook_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'goodreads_auth_secret': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_auth_token': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_user_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'goodreads_user_link': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'goodreads_user_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'home_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
'pic_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
'twitter_id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
},
'core.wishes': {
'Meta': {'object_name': 'Wishes', 'db_table': "'core_wishlist_works'"},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'source': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'wishlist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Wishlist']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Work']"})
},
'core.wishlist': {
'Meta': {'object_name': 'Wishlist'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'wishlist'", 'unique': 'True', 'to': "orm['auth.User']"}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'wishlists'", 'symmetrical': 'False', 'through': "orm['core.Wishes']", 'to': "orm['core.Work']"})
},
'core.work': {
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -0,0 +1,210 @@
# encoding: 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):
# Changing field 'Subject.name'
db.alter_column('core_subject', 'name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=200))
# Adding unique constraint on 'Subject', fields ['name']
db.create_unique('core_subject', ['name'])
def backwards(self, orm):
# Removing unique constraint on 'Subject', fields ['name']
db.delete_unique('core_subject', ['name'])
# Changing field 'Subject.name'
db.alter_column('core_subject', 'name', self.gf('django.db.models.fields.CharField')(max_length=500))
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.author': {
'Meta': {'object_name': 'Author'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
'core.campaign': {
'Meta': {'object_name': 'Campaign'},
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
},
'core.campaignaction': {
'Meta': {'object_name': 'CampaignAction'},
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['core.Campaign']"}),
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '15'})
},
'core.celerytask': {
'Meta': {'object_name': 'CeleryTask'},
'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 12, 19, 1, 15, 14, 636254)', 'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}),
'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"})
},
'core.claim': {
'Meta': {'object_name': 'Claim'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}),
'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"})
},
'core.ebook': {
'Meta': {'object_name': 'Ebook'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}),
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
},
'core.edition': {
'Meta': {'object_name': 'Edition'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
'goodreads_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'googlebooks_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'oclc': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True'}),
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
},
'core.premium': {
'Meta': {'object_name': 'Premium'},
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
},
'core.rightsholder': {
'Meta': {'object_name': 'RightsHolder'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}),
'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
},
'core.subject': {
'Meta': {'object_name': 'Subject'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'facebook_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'goodreads_auth_secret': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_auth_token': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_user_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'goodreads_user_link': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'goodreads_user_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'home_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
'pic_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
'twitter_id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
},
'core.wishes': {
'Meta': {'object_name': 'Wishes', 'db_table': "'core_wishlist_works'"},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'source': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'wishlist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Wishlist']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Work']"})
},
'core.wishlist': {
'Meta': {'object_name': 'Wishlist'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'wishlist'", 'unique': 'True', 'to': "orm['auth.User']"}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'wishlists'", 'symmetrical': 'False', 'through': "orm['core.Wishes']", 'to': "orm['core.Work']"})
},
'core.work': {
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -0,0 +1,205 @@
# encoding: 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 field 'Work.openlibrary_lookup'
db.add_column('core_work', 'openlibrary_lookup', self.gf('django.db.models.fields.DateTimeField')(null=True), keep_default=False)
def backwards(self, orm):
# Deleting field 'Work.openlibrary_lookup'
db.delete_column('core_work', 'openlibrary_lookup')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.author': {
'Meta': {'object_name': 'Author'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
'core.campaign': {
'Meta': {'object_name': 'Campaign'},
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
},
'core.campaignaction': {
'Meta': {'object_name': 'CampaignAction'},
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['core.Campaign']"}),
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '15'})
},
'core.celerytask': {
'Meta': {'object_name': 'CeleryTask'},
'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 12, 19, 1, 22, 42, 254688)', 'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}),
'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"})
},
'core.claim': {
'Meta': {'object_name': 'Claim'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}),
'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"})
},
'core.ebook': {
'Meta': {'object_name': 'Ebook'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}),
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
},
'core.edition': {
'Meta': {'object_name': 'Edition'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
'goodreads_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'googlebooks_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'oclc': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True'}),
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
},
'core.premium': {
'Meta': {'object_name': 'Premium'},
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
},
'core.rightsholder': {
'Meta': {'object_name': 'RightsHolder'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}),
'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
},
'core.subject': {
'Meta': {'object_name': 'Subject'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'facebook_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'goodreads_auth_secret': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_auth_token': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_user_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'goodreads_user_link': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'goodreads_user_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'home_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
'pic_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
'twitter_id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
},
'core.wishes': {
'Meta': {'object_name': 'Wishes', 'db_table': "'core_wishlist_works'"},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'source': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'wishlist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Wishlist']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Work']"})
},
'core.wishlist': {
'Meta': {'object_name': 'Wishlist'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'wishlist'", 'unique': 'True', 'to': "orm['auth.User']"}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'wishlists'", 'symmetrical': 'False', 'through': "orm['core.Wishes']", 'to': "orm['core.Work']"})
},
'core.work': {
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -211,6 +211,7 @@ class Work(models.Model):
openlibrary_id = models.CharField(max_length=50, null=True)
librarything_id = models.CharField(max_length=50, null=True)
language = models.CharField(max_length=2, default="en", null=False)
openlibrary_lookup = models.DateTimeField(null=True)
class Meta:
ordering = ['title']
@ -241,6 +242,10 @@ class Work(models.Model):
def librarything_url(self):
return "http://www.librarything.com/work/%s" % self.librarything_id
@property
def openlibrary_url(self):
return "http://openlibrary.org" + self.openlibrary_id
def cover_image_small(self):
return self.editions.all()[0].cover_image_small()
@ -366,8 +371,11 @@ class Author(models.Model):
class Subject(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=500)
editions = models.ManyToManyField("Edition", related_name="subjects")
name = models.CharField(max_length=200, unique=True)
works = models.ManyToManyField("Work", related_name="subjects")
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name

View File

@ -1,15 +1,18 @@
from celery.decorators import task
from regluit.core import bookloader
from regluit.core import goodreads, librarything
from time import sleep
@task
def add_related(isbn):
return bookloader.add_related(isbn)
from celery.decorators import task
from regluit.core import bookloader
from regluit.core import goodreads, librarything
@task
def add_by_isbn(isbn):
return bookloader.add_by_isbn(isbn)
def populate_edition(edition):
"""given an edition this task will populate the database with additional
information about related editions and subjects related to this edition
"""
bookloader.add_related(edition.isbn_10)
bookloader.add_openlibrary(edition.work)
return edition
@task
def load_goodreads_shelf_into_wishlist(user, shelf_name='all', goodreads_user_id=None, max_books=None,

View File

@ -21,7 +21,7 @@ from time import sleep
from math import factorial
class TestBookLoader(TestCase):
class BookLoaderTests(TestCase):
def test_add_by_isbn(self):
# edition
@ -33,11 +33,6 @@ class TestBookLoader(TestCase):
self.assertEqual(edition.isbn_13, '9780441012039')
self.assertEqual(edition.googlebooks_id, "2NyiPwAACAAJ")
# subjects
subject_names = [subject.name for subject in edition.subjects.all()]
self.assertEqual(len(subject_names), 11)
self.assertTrue('Japan' in subject_names)
# authors
self.assertEqual(edition.authors.all().count(), 1)
self.assertEqual(edition.authors.all()[0].name, 'William Gibson')
@ -51,7 +46,6 @@ class TestBookLoader(TestCase):
self.assertEqual(models.Edition.objects.all().count(), 1)
self.assertEqual(models.Author.objects.all().count(), 1)
self.assertEqual(models.Work.objects.all().count(), 1)
self.assertEqual(models.Subject.objects.all().count(), 11)
def test_missing_isbn(self):
e = bookloader.add_by_isbn('0139391401')
@ -79,6 +73,11 @@ class TestBookLoader(TestCase):
self.assertEqual(models.Edition.objects.count(),
edition.work.editions.count())
def test_populate_edition(self):
edition = bookloader.add_by_googlebooks_id('c_dBPgAACAAJ')
edition = tasks.populate_edition.run(edition)
self.assertTrue(edition.work.editions.all().count() > 20)
self.assertTrue(edition.work.subjects.all().count() > 10)
def test_merge_works(self):
# add two editions and see that there are two stub works
@ -86,6 +85,8 @@ class TestBookLoader(TestCase):
e2 = bookloader.add_by_isbn('1458776204')
self.assertTrue(e1)
self.assertTrue(e2)
self.assertTrue(e1.work)
self.assertTrue(e2.work)
self.assertEqual(models.Work.objects.count(), 2)
# add the stub works to a wishlist
@ -117,10 +118,6 @@ class TestBookLoader(TestCase):
self.assertEqual(c1.work, c2.work)
self.assertEqual(user.wishlist.works.all().count(), 1)
def test_oclc(self):
edition = bookloader.add_by_oclc('1246014')
self.assertEqual(edition.title, 'The Latin language')
def test_ebook(self):
edition = bookloader.add_by_oclc('1246014')
self.assertEqual(edition.ebooks.count(), 2)
@ -154,6 +151,16 @@ class TestBookLoader(TestCase):
for edition in work.editions.all():
self.assertEqual(edition.title.lower(), "cat's cradle")
def test_add_openlibrary(self):
work = bookloader.add_by_isbn('0441012035').work
bookloader.add_related('0441012035')
bookloader.add_openlibrary(work)
subjects = [s.name for s in work.subjects.all()]
self.assertTrue(len(subjects) > 10)
self.assertTrue('Science fiction' in subjects)
self.assertEqual(work.openlibrary_id, '/works/OL27258W')
class SearchTests(TestCase):
def test_basic_search(self):
@ -235,7 +242,6 @@ class CampaignTests(TestCase):
self.assertTrue(c4.update_success())
self.assertEqual(c4.status, 'SUCCESSFUL')
# WITHDRAWN
c5 = Campaign(target=D('1000.00'),deadline=datetime(2012,1,1),work=w)
c5.save()
@ -243,17 +249,6 @@ class CampaignTests(TestCase):
self.assertEqual(c5.status, 'WITHDRAWN')
class SettingsTest(TestCase):
def test_dev_me_alignment(self):
from regluit.settings import me, dev
self.assertEqual(set(me.__dict__.keys()) ^ set(dev.__dict__.keys()), set([]))
def test_prod_me_alignment(self):
from regluit.settings import me, prod
self.assertEqual(set(me.__dict__.keys()) ^ set(prod.__dict__.keys()), set([]))
class WishlistTest(TestCase):
def test_add_remove(self):
@ -266,20 +261,6 @@ class WishlistTest(TestCase):
user.wishlist.remove_work(work)
self.assertEqual(user.wishlist.works.count(), 0)
class SettingsTest(TestCase):
def test_dev_me_alignment(self):
try:
from regluit.settings import me, dev
except:
return
self.assertEqual(set(me.__dict__.keys()) ^ set(dev.__dict__.keys()), set([]))
def test_prod_me_alignment(self):
from regluit.settings import me, prod
self.assertEqual(set(me.__dict__.keys()) ^ set(prod.__dict__.keys()), set([]))
class CeleryTaskTest(TestCase):
def test_single_fac(self):
@ -384,10 +365,3 @@ class ISBNTest(TestCase):
self.assertEqual(len(set([str(isbn.ISBN(milosz_10)), str(isbn.ISBN(milosz_13))])),2)
self.assertEqual(len(set([isbn.ISBN(milosz_10).to_string(), isbn.ISBN(milosz_13).to_string()])),1)
def suite():
testcases = [TestBookLoader, SearchTests, CampaignTests, WishlistTest, CeleryTaskTest, GoodreadsTest, LibraryThingTest, ISBNTest]
suites = unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(testcase) for testcase in testcases])
suites.addTest(SettingsTest('test_dev_me_alignment')) # give option to test this alignment
return suites

View File

@ -2,12 +2,16 @@
import re
import json
import time
import urllib
import fileinput
import requests
from oaipmh.client import Client
from oaipmh.metadata import MetadataRegistry, oai_dc_reader
def match():
for line in fileinput.input():
j = json.loads(line)
authors = j['authors']
title = j['title']
print googlebooks_id(title, authors)
def google_search(title, authors, no_matches):
headers = {'X-Forwarded-For': '69.243.24.29'}
@ -78,6 +82,4 @@ def norm_author(a):
return a
if __name__ == "__main__":
results = open("results.txt", "w")
no_matches = open("no-matches.log", "w")
lookup(results, no_matches)
googlebooks_ids()

View File

@ -101,7 +101,7 @@ class MyZotero(Zotero2):
if isbn:
edition = bookloader.add_by_isbn(isbn)
# let's not trigger too much traffic to Google books for now
# regluit.core.tasks.add_related.delay(isbn)
regluit.core.tasks.populate_edition.delay(edition)
user.wishlist.add_work(edition.work, 'zotero')
logger.info("Work with isbn %s added to wishlist.", isbn)
except Exception, e:

View File

@ -10,14 +10,14 @@
wishlists. It is here primarily to show what subjects are present
in the database to guide further development. You can order by the
<a href="{% url subjects %}">subject name</a> or by the
<a href="{% url subjects %}?order=count">number</a> of editions
<a href="{% url subjects %}?order=count">number</a> of works
with that subject.
</p>
<p>
<ul>
{% for subject in subjects %}
<li>{{ subject.name }} ({{ subject.editions__count }})</li>
<li>{{ subject.name }} ({{ subject.works__count }})</li>
{% endfor %}
</ul>
</p>

View File

@ -196,6 +196,15 @@ jQuery(document).ready(function(){
{% endif %}
{% endif %}
{% if work.subjects.all.count > 0 %}
<h4>Subjects</h4>
<ul>
{% for subject in work.subjects.all %}
<li>{{ subject.name }}</li>
{% endfor %}
</ul>
{% endif %}
<h4>Editions</h4>
{% for edition in editions %}
<div class="editions"><div><img src="http://bks{% cycle '1' '2' '3' '4' '5' '6' '7' '8' '9' %}.books.google.com/books?id={{ edition.googlebooks_id }}&printsec=frontcover&img=1&zoom=5" /></div><div class="metadata">{{edition.publisher}}<br />{{edition.publication_date}}<br /><a href="http://bks{% cycle '1' '2' '3' '4' '5' '6' '7' '8' '9' %}.books.google.com/books?id={{ edition.googlebooks_id }}">This edition on Google Books</a></div></div>
@ -213,10 +222,10 @@ jQuery(document).ready(function(){
<h3 class="jsmod-title"><span>Share</span></h3>
<div class="jsmod-content">
<ul class="social menu">
<li class="facebook first"><a href="https://www.facebook.com/sharer.php?u=http%3A%2F%2F{{ request.META.HTTP_HOST|urlencode:"" }}{{ request.path|urlencode:"" }}"><span>Facebook</span></a></li>
<li class="twitter"><a href="https://twitter.com/intent/tweet?url=http%3A%2F%2F{{ request.META.HTTP_HOST|urlencode:"" }}{{ request.path|urlencode:"" }}&text=I'm%20ungluing%20{{ work.title|urlencode }}%20at%20%40unglueit"><span>Twitter</span></a></li>
<li class="lasts email"><a href="#"<span>Email</span></a></li>
<li><a href="#" id="embed"><span>Embed</span></a></li>
<a href="https://www.facebook.com/sharer.php?u=http%3A%2F%2F{{ request.META.HTTP_HOST|urlencode:"" }}{{ request.path|urlencode:"" }}"><li class="facebook first"><span>Facebook</span></li></a>
<a href="https://twitter.com/intent/tweet?url=http%3A%2F%2F{{ request.META.HTTP_HOST|urlencode:"" }}{{ request.path|urlencode:"" }}&text=I'm%20ungluing%20{{ work.title|urlencode }}%20at%20%40unglueit"><li class="twitter"><span>Twitter</span></li></a>
<a href="#"><li class="email"><span>Email</span></li></a>
<a href="#" id="embed"><li class="embed"><span>Embed</span></li></a>
<div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="{{base_url}}/api/widget/{{work.editions.all.0.isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>
</ul>
</div>

View File

@ -4,9 +4,12 @@ import json
import urllib
import logging
import datetime
from decimal import Decimal as D
from re import sub
from itertools import islice
from decimal import Decimal as D
import requests
import oauth2 as oauth
from django import forms
from django.db.models import Q, Count, Sum
from django.conf import settings
@ -26,10 +29,6 @@ from django.contrib.auth.decorators import login_required
from django.shortcuts import render, render_to_response, get_object_or_404
from django.utils.translation import ugettext_lazy as _
import requests
import oauth2 as oauth
from itertools import islice
from regluit.core import tasks
from regluit.core import models, bookloader, librarything
from regluit.core import userlists
@ -40,13 +39,13 @@ from regluit.frontend.forms import RightsHolderForm, UserClaimForm, LibraryThin
from regluit.frontend.forms import ManageCampaignForm, DonateForm
from regluit.payment.manager import PaymentManager
from regluit.payment.parameters import TARGET_TYPE_CAMPAIGN, TARGET_TYPE_DONATION
from regluit.core import goodreads
from tastypie.models import ApiKey
from regluit.payment.models import Transaction
logger = logging.getLogger(__name__)
from regluit.payment.models import Transaction
def home(request):
if request.user.is_authenticated():
@ -136,19 +135,21 @@ def googlebooks(request, googlebooks_id):
edition = models.Edition.objects.get(googlebooks_id=googlebooks_id)
except models.Edition.DoesNotExist:
edition = bookloader.add_by_googlebooks_id(googlebooks_id)
# we could populate_edition(edition) to pull in related editions here
# but it is left out for now to lower the amount of traffic on
# googlebooks, librarything and openlibrary
if not edition:
return HttpResponseNotFound("invalid googlebooks id")
tasks.add_related.delay(edition.isbn_10)
work_url = reverse('work', kwargs={'work_id': edition.work.id})
return HttpResponseRedirect(work_url)
def subjects(request):
order = request.GET.get('order')
subjects = models.Subject.objects.all()
subjects = subjects.annotate(Count('editions'))
subjects = subjects.annotate(Count('works'))
if request.GET.get('order') == 'count':
subjects = subjects.order_by('-editions__count')
subjects = subjects.order_by('-works__count')
else:
subjects = subjects.order_by('name')
@ -558,7 +559,7 @@ def wishlist(request):
if googlebooks_id:
edition = bookloader.add_by_googlebooks_id(googlebooks_id)
# add related editions asynchronously
tasks.add_related.delay(edition.isbn_10)
tasks.populate_edition.delay(edition)
request.user.wishlist.add_work(edition.work,'user')
# TODO: redirect to work page, when it exists
return HttpResponseRedirect('/')

View File

@ -192,9 +192,6 @@ ul.tabs li a:hover, ul.tabs li.active a {
#js-rightcol .jsmodule {
margin-bottom: 10px;
}
#js-rightcol .jsmod-content {
padding-left: 10px;
}
.js-rightcol-pad {
border: 1px solid #d6dde0;
-moz-border-radius: 10px 10px 10px 10px;
@ -228,14 +225,56 @@ ul.social li {
height: 28px;
line-height: 28px;
}
ul.social li a {
padding-left: 10px;
}
ul.social li.facebook {
background: url("/static/images/icons/facebook.png") left center no-repeat;
background: url("/static/images/icons/facebook.png") 10px center no-repeat;
}
ul.social li.facebook span {
padding-left: 10px;
}
ul.social li.facebook:hover {
background: #8dc63f url("/static/images/icons/facebook-hover.png") 10px center no-repeat;
}
ul.social li.facebook:hover span {
color: #fff;
}
ul.social li.twitter {
background: url("/static/images/icons/twitter.png") left center no-repeat;
background: url("/static/images/icons/twitter.png") 10px center no-repeat;
}
ul.social li.twitter span {
padding-left: 10px;
}
ul.social li.twitter:hover {
background: #8dc63f url("/static/images/icons/twitter-hover.png") 10px center no-repeat;
}
ul.social li.twitter:hover span {
color: #fff;
}
ul.social li.email {
background: url("/static/images/icons/email.png") left center no-repeat;
background: url("/static/images/icons/email.png") 10px center no-repeat;
}
ul.social li.email span {
padding-left: 10px;
}
ul.social li.email:hover {
background: #8dc63f url("/static/images/icons/email-hover.png") 10px center no-repeat;
}
ul.social li.email:hover span {
color: #fff;
}
ul.social li.embed {
background: url("/static/images/icons/embed.png") 10px center no-repeat;
}
ul.social li.embed span {
padding-left: 10px;
}
ul.social li.embed:hover {
background: #8dc63f url("/static/images/icons/embed-hover.png") 10px center no-repeat;
}
ul.social li.embed:hover span {
color: #fff;
}
#widgetcode {
display: none;

View File

@ -175,16 +175,28 @@ a.my-setting.active {
width: 100%;
}
#tabs.wantto {
border-bottom: 4px solid #bacfd6;
border-bottom: 4px solid #d6dde0;
}
#tabs.wantto ul.tabs li.tabs3.active a {
background: #d6dde0;
color: #3d4e53;
}
#tabs.ungluing {
border-bottom: 4px solid #eabc7c;
}
#tabs.ungluing ul.tabs li.tabs2.active a {
background: #eabc7c;
color: #fff;
}
#tabs.unglued {
border-bottom: 4px solid #a7d26a;
border-bottom: 4px solid #8dc63f;
}
#tabs.unglued ul.tabs li.tabs1.active a {
background: #8dc63f;
color: #fff;
}
#tabs ul.book-list-view {
margin-bottom: 4px !important;
margin-bottom: 0 !important;
}
#tabs-1, #tabs-2, #tabs-3 {
margin-left: 10px;
@ -214,13 +226,21 @@ ul.tabs li a {
-moz-border-radius: 7px 7px 0 0;
-webkit-border-radius: 7px 7px 0 0;
border-radius: 7px 7px 0 0;
background: #d6dde0;
color: #3d4e53;
}
ul.tabs li a:hover, ul.tabs li.active a {
background: #6994a3;
color: #fff;
}
ul.tabs li.tabs1 a:hover, ul.tabs li.active a {
background: #8dc63f;
color: #ffffff;
}
ul.tabs li.tabs2 a:hover, ul.tabs li.active a {
background: #eabc7c;
color: #fff;
}
ul.tabs li.tabs3 a:hover, ul.tabs li.active a {
background: #d6dde0;
color: #3d4e53;
}
.book-list span.rounded > span {
line-height: normal;
width: 75px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

View File

@ -5,6 +5,22 @@
border: solid 5px #EDF3F4;
}
.shareclass(@sharewhere) {
background:url("@{image-base}icons/@{sharewhere}.png") 10px center no-repeat;
span {
padding-left:10px;
}
&:hover {
background:@green url("@{image-base}icons/@{sharewhere}-hover.png") 10px center no-repeat;
span {
color: #fff;
}
}
}
#js-page-wrap {
overflow:hidden;
}
@ -206,10 +222,6 @@ ul.tabs {
.jsmodule {
margin-bottom:10px;
}
.jsmod-content {
padding-left:10px;
}
}
.js-rightcol-pad {
@ -246,17 +258,26 @@ ul.social li {
padding:5px 0 5px 30px;
.height(28px);
a {
padding-left: 10px;
}
&.facebook {
background:url("@{image-base}icons/facebook.png") left center no-repeat;
.shareclass("facebook");
}
&.twitter {
background:url("@{image-base}icons/twitter.png") left center no-repeat;
.shareclass("twitter");
}
&.email {
background:url("@{image-base}icons/email.png") left center no-repeat;
.shareclass("email");
}
&.embed {
.shareclass("embed");
}
}
#widgetcode {

View File

@ -200,20 +200,35 @@ a.my-setting.active {
width: 100%;
&.wantto {
border-bottom: 4px solid #bacfd6;
border-bottom: 4px solid @blue-grey;
ul.tabs li.tabs3.active a {
background: @blue-grey;
color: @text-blue;
}
}
&.ungluing {
border-bottom: 4px solid #eabc7c;
ul.tabs li.tabs2.active a {
background: #eabc7c;
color: #fff;
}
}
&.unglued {
border-bottom: 4px solid #a7d26a;
border-bottom: 4px solid @green;
ul.tabs li.tabs1.active a {
background: @green;
color: #fff;
}
}
}
#tabs ul.book-list-view {
margin-bottom:4px !important;
margin-bottom:0 !important;
}
#tabs-1,
@ -244,14 +259,24 @@ ul.tabs {
padding:0 10px;
min-width:80px;
.border-radius(7px, 7px, 0, 0);
background:@blue-grey;
color:@text-blue;
}
a:hover, &.active a {
background:@medium-blue;
color:#fff;
}
&.tabs1 a:hover, &.active a {
background:@green;
color:#fff
}
&.tabs2 a:hover, &.active a {
background:#eabc7c;
color:#fff;
}
&.tabs3 a:hover, &.active a {
background:@blue-grey;
color:@text-blue;
}
}
}