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

pull/1/head
Raymond Yee 2012-01-18 09:05:54 -08:00
commit a1561d7f8d
32 changed files with 1220 additions and 254 deletions

View File

@ -74,11 +74,8 @@ Below are the steps for getting regluit running on EC2 with Apache and mod_wsgi,
1. `sudo cp deploy/celeryd.conf /etc/default/celeryd`
1. `sudo mkdir /var/log/celery`
1. `sudo chown celery:celery /var/log/celery`
1. `sudo mkdir /var/run/celery`
1. `sudo chown celery:celery /var/run/celery`
1. `sudo /etc/init.d/celeryd start`
OS X Develper Notes
-------------------

View File

@ -23,21 +23,52 @@ class UserResource(ModelResource):
fields = ['username', 'first_name', 'last_name']
class EditionResource(ModelResource):
work = fields.ForeignKey('regluit.api.resources.WorkResource', 'work')
identifiers = fields.ToManyField('regluit.api.resources.IdentifierResource', 'identifiers')
class Meta:
authentication = ApiKeyAuthentication()
queryset = models.Edition.objects.all()
resource_name = 'edition'
filtering = {
"isbn_13": ALL,
"isbn_13": ALL, "identifiers": ALL_WITH_RELATIONS,
}
def build_filters(self, filters = None):
if filters is None:
filters = {}
for filter_expr, value in filters.items():
if filter_expr.startswith('isbn_13'):
filters['identifiers__type'] = 'isbn'
if len(filter_expr)>7:
filters['identifiers__value'+filter_expr[7:]] = value
else:
filters['identifiers__value'] = value
del filters[ filter_expr ]
return super(EditionResource, self).build_filters(filters)
class IdentifierResource(ModelResource):
work = fields.ForeignKey('regluit.api.resources.WorkResource', 'work')
edition = fields.ForeignKey('regluit.api.resources.EditionResource', 'edition')
class Meta:
authentication = ApiKeyAuthentication()
queryset = models.Identifier.objects.all()
resource_name = 'identifier'
filtering = {
"value": ALL, "type" : ALL,
}
class WorkResource(ModelResource):
editions = fields.ToManyField(EditionResource, 'editions')
identifiers = fields.ToManyField(IdentifierResource, 'identifiers')
class Meta:
authentication = ApiKeyAuthentication()
queryset = models.Work.objects.all()
resource_name = 'work'
filtering = {'editions': ALL_WITH_RELATIONS, 'id': ALL}
filtering = {'editions': ALL_WITH_RELATIONS, 'id': ALL, 'identifiers': ALL_WITH_RELATIONS}
class CampaignResource(ModelResource):
work = fields.ToOneField(WorkResource, 'work')

View File

@ -20,7 +20,11 @@
{% if user.is_authenticated %}
<h3>Campaign info</h3>
<p>JSON to get data on all campaigns</p>
<a href="/api/v1/campaign/?format=json&api_key={{api_key}}&username={{user.username}}">{{base_url}}/api/v1/campaign/?format=json&api_key={api_key}&username={username}</a>
<a href="/api/v1/campaign/?format=json&amp;api_key={{api_key}}&amp;username={{user.username}}">{{base_url}}/api/v1/campaign/?format=json&amp;api_key={api_key}&amp;username={username}</a>
<h3>Identifier Resolution</h3>
<p>JSON to get work/edition data for an isbn</p>
<a href="/api/v1/identifier/?format=json&amp;api_key={{api_key}}&amp;type=isbn&amp;value=9780441012039">{{base_url}}/api/v1/identifier/?format=json&amp;api_key={api_key}&amp;ype=isbn&amp;value=9780441012039</a>
<p> In addition to isbn, you can use 'goog' if you have a google books id, and 'oclc' for oclc numbers.</p>
{% endif %}
<h3>Campaign Widgets</h3>

View File

@ -33,7 +33,7 @@
<!--- editions --->
{% if work %}
{% with work.editions.all.0.googlebooks_id as googlebooks_id %}
{% with work.googlebooks_id as googlebooks_id %}
{% include "book_panel.html" %}
{% endwith %}
{% else %}

View File

