From 167dccf5745f26849add7618c49766572f4078c2 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 8 Dec 2011 18:22:05 -0500 Subject: [PATCH] Wishlists are now filled using the Wishes intermediate table. It's named the same as previous intermediate table, and I've edited the migration so data is not lost. Also, I've added methods od Wishlists to add and remove Works. There are "source" and created columns on the Wishes table --- api/tests.py | 2 +- core/bookloader.py | 5 +- core/goodreads.py | 2 +- core/librarything.py | 2 +- core/management/commands/random_wishlists.py | 2 +- core/migrations/0006_wishes.py | 193 ++++++++++++++++ ...wishes_created__add_field_wishes_source.py | 207 ++++++++++++++++++ core/models.py | 27 +++ core/tests.py | 8 +- experimental/zotero_books.py | 2 +- frontend/views.py | 4 +- 11 files changed, 441 insertions(+), 13 deletions(-) create mode 100644 core/migrations/0006_wishes.py create mode 100644 core/migrations/0007_auto__add_field_wishes_created__add_field_wishes_source.py diff --git a/api/tests.py b/api/tests.py index 3c91a5c7..be2376e6 100755 --- a/api/tests.py +++ b/api/tests.py @@ -83,7 +83,7 @@ class ApiTests(TestCase): self.assertEqual(j['objects'][0]['in_wishlist'], False) w = models.Work.objects.get(editions__isbn_10='0441012035') - self.user.wishlist.works.add(w) + self.user.wishlist.add_work(w,'test') r = self.client.get('/api/v1/campaign/', data={ 'format': 'json', 'work__editions__isbn_10': '0441012035', diff --git a/core/bookloader.py b/core/bookloader.py index a5d3c0db..6183bdb1 100755 --- a/core/bookloader.py +++ b/core/bookloader.py @@ -171,8 +171,9 @@ def merge_works(w1, w2): campaign.work = w1 campaign.save() for wishlist in models.Wishlist.objects.filter(works__in=[w2]): - wishlist.works.remove(w2) - wishlist.works.add(w1) + w2source=wishlist.work_source(w2) + wishlist.remove_work(w2) + wishlist.add_work(w1, w2source) w2.delete() diff --git a/core/goodreads.py b/core/goodreads.py index 938aae0f..bf9985ee 100644 --- a/core/goodreads.py +++ b/core/goodreads.py @@ -290,7 +290,7 @@ def load_goodreads_shelf_into_wishlist(user, shelf_name='all', goodreads_user_id # let's not trigger too much traffic to Google books for now # regluit.core.tasks.add_related.delay(isbn) - user.wishlist.works.add(edition.work) + user.wishlist.add_work(edition.work, 'goodreads') logger.info("Work with isbn %s added to wishlist.", isbn) except Exception, e: logger.info ("Exception adding ISBN %s: %s", isbn, e) diff --git a/core/librarything.py b/core/librarything.py index d26c38dd..644e092b 100644 --- a/core/librarything.py +++ b/core/librarything.py @@ -219,7 +219,7 @@ def load_librarything_into_wishlist(user, lt_username, max_books=None): # let's not trigger too much traffic to Google books for now # regluit.core.tasks.add_related.delay(isbn) - user.wishlist.works.add(edition.work) + user.wishlist.add_work(edition.work, 'librarything') logger.info("Work with isbn %s added to wishlist.", isbn) except Exception, e: logger.info ("error adding ISBN %s: %s", isbn, e) diff --git a/core/management/commands/random_wishlists.py b/core/management/commands/random_wishlists.py index b61b3372..eb61b75c 100644 --- a/core/management/commands/random_wishlists.py +++ b/core/management/commands/random_wishlists.py @@ -14,7 +14,7 @@ class Command(BaseCommand): continue for work in Work.objects.all(): print "adding %s to %s's wishlist" % (work, user) - user.wishlist.works.add(work) + user.wishlist.add_work(work, 'random') except Exception, e: print e pass diff --git a/core/migrations/0006_wishes.py b/core/migrations/0006_wishes.py new file mode 100644 index 00000000..927ef15a --- /dev/null +++ b/core/migrations/0006_wishes.py @@ -0,0 +1,193 @@ +# 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): + pass + + + def backwards(self, orm): + pass + + + 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'}), + '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'}), + 'suspended': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'suspended_reason': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}), + 'withdrawn': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'withdrawn_reason': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"}) + }, + 'core.celerytask': { + 'Meta': {'object_name': 'CeleryTask'}, + 'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 12, 8, 9, 12, 15, 273108)', 'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}), + 'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'core.claim': { + 'Meta': {'object_name': 'Claim'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"}) + }, + 'core.ebook': { + 'Meta': {'object_name': 'Ebook'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}), + 'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'core.edition': { + 'Meta': {'object_name': 'Edition'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}), + 'goodreads_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'googlebooks_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), + 'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'max_length': '2', 'null': 'True'}), + 'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'oclc': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True'}), + 'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"}) + }, + 'core.premium': { + 'Meta': {'object_name': 'Premium'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}), + 'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '2'}) + }, + 'core.rightsholder': { + 'Meta': {'object_name': 'RightsHolder'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}), + 'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'core.subject': { + 'Meta': {'object_name': 'Subject'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", '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.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'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}), + 'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}) + } + } + + complete_apps = ['core'] diff --git a/core/migrations/0007_auto__add_field_wishes_created__add_field_wishes_source.py b/core/migrations/0007_auto__add_field_wishes_created__add_field_wishes_source.py new file mode 100644 index 00000000..bb4ea7d2 --- /dev/null +++ b/core/migrations/0007_auto__add_field_wishes_created__add_field_wishes_source.py @@ -0,0 +1,207 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + + # Adding field 'Wishes.created' + db.add_column('core_wishlist_works', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.date(2011, 12, 8), blank=True), keep_default=False) + + # Adding field 'Wishes.source' + db.add_column('core_wishlist_works', 'source', self.gf('django.db.models.fields.CharField')(default='', max_length=15, blank=True), keep_default=False) + + + def backwards(self, orm): + + + # Deleting field 'Wishes.created' + db.delete_column('core_wishlist_works', 'created') + + # Deleting field 'Wishes.source' + db.delete_column('core_wishlist_works', 'source') + + + 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'}), + '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'}), + 'suspended': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'suspended_reason': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}), + 'withdrawn': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'withdrawn_reason': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"}) + }, + 'core.celerytask': { + 'Meta': {'object_name': 'CeleryTask'}, + 'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 12, 8, 15, 46, 54, 337715)', 'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}), + 'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'core.claim': { + 'Meta': {'object_name': 'Claim'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"}) + }, + 'core.ebook': { + 'Meta': {'object_name': 'Ebook'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}), + 'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'core.edition': { + 'Meta': {'object_name': 'Edition'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}), + 'goodreads_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'googlebooks_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), + 'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'max_length': '2', 'null': 'True'}), + 'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'oclc': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True'}), + 'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), + 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"}) + }, + 'core.premium': { + 'Meta': {'object_name': 'Premium'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}), + 'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '2'}) + }, + 'core.rightsholder': { + 'Meta': {'object_name': 'RightsHolder'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}), + 'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'core.subject': { + 'Meta': {'object_name': 'Subject'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", '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.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', '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'}), + 'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}) + } + } + + complete_apps = ['core'] diff --git a/core/models.py b/core/models.py index 3407b9b4..252a9298 100755 --- a/core/models.py +++ b/core/models.py @@ -410,6 +410,33 @@ class Wishlist(models.Model): def __unicode__(self): return "%s's Wishlist" % self.user.username + + def add_work(self, work, source): + try: + 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): + w = Wishes.objects.filter(wishlist=self, work=work) + if w: + w.delete() + + def work_source(self, work): + w = Wishes.objects.filter(wishlist=self, work=work) + if w: + return w[0].source + else: + return '' + +class Wishes(models.Model): + created = models.DateTimeField(auto_now_add=True) + source = models.CharField(max_length=15, blank=True) + wishlist = models.ForeignKey('Wishlist') + work = models.ForeignKey('Work') + class Meta: + db_table = 'core_wishlist_works' class UserProfile(models.Model): created = models.DateTimeField(auto_now_add=True) diff --git a/core/tests.py b/core/tests.py index 803ced92..053ae415 100755 --- a/core/tests.py +++ b/core/tests.py @@ -86,8 +86,8 @@ class TestBookLoader(TestCase): # add the stub works to a wishlist user = User.objects.create_user('test', 'test@example.com', 'testpass') - user.wishlist.works.add(e1.work) - user.wishlist.works.add(e2.work) + user.wishlist.add_work(e1.work, 'test') + user.wishlist.add_work(e2.work, 'test') # create campaigns for the stub works c1 = models.Campaign.objects.create( @@ -248,9 +248,9 @@ class WishlistTest(TestCase): user = User.objects.create_user('test', 'test@example.com', 'testpass') edition = bookloader.add_by_isbn('0441012035') work = edition.work - user.wishlist.works.add(work) + user.wishlist.add_work(work, 'test') self.assertEqual(user.wishlist.works.count(), 1) - user.wishlist.works.remove(work) + user.wishlist.remove_work(work) self.assertEqual(user.wishlist.works.count(), 0) class SettingsTest(TestCase): diff --git a/experimental/zotero_books.py b/experimental/zotero_books.py index f0814801..a2078115 100644 --- a/experimental/zotero_books.py +++ b/experimental/zotero_books.py @@ -102,7 +102,7 @@ class MyZotero(Zotero2): edition = bookloader.add_by_isbn(isbn) # let's not trigger too much traffic to Google books for now # regluit.core.tasks.add_related.delay(isbn) - user.wishlist.works.add(edition.work) + user.wishlist.add_work(edition.work, 'zotero') logger.info("Work with isbn %s added to wishlist.", isbn) except Exception, e: logger.info ("error adding ISBN %s: %s", isbn, e) diff --git a/frontend/views.py b/frontend/views.py index 43eefa50..9d73dace 100755 --- a/frontend/views.py +++ b/frontend/views.py @@ -557,12 +557,12 @@ def wishlist(request): edition = bookloader.add_by_googlebooks_id(googlebooks_id) # add related editions asynchronously tasks.add_related.delay(edition.isbn_10) - request.user.wishlist.works.add(edition.work) + request.user.wishlist.add_work(edition.work,'user') # TODO: redirect to work page, when it exists return HttpResponseRedirect('/') elif remove_work_id: work = models.Work.objects.get(id=int(remove_work_id)) - request.user.wishlist.works.remove(work) + request.user.wishlist.remove_work(work) # TODO: where to redirect? return HttpResponseRedirect('/')