diff --git a/___api/__init__.py b/___api/__init__.py new file mode 100644 index 0000000..6d4caf8 --- /dev/null +++ b/___api/__init__.py @@ -0,0 +1 @@ +__author__ = 'fergalm' diff --git a/___api/serializers.py b/___api/serializers.py new file mode 100644 index 0000000..faed3f6 --- /dev/null +++ b/___api/serializers.py @@ -0,0 +1,16 @@ +from rest_framework import serializers +from spa import models + + +class MixSerializer(serializers.ModelSerializer): + user = serializers.SlugRelatedField(slug_field='slug', read_only=True) + + class Meta: + model = models.Mix + + +class UserProfileSerializer(serializers.ModelSerializer): + mixes = serializers.HyperlinkedRelatedField(queryset=models.Mix.objects.all(), view_name='mix-detail', many=True) + + class Meta: + model = models.UserProfile diff --git a/___api/urls.py b/___api/urls.py new file mode 100755 index 0000000..9ef32a7 --- /dev/null +++ b/___api/urls.py @@ -0,0 +1,12 @@ +from ___api import views +from django.conf.urls import patterns, url, include +from rest_framework.routers import DefaultRouter + +router = DefaultRouter() +router.register(r'user', views.UserProfileViewSet) +router.register(r'mix', views.MixViewSet) + +urlpatterns = patterns( + '', + url(r'^', include(router.urls)), +) diff --git a/___api/views.py b/___api/views.py new file mode 100644 index 0000000..85ba844 --- /dev/null +++ b/___api/views.py @@ -0,0 +1,27 @@ +from rest_framework import viewsets +from rest_framework.permissions import IsAuthenticatedOrReadOnly + +from ___api import serializers +from spa import models + + +class MixViewSet(viewsets.ModelViewSet): + queryset = models.Mix.objects.all() + serializer_class = serializers.MixSerializer + + filter_fields = ( + 'waveform_generated', + 'slug', + 'user', + 'is_featured', + ) + +class UserProfileViewSet(viewsets.ModelViewSet): + queryset = models.UserProfile.objects.all().order_by('-id') # annotate(mix_count=Count('mixes')).order_by('-mix_count') + serializer_class = serializers.UserProfileSerializer + + permission_classes = (IsAuthenticatedOrReadOnly,) + lookup_field = 'slug' + filter_fields = ( + 'slug', + ) diff --git a/angular_upgrade.md b/angular_upgrade.md index 8d5e1fb..ccd3d9a 100755 --- a/angular_upgrade.md +++ b/angular_upgrade.md @@ -1,9 +1,9 @@ -#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 poorly saved descriptions + update spa_userprofile set description = '' where description like('Just another%') #import the avatars python manage.py get_avatars #jiggle the waveforms - python manage.py zoom_convert_waveforms \ No newline at end of file + python manage.py zoom_convert_waveforms + diff --git a/api/activity_helpers.py b/api/activity_helpers.py index e9c3488..e7af013 100644 --- a/api/activity_helpers.py +++ b/api/activity_helpers.py @@ -1,3 +1,4 @@ +import datetime from rest_framework.response import Response from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_201_CREATED from rest_framework.views import APIView @@ -16,8 +17,8 @@ class ActivityPlayHelper(ActivityHelper): mix = Mix.objects.get(slug=self.request.QUERY_PARAMS.get('id')) mix.add_play(request.user) data = { - 'user': request.user.get_nice_name() if request.user.is_authenticated() else settings.DEFAULT_USER_NAME, - 'date': mix.description + 'user': request.user.userprofile.get_nice_name() if request.user.is_authenticated() else settings.DEFAULT_USER_NAME, + 'date': datetime.datetime.now() } return Response(data, HTTP_201_CREATED) except Mix.DoesNotExist: diff --git a/api/auth.py b/api/auth.py index 163a924..affbf14 100755 --- a/api/auth.py +++ b/api/auth.py @@ -18,7 +18,6 @@ class LoginException(Exception): @strategy() def register_by_access_token(request, backend): - strat = load_strategy(request) auth = get_authorization_header(request).split() if not auth or auth[0].lower() != b'social': raise LoginException("Unable to register_by_access_token: No token header provided") @@ -93,7 +92,6 @@ class ObtainUser(APIView): model = Token def get(self, request): - serializer = self.serializer_class(data=request.DATA) if request.META.get('HTTP_AUTHORIZATION'): auth = request.META.get('HTTP_AUTHORIZATION').split() @@ -107,7 +105,7 @@ class ObtainUser(APIView): return Response({'id': token.user_id, 'name': token.user.username, 'firstname': token.user.first_name, 'userRole': 'user', 'token': token.key}) else: - return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED) + return Response(status=status.HTTP_401_UNAUTHORIZED) class ObtainLogout(APIView): diff --git a/api/serialisers.py b/api/serializers.py similarity index 85% rename from api/serialisers.py rename to api/serializers.py index 5defc1c..2c8252f 100755 --- a/api/serialisers.py +++ b/api/serializers.py @@ -1,8 +1,9 @@ -import json -# from django.core.serializers import serialize from django.db.models import Count from rest_framework import serializers +from core.utils.html import strip_tags + from dss import settings +from spa import models from spa.models import Activity from spa.models.activity import ActivityDownload, ActivityPlay from spa.models.genre import Genre @@ -12,41 +13,6 @@ from spa.models.mix import Mix, MixUpdateException from spa.models.comment import Comment -class InlineUserProfileSerializer(serializers.ModelSerializer): - class Meta: - model = UserProfile - fields = ( - 'slug', - 'first_name', - 'last_name', - 'display_name', - 'avatar_image', - 'avatar_image_tiny', - ) - - first_name = serializers.ReadOnlyField(source='get_first_name') - last_name = serializers.ReadOnlyField(source='get_last_name') - display_name = serializers.ReadOnlyField(source='get_nice_name') - avatar_image = serializers.SerializerMethodField() - avatar_image_tiny = serializers.SerializerMethodField() - - def get_avatar_image(self, obj): - return obj.get_sized_avatar_image(64, 64) - - def get_avatar_image_tiny(self, obj): - return obj.get_sized_avatar_image(32, 32) - - def to_representation(self, instance): - if instance.user.is_anonymous(): - return { - 'avatar_image': settings.DEFAULT_USER_IMAGE, - 'display_name': settings.DEFAULT_USER_NAME, - 'slug': '' - } - - return super(serializers.ModelSerializer, self).to_representation(instance) - - class InlineMixSerializer(serializers.ModelSerializer): class Meta: model = Mix @@ -114,7 +80,7 @@ class InlineActivityDownloadSerializer(InlineActivitySerializer): class MixSerializer(serializers.ModelSerializer): class Meta: - model = Mix + model = models.Mix fields = [ 'id', 'slug', @@ -137,13 +103,13 @@ class MixSerializer(serializers.ModelSerializer): ] slug = serializers.ReadOnlyField(required=False) - user = InlineUserProfileSerializer(many=False, required=False, read_only=True) + user = serializers.SlugRelatedField(slug_field='slug', read_only=True) waveform_url = serializers.ReadOnlyField(source='get_waveform_url') waveform_progress_url = serializers.ReadOnlyField(source='get_waveform_progress_url') mix_image = serializers.ReadOnlyField(source='get_image_url') can_edit = serializers.SerializerMethodField() - genres = GenreSerializer(many=True, required=False, read_only=True) + genres = GenreSerializer(many=True, required=False, read_only=False) likes = LikeSerializer(many=True, required=False, read_only=False) # slug_field='slug', many=True, read_only=True) favourites = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True) plays = InlineActivityPlaySerializer(many=True, read_only=True, source='activity_plays') @@ -175,10 +141,17 @@ class MixSerializer(serializers.ModelSerializer): validated_data.pop('likes', None) # get any likes that aren't in passed bundle - plays = validated_data['downloads'] - for play in plays: - instance.add_play(play) - validated_data.pop('downloads', None) + if 'downloads' in validated_data: + plays = validated_data['downloads'] or [] + for play in plays: + instance.add_play(play) + validated_data.pop('downloads', None) + + if 'genres' in validated_data: + genres = validated_data['genres'] or [] + for genre in genres: + instance.add_genre(genre) + validated_data.pop('genres', None) return super(MixSerializer, self).update(instance, validated_data) except MixUpdateException, ex: @@ -188,7 +161,7 @@ class MixSerializer(serializers.ModelSerializer): return super(MixSerializer, self).is_valid(raise_exception) def get_avatar_image(self, obj): - return obj.user.get_sized_avatar_image(32, 32) + return obj.user.get_sized_avatar_image(64, 64) def get_can_edit(self, obj): user = self.context['request'].user @@ -210,9 +183,55 @@ class MixSerializer(serializers.ModelSerializer): return obj.is_liked(user) if user.is_authenticated() else False +class InlineUserProfileSerializer(serializers.ModelSerializer): + profile_image_small = serializers.SerializerMethodField() + profile_image_medium = serializers.SerializerMethodField() + profile_image_header = serializers.SerializerMethodField() + + class Meta: + model = UserProfile + fields = ( + 'slug', + 'first_name', + 'last_name', + 'display_name', + 'profile_image_small', + 'profile_image_medium', + 'profile_image_header', + ) + + first_name = serializers.ReadOnlyField(source='get_first_name') + last_name = serializers.ReadOnlyField(source='get_last_name') + display_name = serializers.ReadOnlyField(source='get_nice_name') + + def get_avatar_image(self, obj): + return obj.get_sized_avatar_image(64, 64) + + def get_avatar_image_tiny(self, obj): + return obj.get_sized_avatar_image(64, 64) + + def to_representation(self, instance): + if instance.user.is_anonymous(): + return { + 'avatar_image': settings.DEFAULT_USER_IMAGE, + 'display_name': settings.DEFAULT_USER_NAME, + 'slug': '' + } + + return super(serializers.ModelSerializer, self).to_representation(instance) + + def get_profile_image_small(self, obj): + return obj.get_sized_avatar_image(64, 64) + + def get_profile_image_medium(self, obj): + return obj.get_sized_avatar_image(170, 170) + + def get_profile_image_header(self, obj): + return obj.get_sized_avatar_image(1200, 150) + + class UserProfileSerializer(serializers.ModelSerializer): roles = serializers.SerializerMethodField() - mixes = InlineMixSerializer(many=True, required=False) likes = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True) favourites = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True) following = InlineUserProfileSerializer(many=True, read_only=True) @@ -224,6 +243,7 @@ class UserProfileSerializer(serializers.ModelSerializer): date_joined = serializers.SerializerMethodField() last_login = serializers.SerializerMethodField() title = serializers.SerializerMethodField() + description = serializers.SerializerMethodField() profile_image_small = serializers.SerializerMethodField() profile_image_medium = serializers.SerializerMethodField() profile_image_header = serializers.SerializerMethodField() @@ -246,7 +266,6 @@ class UserProfileSerializer(serializers.ModelSerializer): 'profile_image_medium', 'profile_image_header', 'slug', - 'mixes', 'likes', 'isme', 'favourites', @@ -258,12 +277,15 @@ class UserProfileSerializer(serializers.ModelSerializer): def get_title(self, obj): try: if obj.description: - return obj.description[:75] + (obj.description[75:] and '..') + return strip_tags(obj.description[:128] + (obj.description[128:] and '..')) else: return settings.DEFAULT_USER_TITLE except: return settings.DEFAULT_USER_TITLE + def get_description(self, obj): + return obj.description if obj.description else settings.DEFAULT_USER_TITLE + def get_roles(self, obj): return obj.get_roles() @@ -276,15 +298,6 @@ class UserProfileSerializer(serializers.ModelSerializer): def get_last_login(self, obj): return obj.user.last_login - def get_profile_image_small(self, obj): - return obj.get_sized_avatar_image(32, 32) - - def get_profile_image_medium(self, obj): - return obj.get_sized_avatar_image(170, 170) - - def get_profile_image_header(self, obj): - return obj.get_sized_avatar_image(1200, 150) - def get_top_tags(self, obj): return list( Genre.objects.filter(mix__user__slug='fergalmoran'). @@ -292,11 +305,19 @@ class UserProfileSerializer(serializers.ModelSerializer): order_by('-total'). values('total', 'description', 'slug')[0:3]) + def get_profile_image_small(self, obj): + return obj.get_sized_avatar_image(64, 64) + + def get_profile_image_medium(self, obj): + return obj.get_sized_avatar_image(170, 170) + + def get_profile_image_header(self, obj): + return obj.get_sized_avatar_image(1200, 150) + class CommentSerializer(serializers.HyperlinkedModelSerializer): - user = serializers.SlugRelatedField(slug_field='slug', read_only=True) + user = InlineUserProfileSerializer(source='get_comment_user', read_only=True) avatar_image = serializers.SerializerMethodField() - user_display_name = serializers.SerializerMethodField('get_display_name') mix = serializers.PrimaryKeyRelatedField(read_only=True) can_edit = serializers.SerializerMethodField() @@ -308,27 +329,35 @@ class CommentSerializer(serializers.HyperlinkedModelSerializer): 'time_index', 'date_created', 'user', - 'user_display_name', 'avatar_image', 'mix', - 'can_edit', + 'can_edit' ) + def get_comment_user(self, obj): + try: + if obj.user is not None: + return obj.user.get_nice_name() + except: + pass + + return settings.DEFAULT_USER_NAME + def get_display_name(self, obj): if obj.user is not None: - return obj.user.get_nice_name() + return obj.user.userprofile.get_nice_name() else: return settings.DEFAULT_USER_NAME def get_avatar_image(self, obj): if obj.user is not None: - return obj.user.get_sized_avatar_image(48, 48) + return obj.user.userprofile.get_sized_avatar_image(48, 48) else: return settings.DEFAULT_USER_IMAGE def get_can_edit(self, obj): user = self.context['request'].user - if user.is_authenticated(): + if user is not None and user.is_authenticated(): return user.is_staff or obj.user.id == user.userprofile.id return False diff --git a/api/urls.py b/api/urls.py index db39606..687bd3e 100755 --- a/api/urls.py +++ b/api/urls.py @@ -1,43 +1,38 @@ -from api.auth import ObtainAuthToken, ObtainUser, ObtainLogout -from api.activity_helpers import ActivityPlayHelper -from api.views import CommentViewSet, MixViewSet, UserProfileViewSet, NotificationViewSet, PartialMixUploadView, \ - GenreViewSet, ActivityViewSet, HitlistViewset, AttachedImageUploadView, DownloadItemView, SearchResultsView -from django.conf.urls import url, patterns, include -from rest_framework_nested import routers +from django.conf.urls import patterns, url, include +from rest_framework.routers import DefaultRouter -router = routers.SimpleRouter(trailing_slash=True) -router.register(r'notification', NotificationViewSet) -router.register(r'hitlist', HitlistViewset) -router.register(r'comments', CommentViewSet) -router.register(r'user', UserProfileViewSet, base_name='userprofile') -router.register(r'activity', ActivityViewSet, base_name='activity') +from api import views, auth, activity_helpers -router.register(r'mix', MixViewSet) -mix_router = routers.NestedSimpleRouter(router, r'mix', lookup='mix') -mix_router.register('comments', CommentViewSet) +router = DefaultRouter() # trailing_slash=True) + +router.register(r'user', views.UserProfileViewSet) +router.register(r'mix', views.MixViewSet) + + +router.register(r'notification', views.NotificationViewSet) +router.register(r'hitlist', views.HitlistViewSet) +router.register(r'comments', views.CommentViewSet) +router.register(r'activity', views.ActivityViewSet, base_name='activity') +router.register(r'genre', views.GenreViewSet, base_name='genre') -""" -router.register(r'hitlist', HitlistViewset, base_name='hitlist') -router.register(r'notification', NotificationViewSet, base_name='notification') -""" -router.register(r'genre', GenreViewSet, base_name='genre') urlpatterns = patterns( '', url(r'^', include(router.urls)), - url(r'^', include(mix_router.urls)), - url(r'_download/', DownloadItemView.as_view()), - url(r'_upload/$', PartialMixUploadView.as_view()), - url(r'_image/$', AttachedImageUploadView.as_view()), - url(r'_search/$', SearchResultsView.as_view()), + # url(r'^', include(mix_router.urls)), + url(r'_download/', views.DownloadItemView.as_view()), + url(r'_upload/$', views.PartialMixUploadView.as_view()), + url(r'_image/$', views.AttachedImageUploadView.as_view()), + url(r'_search/$', views.SearchResultsView.as_view()), url(r'^', include(router.urls)), - url(r'^login/', ObtainAuthToken.as_view()), - url(r'^user/', ObtainUser.as_view()), - url(r'^logout/', ObtainLogout.as_view()), - #url(r'^_tr/', RefreshToken.as_view()), + url(r'^login/', auth.ObtainAuthToken.as_view()), + url(r'^logout/', auth.ObtainLogout.as_view()), + + # url(r'^_tr/', RefreshToken.as_view()), + url(r'^__user/', auth.ObtainUser.as_view()), - url(r'^_act/play', ActivityPlayHelper.as_view()), + url(r'^_act/play', activity_helpers.ActivityPlayHelper.as_view()), url('', include('social.apps.django_app.urls', namespace='social')), ) diff --git a/api/views.py b/api/views.py index b212fe0..4e3c529 100755 --- a/api/views.py +++ b/api/views.py @@ -6,36 +6,41 @@ from django.core.files.base import ContentFile from django.core.files.storage import FileSystemStorage from django.db.models import Count from django.http.response import HttpResponse -from django.utils.encoding import smart_str from rest_framework import viewsets from rest_framework import views from rest_framework.decorators import detail_route +from rest_framework.permissions import BasePermission from rest_framework.parsers import FileUploadParser from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly from rest_framework.response import Response from rest_framework.status import HTTP_202_ACCEPTED, HTTP_401_UNAUTHORIZED, HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND, \ HTTP_200_OK, HTTP_204_NO_CONTENT -from rest_framework import filters -from api.serialisers import MixSerializer, UserProfileSerializer, NotificationSerializer, \ - ActivitySerializer, HitlistSerializer, CommentSerializer, GenreSerializer +from api import serializers from dss import settings -from core.tasks import create_waveform_task, archive_mix_task +from core.tasks import create_waveform_task from spa.models.genre import Genre -from spa.models.activity import Activity, ActivityPlay +from spa.models.activity import ActivityPlay from spa.models.mix import Mix from spa.models.comment import Comment from spa.models.notification import Notification from spa.models.userprofile import UserProfile - logger = logging.getLogger(__name__) +class AnonymousWriteUserDelete(BasePermission): + def has_permission(self, request, view): + return True + + def has_object_permission(self, request, view, obj): + return True + + class CommentViewSet(viewsets.ModelViewSet): queryset = Comment.objects.all() - serializer_class = CommentSerializer - permission_classes = (IsAuthenticatedOrReadOnly,) + serializer_class = serializers.CommentSerializer + permission_classes = (AnonymousWriteUserDelete,) filter_fields = ( 'comment', 'mix__slug', @@ -49,30 +54,45 @@ class CommentViewSet(viewsets.ModelViewSet): try: mix = Mix.objects.get(pk=self.request.DATA['mix_id']) if mix is not None: - serializer.save(mix=mix, user=self.request.user.userprofile) + serializer.save( + mix=mix, + user=self.request.user if self.request.user.is_authenticated() else None + ) except Mix.DoesNotExist: pass - + except Exception, ex: + pass class UserProfileViewSet(viewsets.ModelViewSet): queryset = UserProfile.objects.annotate(mix_count=Count('mixes')).order_by('-mix_count') - serializer_class = UserProfileSerializer + serializer_class = serializers.UserProfileSerializer permission_classes = (IsAuthenticatedOrReadOnly,) lookup_field = 'slug' filter_fields = ( 'slug', ) + def get_queryset(self): + if 'following' in self.request.QUERY_PARAMS: + ret = UserProfile.objects.filter(following__slug__in=[self.request.QUERY_PARAMS['following']]) + elif 'followers' in self.request.QUERY_PARAMS: + ret = UserProfile.objects.filter(followers__slug__in=[self.request.QUERY_PARAMS['followers']]) + else: + ret = super(UserProfileViewSet, self).get_queryset() + + return ret + class MixViewSet(viewsets.ModelViewSet): queryset = Mix.objects.all() - serializer_class = MixSerializer - lookup_field = 'slug' + serializer_class = serializers.MixSerializer permission_classes = (IsAuthenticatedOrReadOnly,) + lookup_field = 'slug' + filter_fields = ( 'waveform_generated', 'slug', - 'user', + 'user__slug', 'is_featured', ) @@ -126,7 +146,7 @@ class SearchResultsView(views.APIView): 'slug': mix.slug, 'url': mix.get_absolute_url(), 'description': mix.description - } for mix in Mix.objects.filter(title__icontains=q)[0:10]] + } for mix in Mix.objects.filter(title__icontains=q)[0:10]] return Response(m) return HttpResponse(status=HTTP_204_NO_CONTENT) @@ -165,14 +185,14 @@ class PartialMixUploadView(views.APIView): raise -class HitlistViewset(viewsets.ModelViewSet): +class HitlistViewSet(viewsets.ModelViewSet): queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count')[0:10] - serializer_class = HitlistSerializer + serializer_class = serializers.HitlistSerializer class ActivityViewSet(viewsets.ModelViewSet): - queryset = ActivityPlay.objects.all() #select_subclasses() - serializer_class = ActivitySerializer + queryset = ActivityPlay.objects.all() # select_subclasses() + serializer_class = serializers.ActivitySerializer def get_queryset(self): user = self.request.user @@ -194,7 +214,7 @@ class DownloadItemView(views.APIView): class NotificationViewSet(viewsets.ModelViewSet): queryset = Notification.objects.all() - serializer_class = NotificationSerializer + serializer_class = serializers.NotificationSerializer def get_queryset(self): user = self.request.user @@ -206,7 +226,7 @@ class NotificationViewSet(viewsets.ModelViewSet): class GenreViewSet(viewsets.ModelViewSet): queryset = Genre.objects.all() - serializer_class = GenreSerializer + serializer_class = serializers.GenreSerializer def get_queryset(self): if 'q' in self.request.QUERY_PARAMS: diff --git a/core/utils/html.py b/core/utils/html.py index 2bf8848..753d79a 100755 --- a/core/utils/html.py +++ b/core/utils/html.py @@ -1,18 +1,28 @@ from HTMLParser import HTMLParser + class HTMLStripper(HTMLParser): """ Class that cleans HTML, removing all tags and HTML entities. """ + def __init__(self): self.reset() self.fed = [] + def handle_data(self, d): self.fed.append(d) + def get_data(self): return ''.join(self.fed) + def strip(self, d): self.reset() self.fed = [] self.feed(d) - return self.get_data().strip() \ No newline at end of file + return self.get_data().strip() + +def strip_tags(html): + s = HTMLStripper() + s.feed(html) + return s.get_data() diff --git a/dss/psa.py b/dss/psa.py index 4dff0ff..dff67ff 100755 --- a/dss/psa.py +++ b/dss/psa.py @@ -19,7 +19,7 @@ SOCIAL_AUTH_PIPELINE = ( 'social.pipeline.user.get_username', 'social.pipeline.social_auth.associate_by_email', 'social.pipeline.user.create_user', - 'api.pipeline.save_profile', + 'spa.pipeline.save_profile', 'social.pipeline.social_auth.associate_user', 'social.pipeline.social_auth.load_extra_data', 'social.pipeline.user.user_details' diff --git a/dss/settings.py b/dss/settings.py index 6a037b3..399a363 100755 --- a/dss/settings.py +++ b/dss/settings.py @@ -92,7 +92,7 @@ MIDDLEWARE_CLASSES = ( # 'htmlmin.middleware.MarkRequestMiddleware', 'django_user_agents.middleware.UserAgentMiddleware', # 'spa.middleware.uploadify.SWFUploadMiddleware', - #'spa.middleware.sqlprinter.SqlPrintingMiddleware' if DEBUG else None, + 'spa.middleware.sqlprinter.SqlPrintingMiddleware' if DEBUG else None, # 'debug_toolbar.middleware.DebugToolbarMiddleware', ) @@ -216,3 +216,4 @@ DEFAULT_USER_TITLE = 'Just another DSS lover' SITE_NAME = 'Deep South Sounds' +THUMBNAIL_PREFIX = 'cache/_tn/' diff --git a/dss/urls.py b/dss/urls.py index de41a44..02e55db 100755 --- a/dss/urls.py +++ b/dss/urls.py @@ -6,10 +6,6 @@ from dss import settings admin.autodiscover() -# Uncomment the next two lines to enable the admin: -# from django.contrib import admin -# admin.autodiscover() - urlpatterns = patterns( '', url(r'^admin/', include(admin.site.urls)), diff --git a/spa/migrations/0070_auto__chg_field_comment_user.py b/spa/migrations/0070_auto__chg_field_comment_user.py new file mode 100644 index 0000000..e30193a --- /dev/null +++ b/spa/migrations/0070_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['auth.User'], 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['spa.UserProfile'], 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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': u"orm['auth.User']", '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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 5, 17, 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/comment.py b/spa/models/comment.py index a081a4a..99710ca 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(UserProfile, editable=False, null=True, blank=True) + user = models.ForeignKey(User, 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) @@ -22,16 +22,19 @@ class Comment(BaseModel): def create_activity(self): pass + def get_user(self): + return self.user.userprofile if self.user.is_authenticated() else self.user + @property def avatar_image(self): if self.user is None: return UserProfile.get_default_avatar_image() else: - return self.user.get_profile().get_avatar_image() + return self.user.userprofile.get_avatar_image() @property def user_display_name(self): if self.user is None: return UserProfile.get_default_display_name() else: - return self.user.get_profile().get_nice_name() + return self.user.userprofile.get_nice_name() diff --git a/spa/models/mix.py b/spa/models/mix.py index 4dbc03c..ccb2333 100755 --- a/spa/models/mix.py +++ b/spa/models/mix.py @@ -210,6 +210,19 @@ class Mix(BaseModel): except Exception, e: self.logger.exception("Error adding mix download: %s" % e.message) + def add_genre(self, new_genre): + # first look for genre by slug + genre = Genre.objects.get(slug=new_genre['slug']) + if not genre: + # need to find a genre by description + genre = Genre.objects.get(description__iexact=new_genre['description']) + if not genre: + genre = Genre(description=new_genre['description']) + + if genre: + self.genres.add(genre) + self.save() + def add_play(self, user): try: if user.is_authenticated(): diff --git a/spa/models/userprofile.py b/spa/models/userprofile.py index 1dea258..9060ce7 100755 --- a/spa/models/userprofile.py +++ b/spa/models/userprofile.py @@ -1,4 +1,5 @@ import logging +import os import urlparse from bitfield.models import BitField @@ -15,7 +16,6 @@ from core.utils.url import unique_slugify from dss import settings from spa.models.basemodel import BaseModel - logger = logging.getLogger(__name__) @@ -180,7 +180,10 @@ class UserProfile(BaseModel): if gravatar_exists: return get_gravatar_url(self.email) else: - return self.avatar_image + if os.path.exists(self.avatar_image.file.name): + return self.avatar_image + else: + return self.get_default_avatar_image() return UserProfile.get_default_avatar_image() @@ -202,4 +205,3 @@ class UserProfile(BaseModel): @classmethod def get_default_display_name(cls): return settings.DEFAULT_USER_NAME - diff --git a/api/pipeline.py b/spa/pipeline.py similarity index 100% rename from api/pipeline.py rename to spa/pipeline.py