@ -12,7 +12,7 @@ import regluit.core.isbn
class ApiTests(TestCase):
def setUp(self):
edition = bookloader.add_by_isbn(isbn='0441012035')
edition = bookloader.add_by_isbn_from_google(isbn='0441012035')
campaign = models.Campaign.objects.create(
name=edition.work.title,
work=edition.work,
@ -57,7 +57,8 @@ class ApiTests(TestCase):
def test_campaign_lookup_by_isbn(self):
r = self.client.get('/api/v1/campaign/', data={
'format': 'json',
'work__editions__isbn_13': regluit.core.isbn.convert_10_to_13('0441012035'),
'work__identifiers__value': regluit.core.isbn.convert_10_to_13('0441012035'),
'work__identifiers__type': 'isbn',
'username': self.user.username,
'api_key': self.user.api_key.key
})
@ -75,7 +76,8 @@ class ApiTests(TestCase):
r = self.client.get('/api/v1/campaign/', data={
'format': 'json',
'work__editions__isbn_13': regluit.core.isbn.convert_10_to_13('0441012035'),
'work__identifiers__value': regluit.core.isbn.convert_10_to_13('0441012035'),
'work__identifiers__type': 'isbn',
'username': self.user.username,
'api_key': self.user.api_key.key
})
@ -83,11 +85,12 @@ class ApiTests(TestCase):
self.assertEqual(j['meta']['logged_in_username'], 'test')
self.assertEqual(j['objects'][0]['in_wishlist'], False)
w = models.Work.objects.get(editions__isbn_13=regluit.core.isbn.convert_10_to_13('0441012035'))
w = models.Work.objects.get(identifiers__value=regluit.core.isbn.convert_10_to_13('0441012035'), identifiers__type='isbn')
self.user.wishlist.add_work(w,'test')
r = self.client.get('/api/v1/campaign/', data={
'format': 'json',
'work__editions__isbn_13': regluit.core.isbn.convert_10_to_13('0441012035'),
'work__identifiers__value': regluit.core.isbn.convert_10_to_13('0441012035'),
'work__identifiers__type': 'isbn',
'username': self.user.username,
'api_key': self.user.api_key.key
})

View File

@ -8,6 +8,7 @@ from regluit.api import resources
v1_api = Api(api_name='v1')
v1_api.register(resources.UserResource())
v1_api.register(resources.WorkResource())
v1_api.register(resources.IdentifierResource())
v1_api.register(resources.EditionResource())
v1_api.register(resources.CampaignResource())
v1_api.register(resources.AuthorResource())

View File

@ -13,9 +13,11 @@ from tastypie.models import ApiKey
def isbn(request,isbn):
if len(isbn)==10:
isbn=regluit.core.isbn.convert_10_to_13(isbn)
editions = models.Edition.objects.filter( Q(isbn_13 = isbn))
# models.Campaign.objects.filter(work__editions__isbn_13='9780811216999')
try:
edition = models.Identifier.objects.get( Q(type = 'isbn', value = isbn)).edition
editions = [edition]
except models.Identifier.DoesNotExist:
editions = []
return render_to_response('isbn.html',
{'isbn':isbn, 'editions':editions},
context_instance=RequestContext(request)
@ -44,23 +46,14 @@ def widget(request,isbn):
Current implementation is to supply info for current book panel design
"""
# presumably 0 or 1 Edition will match
if len(isbn)==10:
isbn=regluit.core.isbn.convert_10_to_13(isbn)
editions = models.Edition.objects.filter( Q(isbn_13 = isbn))
# if 1 edition: should be 0 or 1 corresponding Work
# for 1 Work, there will be a Campaign or not
assert len(editions) < 2
if len(editions):
edition = editions[0]
try:
work = edition.work
campaigns = work.campaigns.all()
except Exception, e:
work = None
campaigns = []
else:
isbn = regluit.core.isbn.convert_10_to_13(isbn)
try:
identifier = models.Identifier.objects.get( Q( type = 'isbn', value = isbn ))
work = identifier.work
edition = identifier.edition
campaigns = work.campaigns.all()
except models.Identifer.DoesNotExist:
edition = None
work = None
campaigns = []
@ -104,10 +97,7 @@ class ApiHelpView(TemplateView):
campaigns = models.Campaign.objects.all()
if len(campaigns):
c = campaigns[0]
try:
isbn = c.work.editions.all()[0].isbn_13
except IndexError:
isbn = ''
isbn = c.work.first_isbn_13
context["campaign"] = campaigns[0]
context["campaign_isbn"] = isbn

View File

@ -15,44 +15,85 @@ import regluit.core.isbn
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):
return edition
def add_by_oclc(isbn, work=None):
# this is indirection in case we have a data source other than google
return add_by_oclc_from_google(isbn)
url = "https://www.googleapis.com/books/v1/volumes"
results = _get_json(url, {"q": '"OCLC%s"' % oclc})
if not results.has_key('items') or len(results['items']) == 0:
logger.warn("no google hits for %s" % oclc)
def add_by_oclc_from_google(oclc):
if oclc:
logger.info("adding book by oclc %s" , oclc)
else:
return None
try:
return models.Identifier.objects.get(type='oclc', value=oclc).edition
except:
url = "https://www.googleapis.com/books/v1/volumes"
results = _get_json(url, {"q": '"OCLC%s"' % oclc})
if not results.has_key('items') or len(results['items']) == 0:
logger.warn("no google hits for %s" , oclc)
return None
try:
e = add_by_googlebooks_id(results['items'][0]['id'], results=results['items'][0])
models.Identifier(type='oclc', value=oclc, edition=e, work=e.work).save()
return e
except LookupFailure, e:
logger.exception("failed to add edition for %s", oclc)
except IntegrityError, e:
logger.exception("google books data for %s didn't fit our db", oclc)
return None
try:
e = add_by_googlebooks_id(results['items'][0]['id'])
e.oclc = oclc
e.save()
return e
except LookupFailure, e:
logger.exception("failed to add edition for %s", oclc)
except IntegrityError, e:
logger.exception("google books data for %s didn't fit our db", oclc)
return None
def add_by_isbn(isbn, work=None):
"""add a book to the UnglueIt database based on ISBN. The work parameter
if not isbn:
return None
e = add_by_isbn_from_google(isbn, work=work)
if e:
return e
logger.info("null came back from add_by_isbn_from_google: %s", isbn)
if not work or not work.title:
return None
# if there's a work with a title, we want to create stub editions and
# works, even if google doesn't know about it # but if it's not valid,
# forget it!
try:
isbn = regluit.core.isbn.ISBN(isbn)
except:
logger.exception("invalid isbn: %s", isbn)
return None
if not isbn.valid:
return None
isbn = isbn.to_string()
# we don't know the language ->'xx'
w = models.Work(title=work.title, language='xx')
w.save()
e = models.Edition(title=work.title,work=w)
e.save()
e.new = True
models.Identifier(type='isbn', value=isbn, work=w, edition=e).save()
return e
def add_by_isbn_from_google(isbn, work=None):
"""add a book to the UnglueIt database from google based on ISBN. The work parameter
is optional, and if not supplied the edition will be associated with
a stub work.
"""
if not isbn:
return None
if len(isbn)==10:
isbn=regluit.core.isbn.convert_10_to_13(isbn)
isbn = regluit.core.isbn.convert_10_to_13(isbn)
logger.info("adding book by isbn %s", isbn)
# save a lookup to google if we already have this isbn
has_isbn = Q(isbn_13=isbn)
for edition in models.Edition.objects.filter(has_isbn):
# check if we already have this isbn
edition = get_edition_by_id(type='isbn',value=isbn)
if edition:
edition.new = False
return edition
@ -60,58 +101,89 @@ def add_by_isbn(isbn, work=None):
results = _get_json(url, {"q": "isbn:%s" % isbn})
if not results.has_key('items') or len(results['items']) == 0:
logger.warn("no google hits for %s" % isbn)
logger.warn("no google hits for %s" , isbn)
return None
try:
return add_by_googlebooks_id(results['items'][0]['id'], work)
return add_by_googlebooks_id(results['items'][0]['id'], work=work, results=results['items'][0])
except LookupFailure, e:
logger.exception("failed to add edition for %s", isbn)
except IntegrityError, e:
logger.exception("google books data for %s didn't fit our db", isbn)
return None
def get_work_by_id(type,value):
if value:
try:
return models.Identifier.objects.get(type=type,value=value).work
except models.Identifier.DoesNotExist:
return None
def add_by_googlebooks_id(googlebooks_id, work=None):
def get_edition_by_id(type,value):
if value:
try:
return models.Identifier.objects.get(type=type,value=value).edition
except models.Identifier.DoesNotExist:
return None
def add_by_googlebooks_id(googlebooks_id, work=None, results=None):
"""add a book to the UnglueIt database based on the GoogleBooks ID. The
work parameter is optional, and if not supplied the edition will be
associated with a stub work.
associated with a stub work.
"""
# don't ping google again if we already know about the edition
try:
e = models.Edition.objects.get(googlebooks_id=googlebooks_id)
return e
except models.Edition.DoesNotExist:
return models.Identifier.objects.get(type='goog', value=googlebooks_id).edition
except models.Identifier.DoesNotExist:
pass
logger.info("loading metadata from google for %s", googlebooks_id)
url = "https://www.googleapis.com/books/v1/volumes/%s" % googlebooks_id
item = _get_json(url)
# if google has been queried by caller, don't call again
if results:
item =results
else:
logger.info("loading metadata from google for %s", googlebooks_id)
url = "https://www.googleapis.com/books/v1/volumes/%s" % googlebooks_id
item = _get_json(url)
d = item['volumeInfo']
# don't add the edition to a work with a different language
# https://www.pivotaltracker.com/story/show/17234433
language = d.get('language')
language = d['language']
if work and work.language != language:
logger.warn("ignoring %s since it is %s instead of %s" %
logger.info("not connecting %s since it is %s instead of %s" %
(googlebooks_id, language, work.language))
return
e = models.Edition(googlebooks_id=googlebooks_id)
work = None
isbn = None
for i in d.get('industryIdentifiers', []):
if i['type'] == 'ISBN_10' and not isbn:
isbn = regluit.core.isbn.convert_10_to_13(i['identifier'])
elif i['type'] == 'ISBN_13':
isbn = i['identifier']
# now check to see if there's an existing Work
if not work:
work = get_work_by_id(type='isbn',value=isbn)
if not work:
work = models.Work.objects.create(title=d['title'], language=language)
work.new = True
work.save()
# because this is a new google id, we have to create a new edition
e = models.Edition(work=work)
e.title = d.get('title')
e.description = d.get('description')
e.publisher = d.get('publisher')
e.publication_date = d.get('publishedDate', '')
for i in d.get('industryIdentifiers', []):
if i['type'] == 'ISBN_13':
e.isbn_13 = i['identifier']
elif i['type'] == 'ISBN_13':
e.isbn_13 = i['identifier']
e.save()
e.new=True
e.new = True
# create identifier where needed
models.Identifier(type='goog',value=googlebooks_id,edition=e,work=work).save()
if isbn:
models.Identifier.get_or_add(type='isbn',value=isbn,edition=e,work=work)
for a in d.get('authors', []):
a, created = models.Author.objects.get_or_create(name=a)
@ -133,16 +205,7 @@ def add_by_googlebooks_id(googlebooks_id, work=None):
url=pdf.get('downloadLink', None),
provider='google')
ebook.save()
# if we know what work the edition should be attached to, attach it
if work:
work.editions.add(e)
# otherwise we need to create a stub work
else:
w = models.Work.objects.create(title=e.title, language=language)
w.editions.add(e)
return e
@ -156,26 +219,42 @@ def add_related(isbn):
# this is the work everything will hang off
work = edition.work
new_editions = []
other_editions = {}
for other_isbn in thingisbn(isbn):
# 979's come back as 13
if len(other_isbn)==10:
other_isbn=regluit.core.isbn.convert_10_to_13(other_isbn)
related_edition = add_by_isbn(other_isbn, work)
if related_edition and related_edition.work != edition.work:
merge_works(edition.work, related_edition.work)
other_isbn = regluit.core.isbn.convert_10_to_13(other_isbn)
related_edition = add_by_isbn(other_isbn, work=work)
if related_edition:
new_editions.append(related_edition)
related_language = related_edition.work.language
if edition.work.language == related_language:
new_editions.append(related_edition)
if related_edition.work != edition.work:
merge_works(edition.work, related_edition.work)
else:
if other_editions.has_key(related_language):
other_editions[related_language].append(related_edition)
else:
other_editions[related_language]=[related_edition]
# group the other language editions together
for lang_group in other_editions.itervalues():
if len(lang_group)>1:
lang_edition = lang_group[0]
for related_edition in lang_group[1:]:
if lang_edition.work != related_edition.work:
merge_works(lang_edition.work, related_edition.work)
return new_editions
def thingisbn(isbn):
"""given an ISBN return a list of related edition ISBNs, according to
Library Thing. (takes isbn_10 or isbn_13, returns isbn_10, except for 979 isbns, which come back as isbn_13')
"""
logger.info("looking up %s at ThingISBN" % isbn)
logger.info("looking up %s at ThingISBN" , isbn)
url = "http://www.librarything.com/api/thingISBN/%s" % isbn
xml = requests.get(url, headers={"User-Agent": settings.USER_AGENT}).content
doc = ElementTree.fromstring(xml)
@ -185,7 +264,10 @@ def thingisbn(isbn):
def merge_works(w1, w2):
"""will merge the second work (w2) into the first (w1)
"""
logger.info("merging work %s into %s", w1, w2)
logger.info("merging work %s into %s", w2, w1)
for identifier in w2.identifiers.all():
identifier.work = w1
identifier.save()
for edition in w2.editions.all():
edition.work = w1
edition.save()
@ -193,7 +275,7 @@ def merge_works(w1, w2):
campaign.work = w1
campaign.save()
for wishlist in models.Wishlist.objects.filter(works__in=[w2]):
w2source=wishlist.work_source(w2)
w2source = wishlist.work_source(w2)
wishlist.remove_work(w2)
wishlist.add_work(w1, w2source)
# TODO: should we decommission w2 instead of deleting it, so that we can
@ -202,6 +284,10 @@ def merge_works(w1, w2):
def add_openlibrary(work):
if work.openlibrary_lookup is not None:
# don't hit OL if we've visited in the past month or so
if datetime.datetime.now()- work.openlibrary_lookup < datetime.timedelta(days=30):
return
work.openlibrary_lookup = datetime.datetime.now()
work.save()
@ -217,11 +303,11 @@ def add_openlibrary(work):
for edition in work.editions.all():
isbn_key = "ISBN:%s" % edition.isbn_13
params['bibkeys'] = isbn_key
e = _get_json(url, params)
e = _get_json(url, params, type='ol')
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)
w = _get_json("http://openlibrary.org" + work_key,type='ol')
if w.has_key('subjects'):
found = True
break
@ -235,24 +321,32 @@ def add_openlibrary(work):
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()
models.Identifier.get_or_add(type='olwk',value=w['key'],work=work)
if e[isbn_key]['details'].has_key('identifiers'):
ids = e[isbn_key]['details']['identifiers']
if ids.has_key('goodreads'):
models.Identifier.get_or_add(type='gdrd',value=ids['goodreads'][0],work=work,edition=edition)
if ids.has_key('librarything'):
models.Identifier.get_or_add(type='ltwk',value=ids['librarything'][0],work=work)
# 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={}):
def _get_json(url, params={}, type='gb'):
# TODO: should X-Forwarded-For change based on the request from client?
headers = {'User-Agent': settings.USER_AGENT,
'Accept': 'application/json',
'X-Forwarded-For': '69.174.114.214'}
params['key'] = settings.GOOGLE_BOOKS_API_KEY
if type == 'gb':
params['key'] = settings.GOOGLE_BOOKS_API_KEY
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
return json.loads(response.content)
else:
logger.error("unexpected HTTP response: %s" % response)
if response.content:
logger.error("response content: %s" % response.content)
raise LookupFailure("GET failed: url=%s and params=%s" % (url, params))

View File

@ -13,6 +13,7 @@ import django.utils.encoding
import regluit.core
from regluit.core import bookloader
from regluit.core import models
# import parse_qsl from cgi if it doesn't exist in urlparse
try:
@ -286,8 +287,7 @@ def load_goodreads_shelf_into_wishlist(user, shelf_name='all', goodreads_user_id
link = review['book']['link']
match = re.search('/show/(\d+)', link)
if match:
edition.goodreads_id = match.group(1)
edition.save()
identifier= models.Identifier.get_or_add(type = 'gdrd', value = match.group(1), edition = edition, work = edition.work)
user.wishlist.add_work(edition.work, 'goodreads')
logger.info("Work with isbn %s added to wishlist.", isbn)
else:

View File

@ -6,6 +6,7 @@ import HTMLParser
import logging
import re
from datetime import datetime
from regluit.core import models
logger = logging.getLogger(__name__)
@ -214,10 +215,9 @@ def load_librarything_into_wishlist(user, lt_username, max_books=None):
if not edition:
continue
# add the librarything ids to the db since we know them now
edition.librarything_id = book['book_id']
edition.save()
edition.work.librarything_id = book['work_id']
edition.work.save()
identifier= models.Identifier.get_or_add(type = 'thng', value = book['book_id'], edition = edition, work = edition.work)
identifier= models.Identifier.get_or_add(type = 'ltwk', value = book['work_id'], work = edition.work)
user.wishlist.add_work(edition.work, 'librarything')
if edition.new:
regluit.core.tasks.populate_edition.delay(edition)

View File

@ -0,0 +1,21 @@
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
from regluit.core import bookloader
class Command(BaseCommand):
help = "populate a user's wishlist with books from a file of isbns"
args = "<filename> <username>"
def handle(self, filename, username, **options):
user = User.objects.get(username=username)
wishlist = user.wishlist
for isbn in open(filename):
isbn = isbn.strip()
edition = bookloader.add_by_isbn(isbn)
bookloader.add_related(isbn)
if edition:
user.wishlist.add_work(edition.work, source="user")
print "loaded %s as %s for %s" % (isbn, edition, user)
else:
print "failed to load book for %s" % isbn

View File

@ -1,19 +0,0 @@
from django.db.models import Count
from django.core.management.base import BaseCommand
from regluit.core import models
class Command(BaseCommand):
help = "remove duplicates"
def handle(self, *args, **options):
q = models.Edition.objects.values("googlebooks_id")
q = q.annotate(Count("googlebooks_id"))
for r in q:
if r['googlebooks_id__count'] == 1:
continue
gb = r['googlebooks_id']
editions = models.Edition.objects.filter(googlebooks_id=gb)
for e in editions[1:]:
print "removing duplicate edition: %s" % e
e.delete()

View File

@ -0,0 +1,254 @@
# 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 model 'Identifier'
db.create_table('core_identifier', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('type', self.gf('django.db.models.fields.CharField')(max_length=4)),
('value', self.gf('django.db.models.fields.CharField')(max_length=31)),
('work', self.gf('django.db.models.fields.related.ForeignKey')(related_name='identifiers', to=orm['core.Work'])),
('edition', self.gf('django.db.models.fields.related.ForeignKey')(related_name='identifiers', null=True, to=orm['core.Edition'])),
))
db.send_create_signal('core', ['Identifier'])
# Adding unique constraint on 'Identifier', fields ['type', 'value']
db.create_unique('core_identifier', ['type', 'value'])
# migrating data
if not db.dry_run:
for work in orm.Work.objects.all():
if work.librarything_id:
identifier = orm.Identifier.objects.create(type='ltwk',value=work.librarything_id, work=work)
identifier.save()
if work.openlibrary_id:
identifier = orm.Identifier.objects.create(type='olwk',value=work.openlibrary_id, work=work)
identifier.save()
for edition in work.editions.all():
if edition.googlebooks_id:
identifier = orm.Identifier.objects.create(type='goog',value=edition.googlebooks_id, work=work, edition=edition)
identifier.save()
if edition.goodreads_id:
identifier = orm.Identifier.objects.create(type='gdrd',value=edition.goodreads_id, work=work, edition=edition)
identifier.save()
if edition.librarything_id:
identifier = orm.Identifier.objects.create(type='thng',value=edition.librarything_id, work=work, edition=edition)
identifier.save()
if edition.isbn_13:
identifier = orm.Identifier.objects.create(type='isbn',value=edition.isbn_13, work=work, edition=edition)
identifier.save()
if edition.oclc:
identifier = orm.Identifier.objects.create(type='oclc',value=edition.oclc, work=work, edition=edition)
identifier.save()
def backwards(self, orm):
# Removing unique constraint on 'Identifier', fields ['type', 'value']
db.delete_unique('core_identifier', ['type', 'value'])
# Deleting model 'Identifier'
db.delete_table('core_identifier')
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(2012, 1, 7, 17, 53, 55, 504045)', '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', [], {'unique': 'True', 'max_length': '50'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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.identifier': {
'Meta': {'unique_together': "(('type', 'value'),)", 'object_name': 'Identifier'},
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'null': 'True', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", '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': {'ordering': "['name']", '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

@ -0,0 +1,267 @@
# 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):
# Deleting field 'Work.librarything_id'
db.delete_column('core_work', 'librarything_id')
# Deleting field 'Work.openlibrary_id'
db.delete_column('core_work', 'openlibrary_id')
# Deleting field 'Edition.oclc'
db.delete_column('core_edition', 'oclc')
# Deleting field 'Edition.isbn_13'
db.delete_column('core_edition', 'isbn_13')
# Deleting field 'Edition.goodreads_id'
db.delete_column('core_edition', 'goodreads_id')
# Deleting field 'Edition.googlebooks_id'
db.delete_column('core_edition', 'googlebooks_id')
# Deleting field 'Edition.librarything_id'
db.delete_column('core_edition', 'librarything_id')
def backwards(self, orm):
# Adding field 'Work.librarything_id'
db.add_column('core_work', 'librarything_id', self.gf('django.db.models.fields.CharField')(max_length=50, null=True), keep_default=False)
# Adding field 'Work.openlibrary_id'
db.add_column('core_work', 'openlibrary_id', self.gf('django.db.models.fields.CharField')(max_length=50, null=True), keep_default=False)
# Adding field 'Edition.oclc'
db.add_column('core_edition', 'oclc', self.gf('django.db.models.fields.CharField')(max_length=25, null=True), keep_default=False)
# Adding field 'Edition.isbn_13'
db.add_column('core_edition', 'isbn_13', self.gf('django.db.models.fields.CharField')(max_length=13, null=True), keep_default=False)
# Adding field 'Edition.goodreads_id'
db.add_column('core_edition', 'goodreads_id', self.gf('django.db.models.fields.CharField')(max_length=50, null=True), keep_default=False)
# Adding field 'Edition.googlebooks_id'
db.add_column('core_edition', 'googlebooks_id', self.gf('django.db.models.fields.CharField')(default='0', max_length=50, unique=True), keep_default=False)
# Adding field 'Edition.librarything_id'
db.add_column('core_edition', 'librarything_id', self.gf('django.db.models.fields.CharField')(max_length=50, null=True), keep_default=False)
# migrating data
if not db.dry_run:
for identifier in orm.Identifier.objects.all():
if identifier.type=='ltwk':
identifier.work.librarything_id = identifier.value
identifier.work.save()
elif identifier.type=='olwk':
identifier.work.openlibrary_id = identifier.value
identifier.work.save()
elif identifier.type=='goog':
identifier.edition.googlebooks_id = identifier.value
identifier.edition.save()
elif identifier.type=='gdrd':
identifier.edition.goodreads_id = identifier.value
identifier.edition.save()
elif identifier.type=='thng':
identifier.edition.librarything_id = identifier.value
identifier.edition.save()
elif identifier.type=='isbn':
identifier.edition.isbn_13 = identifier.value
identifier.edition.save()
elif identifier.type=='oclc':
identifier.edition.oclc = identifier.value
identifier.edition.save()
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(2012, 1, 7, 21, 27, 56, 524980)', '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'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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.identifier': {
'Meta': {'unique_together': "(('type', 'value'),)", 'object_name': 'Identifier'},
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'null': 'True', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", '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': {'ordering': "['name']", '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'}),
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -0,0 +1,211 @@
# 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 'Edition.publisher'
db.alter_column('core_edition', 'publisher', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
# Changing field 'Edition.publication_date'
db.alter_column('core_edition', 'publication_date', self.gf('django.db.models.fields.CharField')(max_length=50, null=True))
def backwards(self, orm):
# Changing field 'Edition.publisher'
db.alter_column('core_edition', 'publisher', self.gf('django.db.models.fields.CharField')(default='', max_length=255))
# Changing field 'Edition.publication_date'
db.alter_column('core_edition', 'publication_date', self.gf('django.db.models.fields.CharField')(default=datetime.date(1901, 1, 1), max_length=50))
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(2012, 1, 16, 14, 5, 44, 457292)', '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'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'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.identifier': {
'Meta': {'unique_together': "(('type', 'value'),)", 'object_name': 'Identifier'},
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'null': 'True', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", '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': {'ordering': "['name']", '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', [], {'related_name': "'wishes'", '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'}),
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -198,7 +198,7 @@ class Campaign(models.Model):
return self
def supporters(self):
"""nb: returns (distinct) supporter IDs, not supporter objects"""
"""nb: returns (distinct) supporter IDs, not supporter objects"""
translist = self.transactions().values_list('user', flat=True).distinct()
return translist
@ -208,12 +208,29 @@ class Campaign(models.Model):
if premiums.count() == 0:
premiums = Premium.objects.filter(campaign__isnull=True)
return premiums
class Identifier(models.Model):
# olib, ltwk, goog, gdrd, thng, isbn, oclc, olwk, olib
type = models.CharField(max_length=4, null=False)
value = models.CharField(max_length=31, null=False)
work = models.ForeignKey("Work", related_name="identifiers", null=False)
edition = models.ForeignKey("Edition", related_name="identifiers", null=True)
class Meta:
unique_together = ("type", "value")
@classmethod
def get_or_add(klass, type='goog', value=None, edition=None, work=None):
try:
return Identifier.objects.get(type=type, value=value)
except Identifier.DoesNotExist:
i=Identifier(type=type, value=value, edition=edition, work=work)
i.save()
return i
class Work(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=1000)
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)
@ -226,44 +243,62 @@ class Work(models.Model):
@property
def googlebooks_id(self):
# may want to denormalize this at some point to avoid an extra query
try:
return self.editions.all()[0].googlebooks_id
return self.identifiers.filter(type='goog')[0].value
except IndexError:
return ''
return ''
@property
def googlebooks_url(self):
return "http://books.google.com/books?id=%s" % self.googlebooks_id
if self.googlebooks_id:
return "http://books.google.com/books?id=%s" % self.googlebooks_id
else:
return ''
@property
def goodreads_id(self):
for e in self.editions.filter(goodreads_id__isnull=False):
return e.goodreads_id
try:
return self.identifiers.filter(type='gdrd')[0].value
except IndexError:
return ''
@property
def goodreads_url(self):
return "http://www.goodreads.com/book/show/%s" % self.goodreads_id
@property
def librarything_id(self):
try:
return self.identifiers.filter(type='ltwk')[0].value
except IndexError:
return ''
@property
def librarything_url(self):
return "http://www.librarything.com/work/%s" % self.librarything_id
@property
def openlibrary_id(self):
try:
return self.identifiers.filter(type='olwk')[0].value
except IndexError:
return ''
@property
def openlibrary_url(self):
return "http://openlibrary.org" + self.openlibrary_id
def cover_image_small(self):
try:
return self.editions.all()[0].cover_image_small()
return self.editions.all()[0].cover_image_small()
except IndexError:
return "/static/images/generic_cover_larger.png"
return "/static/images/generic_cover_larger.png"
def cover_image_thumbnail(self):
try:
return self.editions.all()[0].cover_image_thumbnail()
return self.editions.all()[0].cover_image_thumbnail()
except IndexError:
return "/static/images/generic_cover_larger.png"
return "/static/images/generic_cover_larger.png"
def author(self):
authors = list(Author.objects.filter(editions__work=self).all())
@ -291,7 +326,7 @@ class Work(models.Model):
if self.first_ebook() or self.first_epub():
status = "Available"
else:
status = "No campaign yet"
status = "No campaign yet"
return status
def percent_unglued(self):
@ -369,8 +404,17 @@ class Work(models.Model):
return description
def first_isbn_13(self):
for e in self.editions.filter(isbn_13__isnull=False):
return e.isbn_13
try:
return self.identifiers.filter(type='isbn')[0].value
except IndexError:
return ''
@property
def publication_date(self):
for edition in Edition.objects.filter(work=self):
if edition.publication_date:
return edition.publication_date
return ''
def __unicode__(self):
return self.title
@ -398,42 +442,78 @@ class Subject(models.Model):
class Edition(models.Model):
googlebooks_id = models.CharField(max_length=50, null=False, unique=True)
goodreads_id = models.CharField(max_length=50, null=True)
librarything_id = models.CharField(max_length=50, null=True)
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=1000)
description = models.TextField(default='', null=True)
publisher = models.CharField(max_length=255)
publication_date = models.CharField(max_length=50)
publisher = models.CharField(max_length=255, null=True)
publication_date = models.CharField(max_length=50, null=True)
public_domain = models.NullBooleanField(null=True)
isbn_13 = models.CharField(max_length=13, null=True)
oclc = models.CharField(max_length=25, null=True)
work = models.ForeignKey("Work", related_name="editions", null=True)
def __unicode__(self):
return "%s (%s)" % (self.title, self.isbn_13)
def cover_image_small(self):
server_id = random.randint(0, 9)
return "http://bks%i.books.google.com/books?id=%s&printsec=frontcover&img=1&zoom=5" % (server_id, self.googlebooks_id)
if self.googlebooks_id:
server_id = random.randint(0, 9)
return "http://bks%i.books.google.com/books?id=%s&printsec=frontcover&img=1&zoom=5" % (server_id, self.googlebooks_id)
else:
return ''
def cover_image_thumbnail(self):
server_id = random.randint(0, 9)
return "http://bks%s.books.google.com/books?id=%s&printsec=frontcover&img=1&zoom=1" % (server_id, self.googlebooks_id)
if self.googlebooks_id:
server_id = random.randint(0, 9)
return "http://bks%s.books.google.com/books?id=%s&printsec=frontcover&img=1&zoom=1" % (server_id, self.googlebooks_id)
else:
return ''
@property
def isbn_10(self):
return regluit.core.isbn.convert_13_to_10(self.isbn_13)
@property
def isbn_13(self):
try:
return self.identifiers.filter(type='isbn')[0].value
except IndexError:
return ''
@property
def googlebooks_id(self):
try:
return self.identifiers.filter(type='goog')[0].value
except IndexError:
return ''
@property
def librarything_id(self):
try:
return self.identifiers.filter(type='thng')[0].value
except IndexError:
return ''
@property
def oclc(self):
try:
return self.identifiers.filter(type='oclc')[0].value
except IndexError:
return ''
@property
def goodreads_id(self):
try:
return self.identifiers.filter(type='gdrd')[0].value
except IndexError:
return ''
@classmethod
def get_by_isbn(klass, isbn):
if length(isbn)==10:
isbn=regluit.core.isbn.convert_10_to_13(isbn)
for e in Edition.objects.filter( Q(isbn_13=isbn) ):
return e
return None
try:
return Identifier.objects.get( type='isbn', value=isbn ).edition
except Identifier.DoesNotExist:
return None
class Ebook(models.Model):
created = models.DateTimeField(auto_now_add=True)
@ -456,9 +536,9 @@ class Wishlist(models.Model):
def add_work(self, work, source):
try:
w = Wishes.objects.get(wishlist=self,work=work)
w.source=source
except:
w = Wishes.objects.get(wishlist=self,work=work)
w.source=source
except:
Wishes.objects.create(source=source,wishlist=self,work=work)
def remove_work(self, work):

View File

@ -28,7 +28,7 @@ class BookLoaderTests(TestCase):
edition = bookloader.add_by_isbn('0441012035')
self.assertEqual(edition.title, 'Neuromancer')
self.assertEqual(edition.publication_date, '2004')
self.assertEqual(edition.publisher, 'Ace Books')
self.assertEqual(edition.publisher, u'Ace Hardcover')
self.assertEqual(edition.isbn_10, '0441012035')
self.assertEqual(edition.isbn_13, '9780441012039')
self.assertEqual(edition.googlebooks_id, "2NyiPwAACAAJ")
@ -39,6 +39,7 @@ class BookLoaderTests(TestCase):
# work
self.assertTrue(edition.work)
def test_double_add(self):
bookloader.add_by_isbn('0441012035')
@ -48,7 +49,7 @@ class BookLoaderTests(TestCase):
self.assertEqual(models.Work.objects.all().count(), 1)
def test_missing_isbn(self):
e = bookloader.add_by_isbn('0139391401')
e = bookloader.add_by_isbn_from_google('0139391401')
self.assertEqual(e, None)
def test_thingisbn(self):
@ -62,22 +63,22 @@ class BookLoaderTests(TestCase):
edition = bookloader.add_by_isbn('0441012035')
self.assertEqual(models.Edition.objects.count(), 1)
self.assertEqual(models.Work.objects.count(), 1)
lang=edition.work.language
# ask for related editions to be added using the work we just created
bookloader.add_related('0441012035')
self.assertTrue(models.Edition.objects.count() > 15)
self.assertEqual(models.Work.objects.count(), 1)
self.assertTrue(edition.work.editions.count() > 15)
self.assertEqual(models.Work.objects.filter(language=lang).count(), 1)
self.assertTrue(edition.work.editions.count() > 10)
# all the editions in the db should be tied to the work
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)
self.assertTrue(edition.work.publication_date)
edition.publication_date = None
self.assertTrue(edition.work.publication_date)
def test_merge_works(self):
# add two editions and see that there are two stub works
@ -159,6 +160,8 @@ class BookLoaderTests(TestCase):
self.assertTrue(len(subjects) > 10)
self.assertTrue('Science fiction' in subjects)
self.assertEqual(work.openlibrary_id, '/works/OL27258W')
self.assertEqual(work.goodreads_id, '14770')
self.assertEqual(work.librarything_id, '609')
class SearchTests(TestCase):

View File

@ -1,8 +1,7 @@
CELERYD_NODES="w1"
CELERYD_CHDIR="/opt/regluit/"
CELERYD_LOG_FILE="/var/log/celery/%n.log"
CELERYD_PID_FILE="/var/run/celery/%n.pid"
CELERYD_PID_FILE="/var/log/celery/%n.pid"
CELERYD_USER="celery"
CELERYD_GROUP="celery"
CELERYD="/opt/regluit/ENV/bin/django-admin.py celeryd"

View File

@ -1,12 +1,15 @@
WSGIPythonHome /opt/regluit/ENV
WSGISocketPrefix /opt/regluit
<VirtualHost *:80>
<VirtualHost _default_:80>
ServerName unglue.it
ServerAdmin info@gluejar.com
RewriteEngine On
RewriteCond %{SERVER_NAME} !^unglue.it$ [NC]
RewriteRule (.*) http://unglue.it$1 [R=301,L]
RewriteRule ^/$ https://unglue.it/ [R=301]
RewriteRule /admin(.*) https://unglue.it/admin$1 [R=301]
RewriteRule /accounts(.*) https://unglue.it/accounts$1 [R=301]
@ -33,6 +36,11 @@ SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
SSLCertificateChainFile /etc/ssl/certs/gd_bundle.crt
RewriteEngine On
RewriteCond %{SERVER_NAME} !^unglue.it$ [NC]
RewriteRule (.*) https://unglue.it$1 [R=301,L]
WSGIDaemonProcess regluit-ssl processes=4 threads=4 python-eggs=/tmp/regluit-python-eggs
WSGIScriptAlias / /opt/regluit/deploy/regluit.wsgi

View File

@ -123,9 +123,15 @@
<div class="listview panelfront side1 icons">
{% if status == 'No campaign yet' or status == 'INITIALIZED' %}
<span class="rounded"><span class="grey"><span class="panelnope">Wished by&nbsp;</span>{{ work.wished_by.count }}</span></span>
{% else %}
{% if work.first_pdf_url or work.first_epub_url %}
<span class="rounded"><span class="grey"><span class="panelnope">Loved by&nbsp;</span>{{ work.wished_by.count }}</span></span>
{% else %}{% if work.first_pdf_url or work.first_epub_url %}
<span class="listview boolist-ebook">
{% if work.first_epub_url %}
<a href="{{ work.first_epub_url }}">EPUB</a>
{% endif %}
{% if work.first_pdf_url %}
<a href="{{ work.first_pdf_url }}">PDF</a>
{% endif %}
</span>
{% else %}
<div class="booklist-status-img">
@ -135,16 +141,6 @@
{% endif %}{% endif %}
</div>
<div class="listview panelfront side1 ebooks">
{% if work.first_epub_url and work.first_pdf_url %}
<span class="listview boolist-ebook">
{% if work.first_epub_url %}
<a href="{{ work.first_epub_url }}">epub</a>
{% endif %}
{% if work.first_pdf_url %}
<a href="{{ work.first_pdf_url }}">pdf</a>
{% endif %}
</span>
{% endif %}
</div>
<div class="unglue-this panelfront side1 none">
<div class="unglue-this-inner1">

View File

@ -27,10 +27,10 @@
<p>Target: {{campaign.target}}</p>
<p>Deadline: {{campaign.deadline}}</p>
<p>Status: {{campaign.status}}</p>
<p>ISBN: {{campaign.work.editions.all.0.isbn_10}} | {{campaign.work.editions.all.0.isbn_13}} </p>
<p><a href="{% url widget isbn=campaign.work.editions.all.0.isbn_13 %}">Widget Link</a></p>
<p>ISBN: {{campaign.work.editions.all.0.isbn_10}} | {{campaign.work.first_isbn_13}} </p>
<p><a href="{% url widget isbn=campaign.work.first_isbn_13 %}">Widget Link</a></p>
<p>Embed a widget:</p>
<textarea rows="2" cols="80">&lt;iframe src="{{base_url}}/api/widget/{{campaign.work.editions.all.0.isbn_13}}/" width="152" height="325" frameborder="0"&gt;</iframe></textarea>
<textarea rows="2" cols="80">&lt;iframe src="{{base_url}}/api/widget/{{campaign.work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;</iframe></textarea>
<p>PayPal receiver: {{campaign.paypal_receiver}}</p>
<p>Current total (pledged/authorized): {{campaign.current_total}}</p>
<form method="POST" action="{% url campaign_by_id pk=campaign.id %}" onsubmit="test()">

View File

@ -90,7 +90,7 @@
<div class="{% cycle 'row1' 'row2' %}">
{% with campaign.status as status %}
{% with campaign.deadline as deadline %}
{% with campaign.work.editions.all.0.googlebooks_id as googlebooks_id %}
{% with campaign.work.googlebooks_id as googlebooks_id %}
{% with campaign.work as work %}
{% include "book_panel.html" %}
{% endwith %}{% endwith %}{% endwith %}{% endwith %}

View File

@ -23,7 +23,7 @@ Please fix the following before launching your campaign:
<div class="book-detail-info">
<h2 class="book-name">Title: <a href="{% url work campaign.work.id %}">{{ campaign.work.title }}</a></h2>
<h3 class="book-author">Authors: {{ campaign.work.author }}</h3>
<h3 class="book-year">Published: {{ campaign.work.editions.all.0.publication_date }}</h3>
<h3 class="book-year">Published: {{ campaign.work.publication_date }}</h3>
<h3 class="book-author">Language: {{ campaign.work.editions.all.0.language }}</h3>
<p>Target Price: {{ campaign.pretarget }}</p>
<p>End Date: {{ campaign.predeadline }}</p>

View File

@ -18,7 +18,7 @@
<div class="book-detail-info">
<h2 class="book-name">{{ work.title }}</h2>
<h3 class="book-author">{{ work.author }}</h3>
<h3 class="book-year">{{ work.editions.all.0.publication_date }}</h3>
<h3 class="book-year">{{ work.publication_date }}</h3>
<div class="find-book">
<label>Find it here</label>
<!-- todo: these should be a real thing -->

View File

@ -8,7 +8,7 @@
<div class="book-detail-info">
<h2 class="book-name">Title: {{ work.title }}</h2>
<h3 class="book-author">Authors: {{ work.author }}</h3>
<h3 class="book-year">Published: {{ work.editions.all.0.publication_date }}</h3>
<h3 class="book-year">Published: {{ work.publication_date }}</h3>
<h3 class="book-author">Language: {{ work.editions.all.0.language }}</h3>
</div>
<form action="#">

View File

@ -253,7 +253,7 @@ how do I integrate the your wishlist thing with the tabs thing?
<div class="{% cycle 'row1' 'row2' %}">
{% with work.last_campaign_status as status %}
{% with work.last_campaign.deadline as deadline %}
{% with work.editions.all.0.googlebooks_id as googlebooks_id %}
{% with work.googlebooks_id as googlebooks_id %}
{% include "book_panel.html" %}
{% endwith %}{% endwith %}{% endwith %}
</div>

View File

@ -83,7 +83,7 @@
<div class="{% cycle 'row1' 'row2' %}">
{% with work.last_campaign_status as status %}
{% with work.last_campaign.deadline as deadline %}
{% with work.editions.all.0.googlebooks_id as googlebooks_id %}
{% with work.googlebooks_id as googlebooks_id %}
{% include "book_panel.html" %}
{% endwith %}{% endwith %}{% endwith %}
</div>

View File

@ -28,38 +28,37 @@ jQuery(document).ready(function(){
<div class="js-main">
<div id="js-leftcol">
<div class="jsmodule rounded">
{% if work.last_campaign %}
{% if status == 'ACTIVE' %}
<div class="jsmod-content active{{ work.percent_unglued}}">
<span>
Campaign in Progress: <br />${{ work.last_campaign.current_total }}/${{ work.last_campaign.target }}
<div class="jsmod-content{% if status == 'ACTIVE' %} active{{ work.percent_unglued}}{% endif %}">
<span>
{% if work.first_epub_url or work.first_pdf_url %}
AVAILABLE!
{% else %}{% if work.last_campaign %}
{% if status == 'ACTIVE' %}
Campaign in Progress: <br />${{ work.last_campaign.current_total }}/${{ work.last_campaign.target }}
{% else %}
{% if status == 'SUCCESSFUL' %}
Unglued on {{ work.last_campaign.deadline|date:"M j, Y"}}! <br />${{ work.last_campaign.current_total }} raised of ${{ work.last_campaign.target }} goal
{% else %}{% if status == 'INITIALIZED' %}
Campaign starting soon
{% else %}{% if status == 'SUSPENDED' %}
Campaign suspended. <br />See <a href="/faq">FAQ</a>.
{% else %}{% if status == 'WITHDRAWN' %}
Campaign withdrawn. <br />See <a href="/faq">FAQ</a>.
{% else %}{% if wishers == 1 %}
{{ wishers }} Ungluer is WISHING
{% else %}
{{ wishers }} Ungluers are WISHING
{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}
{% endif %}
{% else %}
<div class="jsmod-content">
<span>
{% if status == 'SUCCESSFUL' %}
Unglued on {{ work.last_campaign.deadline|date:"M j, Y"}}! <br />${{ work.last_campaign.current_total }} raised of ${{ work.last_campaign.target }} goal
{% else %}{% if status == 'INITIALIZED' %}
Campaign starting soon
{% else %}{% if status == 'SUSPENDED' %}
Campaign suspended. <br />See <a href="/faq">FAQ</a>.
{% else %}{% if status == 'WITHDRAWN' %}
Campaign withdrawn. <br />See <a href="/faq">FAQ</a>.
{% else %}{% if wishers == 1 %}
{{ wishers }} Ungluer is WISHING
{% else %}
{{ wishers }} Ungluers are WISHING
{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}
{% else %}
<div class="jsmod-content">
<span>
{% if wishers == 1 %}
{{ wishers }} Ungluer is WISHING
{% else %}
{{ wishers }} Ungluers are WISHING
{% endif %}
{% endif %}
</span>
<span class="spacer">&nbsp;<br />&nbsp;</span>
{% if wishers == 1 %}
{{ wishers }} Ungluer is WISHING
{% else %}
{{ wishers }} Ungluers are WISHING
{% endif %}
{% endif %}{% endif %}
</span>
<span class="spacer">&nbsp;<br />&nbsp;</span>
</div>
</div>
{% include "explore.html" %}
@ -103,17 +102,41 @@ jQuery(document).ready(function(){
{% endif %}
</div>
</div>
{% if status == 'ACTIVE' %}
<div class="pledged-info"><div class="pledged-group">{% if work.last_campaign.supporters.count == 1 %}One Ungluer has {% else %} {{ work.last_campaign.supporters.count }} Ungluers have {% endif %}pledged ${{ work.last_campaign.current_total }}<br />toward a ${{ work.last_campaign.target }} goal </div><div class="status"><img src="/static/images/images/icon-book-37by25-{{ work.percent_unglued }}.png" /></div></div>
{% else %}
<div class="pledged-info"><div class="pledged-group">
{% if work.first_epub_url or work.first_pdf_url %}
{% if wishers == 1 %}
{{ wishers }} Ungluer has
1 Ungluer is
{% else %}
{{ wishers }} Ungluers are
{% endif %} enjoying this Work
{% else %}{% if status == 'ACTIVE' %}
{% if work.last_campaign.supporters.count == 1 %}
One Ungluer has
{% else %}
{{ work.last_campaign.supporters.count }} Ungluers have
{% endif %}
pledged ${{ work.last_campaign.current_total }}<br />toward a ${{ work.last_campaign.target }} goal
{% else %}
{% if wishers == 1 %}
1 Ungluer has
{% else %}
{{ wishers }} Ungluers have
{% endif %}wished for this Work</div><div class="status"><img src="/static/images/images/icon-book-37by25-{{ work.percent_unglued }}.png" /></div></div>
{% endif %}
{% endif %} wished for this Work
{% endif %}{% endif %}
</div>
<div class="status"><img src="/static/images/images/icon-book-37by25-{% if work.first_epub_url or work.first_pdf_url %}6{%else%}{{ work.percent_unglued }}{%endif%}.png" /></div>
</div>
<div class="btn_wishlist">
{% if work.first_epub_url or work.first_pdf_url %}
<span class="boolist-ebook">
{% if work.first_epub_url %}
<a href="{{ work.first_epub_url }}">EPUB</a>
{% endif %}
{% if work.first_pdf_url %}
<a href="{{ work.first_pdf_url }}">PDF</a>
{% endif %}
</span>
{% endif %}
{% if request.user.is_anonymous %}
<div class="create-account">
<span title="{% url work work.id %}">Login to Add</span>
@ -128,7 +151,7 @@ jQuery(document).ready(function(){
</div>
{% else %}
<div class="add-wishlist">
<span id="{{ work.googlebooks_id }}">Add to Wishlist</span>
<span id="{{ work.googlebooks_id }}">Add to {% if work.first_epub_url or work.first_pdf_url %}Enjoying{% else %}Wishlist{% endif %}</span>
</div>
{% endif %}{% endif %}{% endif %}
</div>
@ -263,7 +286,7 @@ jQuery(document).ready(function(){
<a href="https://twitter.com/intent/tweet?url={{request.build_absolute_uri|urlencode:"" }}&text=I'm%20ungluing%20{{ work.title|urlencode }}%20at%20%40unglueit"><li class="twitter"><span>Twitter</span></li></a>
{% if request.user.is_authenticated %}<a href="{% url emailshare %}?next={{request.build_absolute_uri|urlencode:""}}"><li class="email"><span>Email</span></li></a>{% endif %}
<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="https://{{request.META.HTTP_HOST}}/api/widget/{{work.editions.all.0.isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>
<div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>
</ul>
</div>
</div>

View File

@ -87,7 +87,7 @@
<div class="{% cycle 'row1' 'row2' %}">
{% with work.last_campaign_status as status %}
{% with work.last_campaign.deadline as deadline %}
{% with work.editions.all.0.googlebooks_id as googlebooks_id %}
{% with work.googlebooks_id as googlebooks_id %}
{% include "book_panel.html" %}
{% endwith %}{% endwith %}{% endwith %}
</div>

View File

@ -47,6 +47,8 @@ class PageTests(TestCase):
# logged in
r = self.client.get("/supporter/test/")
self.assertEqual(r.status_code, 200)
r = self.client.get("/search/?q=sverige")
self.assertEqual(r.status_code, 200)
def test_view_by_other(self):
# someone else's supporter page
@ -60,6 +62,8 @@ class PageTests(TestCase):
self.assertEqual(r.status_code, 200)
r = anon_client.get("/")
self.assertEqual(r.status_code, 200)
r = anon_client.get("/search/?q=sverige")
self.assertEqual(r.status_code, 200)
class GoogleBooksTest(TestCase):

View File

@ -12,7 +12,6 @@ urlpatterns = patterns(
"regluit.frontend.views",
url(r"^$", "home", name="home"),
url(r"^supporter/(?P<supporter_username>.+)/$", "supporter", {'template_name': 'supporter.html'}, name="supporter"),
url(r"^supporter2/(?P<supporter_username>.+)/$", "supporter", {'template_name': 'supporter_panel.html'}, name="supporter2"),
url(r"^search/$", "search", name="search"),
url(r"^privacy/$", TemplateView.as_view(template_name="privacy.html"),
name="privacy"),

View File

@ -97,7 +97,7 @@ def work(request, work_id, action='display'):
except:
pledged = None
try:
pubdate = work.editions.all()[0].publication_date[:4]
pubdate = work.publication_date[:4]
except IndexError:
pubdate = 'unknown'
if not request.user.is_anonymous():
@ -156,8 +156,8 @@ def manage_campaign(request, id):
def googlebooks(request, googlebooks_id):
try:
edition = models.Edition.objects.get(googlebooks_id=googlebooks_id)
except models.Edition.DoesNotExist:
edition = models.Identifier.objects.get(type='goog',value=googlebooks_id).edition
except models.Identifier.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
@ -817,9 +817,9 @@ def search(request):
works=[]
for result in results:
try:
edition = models.Edition.objects.get(googlebooks_id=result['googlebooks_id'])
works.append(edition.work)
except models.Edition.DoesNotExist:
work = models.Identifier.objects.get(type='goog',value=result['googlebooks_id']).work
works.append(work)
except models.Identifier.DoesNotExist:
works.append(result)
context = {
"q": q,
@ -1161,7 +1161,7 @@ def work_librarything(request, work_id):
def work_openlibrary(request, work_id):
work = get_object_or_404(models.Work, id=work_id)
isbns = ["ISBN:" + e.isbn_13 for e in work.editions.filter(isbn_13__isnull=False)]
isbns = ["ISBN:" + i.value for i in work.identifiers.filter(type='isbn')]
url = None
if work.openlibrary_id: