diff --git a/angular_upgrade.md b/angular_upgrade.md index a466134..8d5e1fb 100755 --- a/angular_upgrade.md +++ b/angular_upgrade.md @@ -1,7 +1,5 @@ #update comments user_id to be userprofile_id - UPDATE spa_comment SET user_id = spa_userprofile.id - FROM spa_userprofile - WHERE spa_comment.user_id = spa_userprofile.user_id + UPDATE spa_comment SET user_id = spa_userprofile.id FROM spa_userprofile WHERE spa_comment.user_id = spa_userprofile.user_id #import the avatars diff --git a/api/serialisers.py b/api/serialisers.py index f788741..d668172 100755 --- a/api/serialisers.py +++ b/api/serialisers.py @@ -8,7 +8,7 @@ from spa.models.activity import ActivityDownload, ActivityPlay from spa.models.genre import Genre from spa.models.notification import Notification from spa.models.userprofile import UserProfile -from spa.models.mix import Mix +from spa.models.mix import Mix, MixUpdateException from spa.models.comment import Comment @@ -153,28 +153,31 @@ class MixSerializer(serializers.ModelSerializer): def update(self, instance, validated_data): # all nested representations need to be serialized separately here - likes = validated_data['likes'] + try: + likes = validated_data['likes'] - # get any likes that aren't in passed bundle - unliked = instance.likes.exclude(user__userprofile__slug__in=[l['slug'] for l in likes]) - for ul in unliked: - # check that the user removing the like is an instance of the current user - # for now, only the current user can like stuff - if ul == self.context['request'].user.userprofile: - instance.update_liked(ul, False) + # get any likes that aren't in passed bundle + unliked = instance.likes.exclude(user__userprofile__slug__in=[l['slug'] for l in likes]) + for ul in unliked: + # check that the user removing the like is an instance of the current user + # for now, only the current user can like stuff + if ul == self.context['request'].user.userprofile: + instance.update_liked(ul, False) - for like in likes: - # check that the user adding the like is an instance of the current user - # for now, only the current user can like stuff - try: - user = UserProfile.objects.get(slug=like['slug']) - if user is not None and user == self.context['request'].user.userprofile: - instance.update_favourite(user, True) + for like in likes: + # check that the user adding the like is an instance of the current user + # for now, only the current user can like stuff + try: + user = UserProfile.objects.get(slug=like['slug']) + if user is not None and user == self.context['request'].user.userprofile: + instance.update_liked(user, True) - except UserProfile.DoesNotExist: - pass - validated_data.pop('likes', None) - return super(MixSerializer, self).update(instance, validated_data) + except UserProfile.DoesNotExist: + pass + validated_data.pop('likes', None) + return super(MixSerializer, self).update(instance, validated_data) + except MixUpdateException, ex: + raise ex def is_valid(self, raise_exception=False): return super(MixSerializer, self).is_valid(raise_exception) diff --git a/dss/settings.py b/dss/settings.py index 869914e..6a037b3 100755 --- a/dss/settings.py +++ b/dss/settings.py @@ -116,6 +116,7 @@ INSTALLED_APPS = ( 'corsheaders', 'sorl.thumbnail', 'spa', + 'tinymce', 'spa.signals', 'core', #'schedule', diff --git a/requirements.txt b/requirements.txt index b08e5fd..9c8cc37 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,37 +1,41 @@ -Django>=1.6,<1.7 -django-extensions -django-sendfile -Werkzeug -psycopg2 -gunicorn -dropbox -django-dirtyfields -django-storages -django-user-sessions -django-cors-headers -django-rest-swagger -django-filter -django-grappelli -django-model_utils -django-dbbackup -django-user-agents -south - -sorl-thumbnail - -git+git://github.com/disqus/django-bitfield.git#django-bitfield -git+git://github.com/Azure/azure-sdk-for-python.git#azure -git+git://github.com/tschellenbach/Django-facebook.git#django-facebook -git+git://github.com/llazzaro/django-scheduler.git#django-scheduler -git+git://github.com/omab/python-social-auth.git#egg=python-social-auth -apache-libcloud -mandrill -djrill - -djangorestframework -drf-nested-routers -django-celery -pillow -django-gravatar2 - -mutagen +Django>=1.6,<1.7 +django-extensions +django-sendfile +Werkzeug +psycopg2 +gunicorn +dropbox +django-dirtyfields +django-storages +django-user-sessions +django-cors-headers +django-rest-swagger +django-filter +django-grappelli +django-model_utils +django-dbbackup +django-user-agents +south + +sorl-thumbnail + +git+git://github.com/disqus/django-bitfield.git#django-bitfield +git+git://github.com/Azure/azure-sdk-for-python.git#azure +git+git://github.com/tschellenbach/Django-facebook.git#django-facebook +git+git://github.com/llazzaro/django-scheduler.git#django-scheduler +git+git://github.com/omab/python-social-auth.git#egg=python-social-auth +apache-libcloud +mandrill +djrill + +djangorestframework +drf-nested-routers +django-celery +pillow +django-gravatar2 + +mutagen + +django-enumfield + +ipython diff --git a/spa/migrations/0069_auto__chg_field_comment_user.py b/spa/migrations/0069_auto__chg_field_comment_user.py new file mode 100644 index 0000000..bf44ffa --- /dev/null +++ b/spa/migrations/0069_auto__chg_field_comment_user.py @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as 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 'Comment.user' + db.alter_column(u'spa_comment', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.UserProfile'], null=True)) + + def backwards(self, orm): + + # Changing field 'Comment.user' + db.alter_column(u'spa_comment', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)) + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'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'}), + u'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'}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}) + }, + 'spa.activity': { + 'Meta': {'object_name': 'Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']", 'null': 'True', 'blank': 'True'}) + }, + 'spa.activitycomment': { + 'Meta': {'object_name': 'ActivityComment', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_comments'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activitydownload': { + 'Meta': {'object_name': 'ActivityDownload', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activityfavourite': { + 'Meta': {'object_name': 'ActivityFavourite', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_favourites'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activityfollow': { + 'Meta': {'object_name': 'ActivityFollow', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_follow'", 'to': "orm['spa.UserProfile']"}) + }, + 'spa.activitylike': { + 'Meta': {'object_name': 'ActivityLike', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activityplay': { + 'Meta': {'object_name': 'ActivityPlay', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'liked_comments'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'time_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']", 'null': 'True', 'blank': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}) + }, + 'spa.mix': { + 'Meta': {'ordering': "('-id',)", 'object_name': 'Mix'}, + 'archive_path': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}), + 'archive_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + 'filetype': ('django.db.models.fields.CharField', [], {'default': "'mp3'", 'max_length': '10'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'likes'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}), + 'mp3tags_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mixes'", 'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'waveform_version': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + 'spa.notification': { + 'Meta': {'ordering': "('-id',)", 'object_name': 'Notification'}, + 'accepted_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notifications'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notification_html': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'notification_text': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'notification_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'target': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}), + 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_notications'", 'to': "orm['spa.UserProfile']"}), + 'verb': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}) + }, + 'spa.playlist': { + 'Meta': {'object_name': 'Playlist'}, + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mixes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Mix']", 'symmetrical': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'playlists'", 'to': "orm['spa.UserProfile']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing_facebook': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_twitter': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'country': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'email_notifications': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_known_session': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 3, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/models/__init__.py b/spa/models/__init__.py index 33f529d..0c8a45f 100755 --- a/spa/models/__init__.py +++ b/spa/models/__init__.py @@ -6,11 +6,14 @@ from comment import Comment from venue import Venue from label import Label from mix import Mix -from activity import Activity +from activity import Activity, ActivityFollow, ActivityLike, ActivityComment, ActivityDownload, ActivityFavourite, \ + ActivityPlay + +from testrel import TestRelBase, TestRelChild + from notification import Notification from genre import Genre from tracklist import Tracklist from purchaselink import PurchaseLink from release import Release -#from show import Show from playlist import Playlist diff --git a/spa/models/activity.py b/spa/models/activity.py index e6bc902..f31131e 100755 --- a/spa/models/activity.py +++ b/spa/models/activity.py @@ -1,12 +1,15 @@ import abc from django.contrib.auth.models import AnonymousUser, User +from allauth.socialaccount.models import SocialToken +from datetime import datetime from django.db import models from model_utils.managers import InheritanceManager + from open_facebook import OpenFacebook + from core.utils.url import wrap_full from dss import settings - from spa.models.notification import Notification from spa.models.userprofile import UserProfile from spa.models.basemodel import BaseModel @@ -24,11 +27,10 @@ ACTIVITYTYPES = ( class Activity(BaseModel): objects = InheritanceManager() user = models.ForeignKey(UserProfile, null=True, blank=True) - date = models.DateTimeField(auto_now_add=True) def __unicode__(self): - return "{0}".format(self.get_object_name()) + return "%s" % self.get_object_name() def get_user(self): if self.user is not None: @@ -60,8 +62,6 @@ class Activity(BaseModel): else: action_type = "deepsouthsounds:play" - # TODO: re-enable this once I figure out psa - """ social_account = SocialToken.objects.filter(account__user=self.user.user, account__provider='facebook')[0] facebook = OpenFacebook(social_account.token) notification_html = { @@ -69,7 +69,6 @@ class Activity(BaseModel): } result = facebook.set('me/%s' % action_type, notification_html) print result - """ except Exception, ex: print ex.message pass @@ -95,8 +94,6 @@ class Activity(BaseModel): notification.notification_url = self.get_object_url() notification.verb = self.get_verb_past() notification.target = self.get_object_name() - - notification._activity = self notification.save() except Exception, ex: print "Error creating activity notification: %s" % ex.message @@ -105,27 +102,23 @@ class Activity(BaseModel): return '/api/v1/activity/%s' % self.id @abc.abstractmethod - def should_send_email(self): + def get_object_type(self): + return + + @abc.abstractmethod + def get_object_slug(self): pass @abc.abstractmethod def get_target_user(self): pass - @abc.abstractmethod - def get_object_type(self): - return - @abc.abstractmethod def get_object_name(self): - return - - @abc.abstractmethod - def get_object_url(self): pass @abc.abstractmethod - def get_object_slug(self): + def get_object_url(self): pass @abc.abstractmethod @@ -136,63 +129,52 @@ class Activity(BaseModel): return self.get_object_name() -class ActivityFavourite(Activity): - mix = models.ForeignKey('spa.Mix', related_name='activity_favourites') +class ActivityLike(Activity): + mix = models.ForeignKey('spa.Mix', related_name='activity_likes') - def __unicode__(self): - return "%s - %s" % (self.mix.user.get_nice_name(), self.date) - - def get_target_user(self): - return self.mix.user + class Meta: + app_label = 'spa' def get_object_type(self): return "mix" + def get_object_slug(self): + return self.mix.slug + + def get_target_user(self): + return self.mix.user + def get_object_name(self): return self.mix.title def get_object_url(self): return self.mix.get_absolute_url() - def get_object_slug(self): - return self.mix.slug - def get_object_singular(self): return "mix" def get_verb_past(self): - return "favourited" - - def should_send_email(self): - return self.to_user.email_notifications.favourites.is_set - - def save(self, force_insert=False, force_update=False, using=None, - update_fields=None): - self.__to_user = self.mix.user - return super(Activity, self).save(force_insert, force_update, using, update_fields) + return "liked" class ActivityFollow(Activity): to_user = models.ForeignKey('spa.UserProfile', related_name='activity_follow') - def __unicode__(self): - return "%s - %s" % (self.to_user.get_nice_name(), self.date) + def get_object_type(self): + return "user" + + def get_object_slug(self): + return self.to_user.slug def get_target_user(self): return self.to_user - def get_object_type(self): - return "user" - def get_object_name(self): return self.to_user.get_nice_name() def get_object_url(self): return self.to_user.get_profile_url() - def get_object_slug(self): - return self.to_user.slug - def get_object_singular(self): return "user" @@ -202,35 +184,46 @@ class ActivityFollow(Activity): def get_object_name_for_notification(self): return "You" - def should_send_email(self): - return self.to_user.email_notifications.follows.is_set - def save(self, force_insert=False, force_update=False, using=None, - update_fields=None): - self.__to_user = self.to_user - return super(Activity, self).save(force_insert, force_update, using, update_fields) - - -class ActivityPlay(Activity): - mix = models.ForeignKey('spa.Mix', related_name='activity_plays') - - def __unicode__(self): - return "%s - %s" % (self.mix.user.get_nice_name(), self.date) - - def get_target_user(self): - return self.mix.user +class ActivityFavourite(Activity): + mix = models.ForeignKey('spa.Mix', related_name='activity_favourites') def get_object_type(self): return "mix" + def get_object_slug(self): + return self.mix.slug + + def get_target_user(self): + return self.mix.user + def get_object_name(self): return self.mix.title def get_object_url(self): return self.mix.get_absolute_url() - def get_object_slug(self): - return self.mix.slug + def get_object_singular(self): + return "mix" + + def get_verb_past(self): + return "favourited" + + +class ActivityPlay(Activity): + mix = models.ForeignKey('spa.Mix', related_name='activity_plays') + + def get_object_type(self): + return "mix" + + def get_target_user(self): + return self.mix.user + + def get_object_name(self): + return self.mix.title + + def get_object_url(self): + return self.mix.get_absolute_url() def get_object_singular(self): return "mix" @@ -238,103 +231,52 @@ class ActivityPlay(Activity): def get_verb_past(self): return "played" - def save(self, force_insert=False, force_update=False, using=None, - update_fields=None): - self.__to_user = self.mix.user - return super(Activity, self).save(force_insert, force_update, using, update_fields) - - def should_send_email(self): - return self.to_user.email_notifications.plays.is_set - - -class ActivityLike(Activity): - mix = models.ForeignKey('spa.Mix', related_name='activity_likes') - - def __unicode__(self): - return "%s - %s" % (self.mix.user.get_nice_name(), self.date) - - def get_target_user(self): - return self.mix.user - - def get_object_type(self): - return "mix" - - def get_object_name(self): - return self.mix.title - - def get_object_url(self): - return self.mix.get_absolute_url() - - def get_object_slug(self): - return self.mix.slug - - def get_object_singular(self): - return "mix" - - def get_verb_past(self): - return "liked" - - def save(self, force_insert=False, force_update=False, using=None, - update_fields=None): - self.__to_user = self.mix.user - return super(Activity, self).save(force_insert, force_update, using, update_fields) - class ActivityDownload(Activity): mix = models.ForeignKey('spa.Mix', related_name='activity_downloads') - def get_target_user(self): - return self.mix.user - def get_object_type(self): return "mix" + def get_object_slug(self): + return self.mix.slug + + def get_target_user(self): + return self.mix.user + def get_object_name(self): return self.mix.title def get_object_url(self): return self.mix.get_absolute_url() - def get_object_slug(self): - return self.mix.slug - def get_object_singular(self): return "mix" def get_verb_past(self): return "downloaded" - def save(self, force_insert=False, force_update=False, using=None, - update_fields=None): - self.__to_user = self.mix.user - return super(Activity, self).save(force_insert, force_update, using, update_fields) - class ActivityComment(Activity): mix = models.ForeignKey('spa.Mix', related_name='activity_comments') - def get_target_user(self): - return self.mix.user - def get_object_type(self): return "mix" + def get_object_slug(self): + return self.mix.slug + + def get_target_user(self): + return self.mix.user + def get_object_name(self): return self.mix.title def get_object_url(self): return self.mix.get_absolute_url() - def get_object_slug(self): - return self.mix.slug - def get_object_singular(self): return "mix" def get_verb_past(self): - return "commented on" - - def save(self, force_insert=False, force_update=False, using=None, - update_fields=None): - self.__to_user = self.mix.user - return super(Activity, self).save(force_insert, force_update, using, update_fields) + return "commented on" \ No newline at end of file diff --git a/spa/models/basemodel.py b/spa/models/basemodel.py index cf45478..4a33fd3 100755 --- a/spa/models/basemodel.py +++ b/spa/models/basemodel.py @@ -3,11 +3,12 @@ import os from datetime import datetime from dirtyfields import DirtyFieldsMixin from django.db import models +from django.utils import simplejson from core.utils import url from dss import localsettings, settings -class BaseModel(DirtyFieldsMixin, models.Model): +class BaseModel(models.Model): logger = logging.getLogger(__name__) object_created = models.DateTimeField(auto_now_add=True, default=datetime.now()) diff --git a/spa/models/comment.py b/spa/models/comment.py index edf8496..a081a4a 100755 --- a/spa/models/comment.py +++ b/spa/models/comment.py @@ -9,7 +9,7 @@ class Comment(BaseModel): class Meta: app_label = 'spa' - user = models.ForeignKey(User, editable=False, null=True, blank=True) + user = models.ForeignKey(UserProfile, editable=False, null=True, blank=True) mix = models.ForeignKey(Mix, editable=False, null=True, blank=True, related_name='comments') comment = models.CharField(max_length=1024) date_created = models.DateTimeField(auto_now_add=True) diff --git a/spa/models/mix.py b/spa/models/mix.py index a89fdd1..4dbc03c 100755 --- a/spa/models/mix.py +++ b/spa/models/mix.py @@ -12,7 +12,8 @@ from core.utils import url from core.utils.audio import Mp3FileNotFoundException from core.utils.audio.mp3 import mp3_length, tag_mp3 from core.utils.url import unique_slugify, url_path_join -from spa.models.activity import ActivityDownload, ActivityPlay, ActivityFavourite, ActivityLike +from spa.models.activity import ActivityDownload, ActivityPlay, ActivityFavourite, \ + ActivityLike # , ActivityTestConcrete from spa.models.genre import Genre from dss import settings, localsettings from spa.models.userprofile import UserProfile @@ -54,6 +55,10 @@ class MixManager(models.Manager): return super(MixManager, self).get(id=id_or_slug) +class MixUpdateException(Exception): + pass + + class Mix(BaseModel): class Meta: app_label = 'spa' @@ -81,7 +86,7 @@ class Mix(BaseModel): duration = models.IntegerField(null=True, blank=True) archive_path = models.CharField(max_length=2048, null=True, blank=True) archive_updated = models.BooleanField(default=False) - #archive_details_updated = models.BooleanField(default=False) + # archive_details_updated = models.BooleanField(default=False) slug = models.SlugField() genres = models.ManyToManyField(Genre) @@ -142,7 +147,7 @@ class Mix(BaseModel): return 'http://%s%s' % (Site.objects.get_current().domain, self.get_absolute_url()) def get_download_url(self): - return self.get_stream_url() #'HTTP://%s/audio/download/%s' % (Site.objects.get_current().domain, self.pk) + return self.get_stream_url() # 'HTTP://%s/audio/download/%s' % (Site.objects.get_current().domain, self.pk) def get_waveform_path(self): return os.path.join(settings.MEDIA_ROOT, "waveforms/", "%s.%s" % (self.uid, "png")) @@ -222,8 +227,9 @@ class Mix(BaseModel): if user.user.is_authenticated(): if value: if self.favourites.filter(user=user).count() == 0: - fav = ActivityFavourite(user=user) - self.favourites.add(fav) + fav = ActivityFavourite(user=user) # , mix=self) + fav.save() + self.favourites.add(user) self.save() else: self.favourites.remove(user) @@ -239,7 +245,8 @@ class Mix(BaseModel): if user.user.is_authenticated(): if value: if self.likes.filter(user=user).count() == 0: - ActivityLike(user=user, mix=self).save() + v = ActivityLike(user=user, mix=self) + v.save() self.likes.add(user) self.save() else: @@ -247,6 +254,7 @@ class Mix(BaseModel): self.save() except Exception, ex: self.logger.error("Exception updating like: %s" % ex.message) + raise MixUpdateException(ex.message) def is_favourited(self, user): if user is None: @@ -263,4 +271,3 @@ class Mix(BaseModel): return self.likes.filter(user=user).count() != 0 return False -