Initial commit

This commit is contained in:
Fergal Moran
2015-04-30 23:17:58 +01:00
commit 6f9f29f5fc
193 changed files with 23428 additions and 0 deletions

35
.gitignore vendored Normal file
View File

@@ -0,0 +1,35 @@
.gitignore~
.coverage
.keystore
tags
.tags
.tags_sorted_by_file
.idea
*.pyc
*.swp
media/*
build/*
_working/*
static/CACHE/*
dss/localsettings.py
dss/storagesettings.py
dss/celery_settings.py
dss.conf
dss/debugsettings.py
mysql
test.py
mysql2pgsql.yml
downloads.txt
plays.txt
dss_ah
fixtures.json
dss_test.db
dsskeys
.ropeproject/*
*.map
./dds.sublime-project
./dds.sublime-workspace
./__krud/*
reload
reset
__krud/

29
INSTALL Executable file
View File

@@ -0,0 +1,29 @@
#curl -u hb_client_2862_1:j2CbCM8H -H 'Accept: application/json' -H 'Content-type: application/json' http://c1.lon2.dediserve.com/virtual_machines.xml
apt-get install git python-virtualenv postgresql-common libsndfile1-dev libpng++-dev libpng12-dev libboost-program-options-dev libjpeg-dev python-dev libsox-fmt-mp3
virtualenv env
source env/bin/activate
git clone https://github.com/fergalmoran/dss.git dss
cd dss
pip install -r requirements.txt
#can't get gstreamer working in a virtualenv
#I installed it using apt and did this - it's dirty and horrid.
cp /usr/lib/python2.7/dist-packages/pygst.py /home/fergalm/Dropbox/Private/deepsouthsounds.com/nixenv/lib/python2.7/site-packages/
#setup db host
sudo -u postgres createuser deepsouthsounds --no-superuser --createdb --no-createrole --pwprompt
sudo -u postgres createdb deepsouthsounds --owner deepsouthsounds
#skip this in production, start with a default
if production:
python manage.py dbrestore
else
python manage.py syncdb
python manage.py migrate
#re-run compressor (stale paths will be in db)
python manage.py compress --force
git clone https://github.com/fergalmoran/dss.lib lib

14
LICENSE Executable file
View File

@@ -0,0 +1,14 @@
Copyright (c) 2012, Deep South Sounds (inc)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

17
README Executable file
View File

@@ -0,0 +1,17 @@
#Deep South Sounds
an open source audio sharing site
Technology Stack
--------------
##### Server
* Django
* Tastypie
* NodeJs (https://github.com/fergalmoran/dss-realtime)
* Celery
* RabbitMq
##### Client
* Backbone
* Marionette
* RequireJs

11
angular_upgrade.md Executable file
View File

@@ -0,0 +1,11 @@
#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
#import the avatars
python manage.py get_avatars
#jiggle the waveforms
python manage.py zoom_convert_waveforms

16
apache/django_live.wsgi Executable file
View File

@@ -0,0 +1,16 @@
import os
import sys
path = '/var/www/deepsouthsounds.com/dss'
if path not in sys.path:
sys.path.append(path)
path = '/var/www/deepsouthsounds.com'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'dss.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

0
api/__init__.py Executable file
View File

94
api/auth.py Executable file
View File

@@ -0,0 +1,94 @@
from requests import HTTPError
from rest_framework import parsers
from rest_framework.authentication import get_authorization_header
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.response import Response
from rest_framework.status import *
from rest_framework.views import APIView
from rest_framework import status
from rest_framework import renderers
from social.apps.django_app.utils import strategy, load_strategy, load_backend
from dss import settings
class LoginException(Exception):
pass
@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")
access_token = auth[1]
user = request.backend.do_auth(access_token)
return user
class ObtainAuthToken(APIView):
serializer_class = AuthTokenSerializer
model = Token
def post(self, request):
# Here we call PSA to authenticate like we would if we used PSA on server side.
try:
backend = request.META.get('HTTP_AUTH_BACKEND')
if backend is None:
# Work around django test client oddness
return Response("No Auth-Backend header specified", HTTP_400_BAD_REQUEST)
user = register_by_access_token(request, backend)
# If user is active we get or create the REST token and send it back with user data
if user and user.is_active:
token, created = Token.objects.get_or_create(user=user)
return Response({
'slug': user.userprofile.slug,
'token': token.key
})
except LoginException, ex:
return Response(ex.message, HTTP_400_BAD_REQUEST)
except HTTPError, ex:
return Response(ex.message, HTTP_400_BAD_REQUEST)
class ObtainUser(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
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()
if not auth or auth[0].lower() != b'token' or len(auth) != 2:
msg = 'Invalid token header. No credentials provided.'
return Response(msg, status=status.HTTP_401_UNAUTHORIZED)
token = Token.objects.get(key=auth[1])
if token and token.user.is_active:
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)
class ObtainLogout(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
model = Token
# Logout le user
def get(self, request):
return Response({'User': ''})

34
api/pipeline.py Executable file
View File

@@ -0,0 +1,34 @@
from django.core.files.base import ContentFile
from requests import request, ConnectionError
def save_profile(backend, user, response, is_new, *args, **kwargs):
if backend.name == 'google-oauth2':
if response.get('image') and response['image'].get('url'):
url = response['image'].get('url')
profile = user.userprofile
try:
response = request('GET', url)
response.raise_for_status()
except ConnectionError:
pass
else:
profile.avatar_image.save(u'',
ContentFile(response.content),
save=False)
profile.save()
elif backend.name == 'facebook':
profile = user.userprofile
url = 'http://graph.facebook.com/{0}/picture'.format(response['id'])
try:
response = request('GET', url, params={'type': 'large'})
response.raise_for_status()
except ConnectionError:
pass
else:
profile.avatar_image.save(u'',
ContentFile(response.content),
save=False
)
profile.save()

392
api/serialisers.py Executable file
View File

@@ -0,0 +1,392 @@
import json
# from django.core.serializers import serialize
from django.db.models import Count
from rest_framework import serializers
from dss import settings
from spa.models import Activity
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.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
fields = (
'title',
'slug',
'title',
'description',
'mix_image',
)
mix_image = serializers.ReadOnlyField(source='get_image_url')
class LikeSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = (
'display_name',
'slug',
)
display_name = serializers.ReadOnlyField(source='get_nice_name')
class GenreSerializer(serializers.ModelSerializer):
class Meta:
model = Genre
fields = (
'slug',
'description'
)
class InlineActivitySerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField()
def get_user(self, obj):
try:
if obj.user is not None:
return obj.user.get_nice_name()
except:
pass
return "Anomymouse"
class InlineActivityPlaySerializer(InlineActivitySerializer):
class Meta:
model = ActivityPlay
fields = (
'user',
'date'
)
class InlineActivityDownloadSerializer(InlineActivitySerializer):
class Meta:
model = ActivityDownload
fields = (
'user',
'date'
)
class MixSerializer(serializers.ModelSerializer):
class Meta:
model = Mix
fields = [
'id',
'slug',
'uid',
'title',
'description',
'user',
'duration',
'waveform_url',
'waveform_progress_url',
'mix_image',
# 'stream_url',
'download_allowed',
'can_edit',
'genres',
'likes',
'favourites',
'activity_plays',
'activity_downloads',
'is_liked',
]
slug = serializers.ReadOnlyField(required=False)
user = InlineUserProfileSerializer(many=False, required=False, 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)
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)
activity_plays = InlineActivityPlaySerializer(many=True, read_only=True)
activity_downloads = InlineActivityDownloadSerializer(read_only=True)
is_liked = serializers.SerializerMethodField(read_only=True)
def update(self, instance, validated_data):
# all nested representations need to be serialized separately here
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)
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)
except UserProfile.DoesNotExist:
pass
validated_data.pop('likes', None)
return super(MixSerializer, self).update(instance, validated_data)
def is_valid(self, raise_exception=False):
return super(MixSerializer, self).is_valid(raise_exception)
def get_avatar_image(self, obj):
return obj.user.get_sized_avatar_image(32, 32)
def get_can_edit(self, obj):
user = self.context['request'].user
if user.is_authenticated():
return user.is_staff or obj.user.id == user.userprofile.id
return False
def get_is_favourited(self, obj):
user = self.context['request'].user
return obj.is_favourited(user) if user.is_authenticated() else False
def get_validation_exclusions(self, instance=None):
exclusions = super(MixSerializer, self).get_validation_exclusions()
return exclusions + ['genres', 'comments', 'slug', 'user']
def get_is_liked(self, obj):
user = self.context['request'].user
return obj.is_liked(user) if user.is_authenticated() else False
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)
followers = InlineUserProfileSerializer(many=True, read_only=True)
first_name = serializers.ReadOnlyField(source='get_first_name')
last_name = serializers.ReadOnlyField(source='get_last_name')
display_name = serializers.ReadOnlyField(source='get_nice_name')
isme = serializers.SerializerMethodField()
date_joined = serializers.SerializerMethodField()
last_login = serializers.SerializerMethodField()
title = serializers.SerializerMethodField()
profile_image_small = serializers.SerializerMethodField()
profile_image_medium = serializers.SerializerMethodField()
profile_image_header = serializers.SerializerMethodField()
top_tags = serializers.SerializerMethodField()
class Meta:
model = UserProfile
lookup_field = 'slug'
fields = (
'roles',
'date_joined',
'last_login',
'first_name',
'last_name',
'display_name',
'description',
'title',
'profile_image_small',
'profile_image_medium',
'profile_image_header',
'slug',
'mixes',
'likes',
'isme',
'favourites',
'following',
'followers',
'top_tags',
)
def get_title(self, obj):
try:
if obj.description:
return obj.description[:75] + (obj.description[75:] and '..')
else:
return settings.DEFAULT_USER_TITLE
except:
return settings.DEFAULT_USER_TITLE
def get_roles(self, obj):
return obj.get_roles()
def get_isme(self, obj):
return self.context['request'].user.pk == obj.user_id
def get_date_joined(self, obj):
return obj.user.date_joined
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').
annotate(total=Count('mix')).
order_by('-total').
values('total', 'description', 'slug')[0:3])
class CommentSerializer(serializers.HyperlinkedModelSerializer):
user = serializers.SlugRelatedField(slug_field='slug', 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()
class Meta:
model = Comment
fields = (
'id',
'comment',
'time_index',
'date_created',
'user',
'user_display_name',
'avatar_image',
'mix',
'can_edit',
)
def get_display_name(self, obj):
if obj.user is not None:
return obj.user.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)
else:
return settings.DEFAULT_USER_IMAGE
def get_can_edit(self, obj):
user = self.context['request'].user
if user.is_authenticated():
return user.is_staff or obj.user.id == user.userprofile.id
return False
class HitlistSerializer(serializers.ModelSerializer):
display_name = serializers.SerializerMethodField(method_name='get_display_name')
avatar_image = serializers.SerializerMethodField(method_name='get_avatar_image')
class Meta:
model = UserProfile
fields = (
'display_name',
'description',
'slug',
'avatar_image'
)
def get_display_name(self, obj):
return obj.get_nice_name()
def get_avatar_image(self, obj):
return obj.get_sized_avatar_image(170, 170)
class ActivitySerializer(serializers.HyperlinkedModelSerializer):
from_user = InlineUserProfileSerializer(source='get_user')
to_user = InlineUserProfileSerializer(source='get_target_user')
verb = serializers.CharField(source='get_verb_past')
object_type = serializers.CharField(source='get_object_type')
object_name = serializers.CharField(source='get_object_name')
object_slug = serializers.CharField(source='get_object_slug')
class Meta:
model = Activity
fields = (
'id',
'date',
'from_user',
'to_user',
'verb',
'object_type',
'object_name',
'object_slug',
)
class NotificationSerializer(serializers.HyperlinkedModelSerializer):
from_user = UserProfileSerializer(many=False, required=False)
display_name = serializers.SerializerMethodField(method_name='get_display_name')
avatar_image = serializers.SerializerMethodField(method_name='get_avatar_image')
class Meta:
model = Notification
fields = (
'id',
'notification_url',
'from_user',
'display_name',
'avatar_image',
'verb',
'target',
)
def get_display_name(self, obj):
return settings.DEFAULT_USER_NAME if obj.from_user is None else obj.from_user.get_nice_name()
def get_avatar_image(self, obj):
return settings.DEFAULT_USER_IMAGE if obj.from_user is None else obj.from_user.get_sized_avatar_image(170, 170)

3
api/tests.py Executable file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

6
api/tests/upload.py Normal file
View File

@@ -0,0 +1,6 @@
import unittest
from spa.models.mix import Mix
class UploadTest(unittest.TestCase):
def run(self, result=None):
print "Argle Bargle"

38
api/urls.py Executable file
View File

@@ -0,0 +1,38 @@
from api.auth import ObtainAuthToken, ObtainUser, ObtainLogout
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
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')
router.register(r'mix', MixViewSet)
mix_router = routers.NestedSimpleRouter(router, r'mix', lookup='mix')
mix_router.register('comments', CommentViewSet)
"""
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(router.urls)),
url(r'^login/', ObtainAuthToken.as_view()),
url(r'^user/', ObtainUser.as_view()),
url(r'^logout/', ObtainLogout.as_view()),
url('', include('social.apps.django_app.urls', namespace='social')),
)

224
api/views.py Executable file
View File

@@ -0,0 +1,224 @@
import logging
import os
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
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.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 dss import settings
from core.tasks import create_waveform_task, archive_mix_task
from spa.models.genre import Genre
from spa.models.activity import Activity, 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 CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
filter_fields = (
'comment',
'mix__slug',
)
ordering_fields = (
'id',
)
def perform_create(self, serializer):
if 'mix_id' in self.request.DATA:
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)
except Mix.DoesNotExist:
pass
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.annotate(mix_count=Count('mixes')).order_by('-mix_count')
serializer_class = UserProfileSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
lookup_field = 'slug'
filter_fields = (
'slug',
)
class MixViewSet(viewsets.ModelViewSet):
queryset = Mix.objects.all()
serializer_class = MixSerializer
lookup_field = 'slug'
permission_classes = (IsAuthenticatedOrReadOnly,)
filter_fields = (
'waveform_generated',
'slug',
'user',
'is_featured',
)
@detail_route()
def stream_url(self, request, **kwargs):
mix = self.get_object()
return Response({'url': mix.get_stream_url()})
def get_queryset(self):
if 'friends' in self.request.QUERY_PARAMS:
if self.request.user.is_authenticated():
rows = Mix.objects.filter(user__in=self.request.user.userprofile.following.all())
return rows
else:
raise PermissionDenied("Not allowed")
else:
return Mix.objects.all()
def perform_create(self, serializer):
serializer.save(user=self.request.user.userprofile)
class AttachedImageUploadView(views.APIView):
parser_classes = (FileUploadParser,)
def post(self, request):
if request.FILES['file'] is None or request.DATA.get('data') is None:
return Response(status=HTTP_400_BAD_REQUEST)
file_obj = request.FILES['file']
file_hash = request.DATA.get('data')
try:
mix = Mix.objects.get(uid=file_hash)
if mix:
mix.mix_image = file_obj
mix.save()
return Response(HTTP_202_ACCEPTED)
except ObjectDoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
return Response(status=HTTP_401_UNAUTHORIZED)
class SearchResultsView(views.APIView):
def get(self, request, format=None):
q = request.GET.get('q', '')
if len(q) > 0:
m = [{
'title': mix.title,
'image': mix.get_image_url(),
'slug': mix.slug,
'url': mix.get_absolute_url(),
'description': mix.description
} for mix in Mix.objects.filter(title__icontains=q)[0:10]]
return Response(m)
return HttpResponse(status=HTTP_204_NO_CONTENT)
class PartialMixUploadView(views.APIView):
parser_classes = (FileUploadParser,)
permission_classes = (IsAuthenticated,)
# noinspection PyBroadException
def post(self, request):
try:
uid = request.META.get('HTTP_UPLOAD_HASH')
in_file = request.FILES['file'] if request.FILES else None
file_name, extension = os.path.splitext(in_file.name)
file_storage = FileSystemStorage(location=os.path.join(settings.CACHE_ROOT, "mixes"))
cache_file = file_storage.save("%s%s" % (uid, extension), ContentFile(in_file.read()))
response = 'File creation in progress'
try:
create_waveform_task.delay(in_file=os.path.join(file_storage.base_location, cache_file), uid=uid)
create_waveform_task.delay(in_file=os.path.join(file_storage.base_location, cache_file), uid=uid)
except Exception, ex:
response = \
'Unable to connect to waveform generation task, there may be a delay in getting your mix online'
file_dict = {
'response': response,
'size': in_file.size,
'uid': uid
}
return Response(file_dict, HTTP_202_ACCEPTED)
except Exception, ex:
logger.exception(ex.message)
raise
class HitlistViewset(viewsets.ModelViewSet):
queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count')[0:10]
serializer_class = HitlistSerializer
class ActivityViewSet(viewsets.ModelViewSet):
queryset = ActivityPlay.objects.all() #select_subclasses()
serializer_class = ActivitySerializer
def get_queryset(self):
user = self.request.user
if not user.is_authenticated():
raise PermissionDenied("Not allowed")
return ActivityPlay.objects.filter(mix__user=user).order_by("-id")
class DownloadItemView(views.APIView):
def get(self, request, *args, **kwargs):
try:
mix = Mix.objects.get(uid=request.query_params['uid'])
return Response({'url': mix.get_download_url()}, HTTP_200_OK)
except ObjectDoesNotExist:
return Response("Not Found", HTTP_404_NOT_FOUND)
class NotificationViewSet(viewsets.ModelViewSet):
queryset = Notification.objects.all()
serializer_class = NotificationSerializer
def get_queryset(self):
user = self.request.user
if not user.is_authenticated():
raise PermissionDenied("Not allowed")
return Notification.objects.filter(to_user=user).order_by('-date')[0:5]
class GenreViewSet(viewsets.ModelViewSet):
queryset = Genre.objects.all()
serializer_class = GenreSerializer
def get_queryset(self):
if 'q' in self.request.QUERY_PARAMS:
rows = Genre.objects \
.annotate(used=Count('mix')) \
.filter(description__icontains=self.request.QUERY_PARAMS['q']) \
.only('description') \
.order_by('-used')
return rows
else:
rows = Genre.objects \
.annotate(used=Count('mix')) \
.only('description') \
.order_by('-used')
return rows

1
core/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

1
core/analytics/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

25
core/analytics/google.py Executable file
View File

@@ -0,0 +1,25 @@
from django import template
from dss import settings
register = template.Library()
class ShowGoogleAnalyticsJS(template.Node):
def render(self, context):
code = getattr(settings, "GOOGLE_ANALYTICS_CODE", False)
if not code:
return "<!-- Google Analytics not included because you haven't set the settings.GOOGLE_ANALYTICS_CODE variable! -->"
if 'user' in context and context['user'] and context['user'].is_staff:
return "<!-- Google Analytics not included because you are a staff user! -->"
if settings.DEBUG:
return "<!-- Google Analytics not included because you are in Debug mode! -->"
return """<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '""" + str(code) + """', 'auto');
ga('send', 'pageview');
</script>"""

26
core/decorators.py Executable file
View File

@@ -0,0 +1,26 @@
from decorator import decorator
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template.context import RequestContext
@decorator
def render_template(func, *args, **kwargs):
"""
using example:
@render_template
def view(request, template='abc.html'):
slot = "this is a slot"
return template, {'slot' : slot}
"""
request = args[0]
_call = func(*args, **kwargs)
if isinstance(_call, HttpResponseRedirect):
return _call
if isinstance(_call, tuple):
template, context = _call
else:
template, context = _call, {}
return render_to_response(template, context_instance=RequestContext(request, context))

1
core/realtime/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

16
core/realtime/activity.py Executable file
View File

@@ -0,0 +1,16 @@
import requests
from core.serialisers import json
from dss import localsettings, settings
def post_activity(session_id, activity_url):
payload = {
'sessionid': session_id,
'message': activity_url
}
data = json.dumps(payload)
r = requests.post(localsettings.REALTIME_HOST + 'activity', data=data, headers=settings.REALTIME_HEADERS)
if r.status_code == 200:
return ""
else:
return r.text

33
core/realtime/notification.py Executable file
View File

@@ -0,0 +1,33 @@
import requests
import logging
from requests.packages.urllib3.exceptions import ConnectionError
from dss import localsettings
import json
# classes to avoid duplicating constants below
HEADERS = {
'content-type': 'application/json'
}
logger = logging.getLogger('spa')
def post_notification(session_id, image, message):
try:
payload = {
'sessionid': session_id,
'image': image,
'message': message
}
data = json.dumps(payload)
r = requests.post(
localsettings.REALTIME_HOST + 'notification',
data=data,
headers=HEADERS
)
if r.status_code == 200:
return ""
else:
return r.text
except ConnectionError:
#should probably implement some sort of retry in here
pass

1
core/serialisers/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

47
core/tasks.py Executable file
View File

@@ -0,0 +1,47 @@
import shutil
from celery.task import task
import os
from core.utils.cdn import upload_to_azure
try:
from django.contrib.gis.geoip import GeoIP
except ImportError:
pass
from core.utils.waveform import generate_waveform
from dss import settings
@task(time_limit=3600)
def create_waveform_task(in_file, uid):
out_file = os.path.join(settings.MEDIA_ROOT, 'waveforms/%s.png' % uid)
print "Creating waveform \n\tIn: %s\n\tOut: %s" % (in_file, out_file)
generate_waveform(in_file, out_file)
if os.path.isfile(out_file):
print "Waveform generated successfully"
out_file, extension = os.path.splitext(in_file)
new_file = os.path.join(settings.MEDIA_ROOT, "mixes", "%s%s" % (uid, extension))
print "Moving cache audio clip from %s to %s" % (in_file, new_file)
shutil.move(in_file, new_file)
print "Uid: %s" % uid
else:
print "Outfile is missing"
@task(time_limit=3600)
def archive_mix_task(in_file, uid):
print "Sending {0} to azure".format(uid)
upload_to_azure(in_file, uid)
@task
def update_geo_info_task(ip_address, profile_id):
try:
ip = '188.141.70.110' if ip_address == '127.0.0.1' else ip_address
if ip:
g = GeoIP()
city = g.city(ip)
country = g.country(ip)
print "Updated user location"
except Exception, e:
print e.message
pass

1
core/utils/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

1
core/utils/audio/__init__.py Executable file
View File

@@ -0,0 +1 @@
class Mp3FileNotFoundException(Exception): pass

29
core/utils/audio/mp3.py Executable file
View File

@@ -0,0 +1,29 @@
from mutagen.easyid3 import EasyID3, mutagen
from mutagen.id3 import ID3, TPE1, TIT2, TALB, TCON, COMM, TDRC
from mutagen.mp3 import MP3
from core.utils.audio import Mp3FileNotFoundException
def mp3_length(source_file):
try:
audio = MP3(source_file)
return audio.info.length
except IOError:
raise Mp3FileNotFoundException("Audio file not found: %s" % source_file)
def tag_mp3(source_file, artist, title, url="", album="", year="", comment="", genres=""):
try:
audio = EasyID3(source_file)
except mutagen.id3.ID3NoHeaderError:
audio = mutagen.File(source_file, easy=True)
audio.add_tags()
audio["artist"] = artist
audio["title"] = title
audio["genre"] = genres
audio["website"] = url
audio["copyright"] = "Deep South Sounds"
audio["album"] = album
audio.save(v1=2)

50
core/utils/cdn.py Executable file
View File

@@ -0,0 +1,50 @@
import os
from azure import WindowsAzureMissingResourceError
from azure.storage import BlobService
from core.utils.url import url_path_join
from dss import settings
from dss.storagesettings import AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY, AZURE_CONTAINER
from libcloud.storage.types import Provider
from libcloud.storage.providers import get_driver
def upload_to_azure(in_file, filetype, uid):
if os.path.isfile(in_file):
print "Uploading file for: %s" % in_file
file_name = "%s.%s" % (uid, filetype)
archive_path = url_path_join(settings.AZURE_ITEM_BASE_URL, settings.AZURE_CONTAINER, file_name)
cls = get_driver(Provider.AZURE_BLOBS)
driver = cls(settings.AZURE_ACCOUNT_NAME, settings.AZURE_ACCOUNT_KEY)
container = driver.get_container(container_name=settings.AZURE_CONTAINER)
with open(in_file, 'rb') as iterator:
obj = driver.upload_object_via_stream(
iterator=iterator,
container=container,
object_name=file_name
)
print "Uploaded"
return obj
return None
def set_azure_details(blob_name, download_name):
try:
blob_service = BlobService(AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY)
blob = blob_service.get_blob(AZURE_CONTAINER, blob_name)
if blob:
blob_service.set_blob_properties(
AZURE_CONTAINER,
blob_name,
x_ms_blob_content_type='application/octet-stream',
x_ms_blob_content_disposition='attachment;filename="{0}"'.format(download_name)
)
print "Processed: %s" % download_name
else:
print "No blob found for: %s" % download_name
except WindowsAzureMissingResourceError:
print "No blob found for: %s" % download_name
except Exception, ex:
print "Error processing blob %s: %s" % (download_name, ex.message)

6
core/utils/file.py Executable file
View File

@@ -0,0 +1,6 @@
import os
def generate_save_file_name(uid, prefix, filename):
filename, extension = os.path.splitext(filename)
ret = "%s%s" % ('/'.join([prefix, uid]), extension)
return ret

18
core/utils/html.py Executable file
View File

@@ -0,0 +1,18 @@
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()

80
core/utils/ice.py Executable file
View File

@@ -0,0 +1,80 @@
#!/usr/bin/python
"""Returns icecast metadata from a stream as a JSON object.
Optionally posts it to a url."""
import socket
import json
import urllib2
import getopt
import sys
def usage ():
print """usage:
-h host to get metadata from
-m mount to get metadata from
[-p port to get metadata from (default 8000)]
[-u url to post metadata to as json]"""
try:
optlist, cmdline = getopt.getopt(sys.argv[1:],'h:p:m:u:')
except getopt.GetoptError:
sys.stderr.write("invalid options\n")
usage()
sys.exit(1)
# defaults
port = 8000
# check options
for opt in optlist:
if opt[0] == '-h':
host=opt[1]
if opt[0] == '-p':
port=int(opt[1])
if opt[0] == '-m':
mount=opt[1]
if opt[0] == '-u':
posturl=opt[1]
# required options
try:
host
port
mount
except NameError:
usage()
sys.exit(1)
def get_data(host, port, mount):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect ((host, port))
s.sendall('GET %s HTTP/1.0\r\n'
'Host: %s:%d\r\n'
'User-Agent: Ice Meta Fetcher\r\n'
'Connection: close\r\n'
'Icy-Metadata: 1\r\n'
'\r\n' % (mount, host, port))
data = s.recv(1024).decode('utf-8', 'ignore').encode('utf-8')
s.close()
pdata = dict([d.split(':',1) for d in data.split('\r\n') if d.count("icy")])
if pdata.has_key("icy-br"):
return json.dumps(pdata)
jdata = get_data(host, port, mount)
#skip empty crap
if jdata:
print jdata
try:
# this post is optional
req = urllib2.Request(posturl, data=jdata, headers={'Content-Type': 'application/json',
'Referer': 'http://%s' % (host)})
r = urllib2.urlopen(req)
except NameError:
pass

44
core/utils/live.py Executable file
View File

@@ -0,0 +1,44 @@
import logging
import urllib2
from bs4 import BeautifulSoup
def _parseItem(soup, param):
try:
match = soup.find(text=param)
if match is not None:
return match.findNext('td').contents[0]
except Exception, ex:
logging.getLogger('core').exception("Error parsing ice stream details: " + ex.message)
return ""
def get_server_details(server, port, mount):
server = "http://%s:%s/status.xsl?mount=/%s" % (server, port, mount)
print "Getting info for %s" % server
try:
response = urllib2.urlopen(server)
html = response.read()
if html:
soup = BeautifulSoup(html)
info = {
'stream_title': _parseItem(soup, "Stream Title:"),
'stream_description': _parseItem(soup, "Stream Description:"),
'content_type': _parseItem(soup, "Content Type:"),
'mount_started': _parseItem(soup, "Mount started:"),
'quality': _parseItem(soup, "Quality:"),
'current_listeners': _parseItem(soup, "Current Listeners:"),
'peak_listeners': _parseItem(soup, "Peak Listeners:"),
'stream_genre': _parseItem(soup, "Stream Genre:"),
'current_song': _parseItem(soup, "Current Song:")
}
return info
else:
print "Invalid content found"
return None
except urllib2.URLError:
return "Unknown stream %s" % server
def get_now_playing(server, port, mount):
return get_server_details(server, port, mount)

41
core/utils/string.py Executable file
View File

@@ -0,0 +1,41 @@
__author__ = 'fergalm'
import re
def lreplace(string, pattern, sub):
"""
Replaces 'pattern' in 'string' with 'sub' if 'pattern' starts 'string'.
"""
return re.sub('^%s' % pattern, sub, string)
def rreplace(string, pattern, sub):
"""
Replaces 'pattern' in 'string' with 'sub' if 'pattern' ends 'string'.
"""
return re.sub('%s$' % pattern, sub, string)
def is_number(s):
try:
if len(s) > 0:
float(s)
return True
except ValueError:
pass
except IndexError:
pass
except Exception:
pass
return False
def trunc_lines(s, linecount):
ret = ""
cur = 0
for line in s.splitlines():
if cur < linecount:
ret += line + "\n"
cur += 1
else:
break
return ret

100
core/utils/url.py Executable file
View File

@@ -0,0 +1,100 @@
import urlparse
import re
from django.contrib.sites.models import Site
from django.template.defaultfilters import slugify
__author__ = 'fergalm'
def url_path_join(*parts):
"""Join and normalize url path parts with a slash."""
schemes, netlocs, paths, queries, fragments = zip(*(urlparse.urlsplit(part) for part in parts))
# Use the first value for everything but path. Join the path on '/'
scheme = next((x for x in schemes if x), '')
netloc = next((x for x in netlocs if x), '')
path = '/'.join(x.strip('/') for x in paths if x)
query = next((x for x in queries if x), '')
fragment = next((x for x in fragments if x), '')
return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
def urlclean(url):
#remove double slashes
ret = urlparse.urljoin(url, urlparse.urlparse(url).path.replace('//', '/'))
return ret
def unique_slugify(instance, value, slug_field_name='slug', queryset=None, slug_separator='-'):
"""
Calculates and stores a unique slug of ``value`` for an instance.
``slug_field_name`` should be a string matching the name of the field to
store the slug in (and the field to check against for uniqueness).
``queryset`` usually doesn't need to be explicitly provided - it'll default
to using the ``.all()`` queryset from the model's default manager.
"""
slug_field = instance._meta.get_field(slug_field_name)
slug = getattr(instance, slug_field.attname)
slug_len = slug_field.max_length
# Sort out the initial slug, limiting its length if necessary.
slug = slugify(value)
if slug_len:
slug = slug[:slug_len]
slug = _slug_strip(slug, slug_separator)
original_slug = slug
# Create the queryset if one wasn't explicitly provided and exclude the
# current instance from the queryset.
if queryset is None:
queryset = instance.__class__._default_manager.all()
if instance.pk:
queryset = queryset.exclude(pk=instance.pk)
# Find a unique slug. If one matches, at '-2' to the end and try again
# (then '-3', etc).
next = 2
while not slug or queryset.filter(**{slug_field_name: slug}):
slug = original_slug
end = '%s%s' % (slug_separator, next)
if slug_len and len(slug) + len(end) > slug_len:
slug = slug[:slug_len - len(end)]
slug = _slug_strip(slug, slug_separator)
slug = '%s%s' % (slug, end)
next += 1
return slug
def _slug_strip(value, separator='-'):
"""
Cleans up a slug by removing slug separator characters that occur at the
beginning or end of a slug.
If an alternate separator is used, it will also replace any instances of
the default '-' separator with the new separator.
"""
separator = separator or ''
if separator == '-' or not separator:
re_sep = '-'
else:
re_sep = '(?:-|%s)' % re.escape(separator)
# Remove multiple instances and if an alternate separator is provided,
# replace the default '-' separator.
if separator != re_sep:
value = re.sub('%s+' % re_sep, separator, value)
# Remove separator from the beginning and end of the slug.
if separator:
if separator != '-':
re_sep = re.escape(separator)
value = re.sub(r'^%s+|%s+$' % (re_sep, re_sep), '', value)
return value
def is_absolute(url):
return bool(urlparse.urlparse(url).scheme)
def wrap_full(url):
if not is_absolute(url):
url = "http://%s%s" % (Site.objects.get_current().domain, url)
return url

34
core/utils/waveform.py Executable file
View File

@@ -0,0 +1,34 @@
import subprocess
import traceback
import uuid
import os
from dss import settings
def generate_waveform(input_file, output_file):
try:
print "Starting decode : %s\n\tIn: %s\n\tOut: %s" % \
(settings.DSS_LAME_PATH, input_file, output_file)
convert_command = "%s %s -c 1 -t wav - | %s -w 1170 -h 140 -o %s /dev/stdin" % \
(settings.DSS_LAME_PATH, input_file, settings.DSS_WAVE_PATH, output_file)
print "Convert command: %s" % convert_command
result = os.system(convert_command)
print result
if os.path.exists(output_file):
#crop the image as it looks nice with zoom
from PIL import Image
import glob
im = Image.open(output_file)
w, h = im.size
im.crop((0, 0, w, h / 2)).save(output_file)
return output_file
else:
print "Unable to find working file, did LAME succeed?"
return ""
except Exception, ex:
print "Error generating waveform %s" % (ex)

1
core/widgets/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

4
core/widgets/upload.py Executable file
View File

@@ -0,0 +1,4 @@
from django.forms.widgets import ClearableFileInput
class FileUploadWidget(ClearableFileInput):
pass

0
dss/__init__.py Executable file
View File

41
dss/localsettings.initial.py Executable file
View File

@@ -0,0 +1,41 @@
import os
DEBUG = True
if os.name == 'posix':
DSS_TEMP_PATH = "/tmp/"
DSS_LAME_PATH = "sox"
DSS_WAVE_PATH = "wav2png"
else:
DSS_TEMP_PATH = "d:\\temp\\"
DSS_LAME_PATH = "D:\\Apps\\lame\\lame.exe"
DSS_WAVE_PATH = "d:\\Apps\\waveformgen.exe"
DATABASE_NAME = 'deepsouthsounds'
DATABASE_USER = 'deepsouthsounds'
DATABASE_PASSWORD = ''
# DATABASE_HOST = ''
PIPELINE_YUI_BINARY = ""
FACEBOOK_APP_SECRET = ''
JS_SETTINGS = {
'CHAT_HOST': "ext-test.deepsouthsounds.com:8081",
'API_URL': "/api/v1/",
'LIVE_STREAM_URL': "radio.deepsouthsounds.com",
'LIVE_STREAM_PORT': "8000",
'LIVE_STREAM_MOUNT': "mp3",
'DEFAULT_AUDIO_VOLUME': "50",
'SM_DEBUG_MODE': DEBUG,
'LIVE_STREAM_INFO_URL': "radio.deepsouthsounds.com:8000/mp3"
}
"""
WAVEFORM_URL = 'http://waveforms.podnoms.com/'
IMAGE_URL = 'http://images.podnoms.com/'
STATIC_URL = 'http://static.podnoms.com/'
"""
IMAGE_URL = 'http://ext-test.deepsouthsounds.com:8000/media/'
GOOGLE_ANALYTICS_CODE = ''
SENDFILE_BACKEND = 'sendfile.backends.development'
#SENDFILE_BACKEND = 'sendfile.backends.xsendfile'
#SENDFILE_BACKEND = 'sendfile.backends.nginx'

64
dss/logsettings.py Executable file
View File

@@ -0,0 +1,64 @@
import os
import localsettings
if os.name == 'posix':
LOG_FILE = '/tmp/dss.log'
else:
LOG_FILE = 'c:\\temp\\dss.log'
LOGGING = {
'version': 1,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': LOG_FILE,
'formatter': 'simple'
},
},
'loggers': {
'spa': {
'handlers': ['file', 'console'],
'level': 'DEBUG',
'propagate': True,
},
'core': {
'handlers': ['file', 'console', 'mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'django.request': {
'handlers': ['file', 'console', 'mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'django.db.backends': {
'level': 'DEBUG',
'handers': ['console'],
},
}
}

4
dss/paymentsettings.py Executable file
View File

@@ -0,0 +1,4 @@
PAYPAL_RECEIVER_EMAIL = "admin@deepsouthsounds.com"
PAYPAL_RETURN_URL = "http://ext-test.deepsouthsounds.com:8080/a9cef/pp-lb/rt"
PAYPAL_NOTIFY_URL = "http://ext-test.deepsouthsounds.com:8080/a9cef/pp-lb/nt"
PAYPAL_CANCEL_URL = "http://ext-test.deepsouthsounds.com:8080/a9cef/pp-lb/ct"

91
dss/pipelinesettings.py Executable file
View File

@@ -0,0 +1,91 @@
iPIPELINE_TEMPLATE_FUNC = "_.template"
PIPELINE_COMPILERS = (
'pipeline.compilers.coffee.CoffeeScriptCompiler',
)
PIPELINE_CSS = {
'css': {
'source_filenames': (
'css/dss.overrides.css',
'css/ace/dropzone.css',
'css/ace/uncompressed/jquery.gritter.css',
'css/ace/uncompressed/bootstrap.css',
'css/ace/uncompressed/ace.css',
'css/ace/uncompressed/ace-ie.css',
'css/ace/uncompressed/ace-skins.css',
'css/ace/uncompressed/font-awesome.css',
'css/ace/uncompressed/fullcalendar.css',
'css/ace/uncompressed/bootstrap-editable.css',
'css/jasny-bootstrap.css',
'css/select2.css',
'css/jquery.fileupload-ui.css',
'css/peneloplay.css',
'css/toastr.css',
'css/dss.main.css',
),
'output_filename': 'css/site.css'
}
}
PIPELINE_JS = {
'templates': {
'source_filenames': (
'js/dss/templates/*.jst',
),
'variant': 'datauri',
'output_filename': 'js/t.js',
},
'lib': {
'source_filenames': (
'js/lib/jquery.js',
'js/lib/jquery-ui.js',
'js/lib/moment.js',
'js/lib/typeahead.js',
'js/lib/sm/soundmanager2.js',
'js/lib/underscore.js',
'js/lib/underscore.templatehelpers.js',
'js/lib/backbone.js',
'js/lib/backbone.syphon.js',
'js/lib/backbone.associations.js',
'js/lib/backbone.marionette.js',
'js/lib/ace/uncompressed/bootstrap.js',
'js/lib/ace/uncompressed/ace.js',
'js/lib/ace/uncompressed/ace-elements.js',
'js/lib/ace/uncompressed/select2.js',
'js/lib/ace/uncompressed/fuelux/fuelux.wizard.js',
'js/lib/ace/ace/elements.wizard.js',
'js/lib/ace/uncompressed/bootstrap-wysiwyg.js',
'js/lib/ace/uncompressed/jquery.gritter.js',
'js/lib/ace/uncompressed/dropzone.js',
'js/lib/ace/uncompressed/fullcalendar.js',
'js/lib/ace/uncompressed/x-editable/bootstrap-editable.js',
'js/lib/ace/uncompressed/x-editable/ace-editable.js',
'js/lib/ajaxfileupload.js',
'js/lib/jasny.fileinput.js',
'js/lib/jquery.fileupload.js',
'js/lib/jquery.fileupload-process.js',
'js/lib/jquery.fileupload-audio.js',
'js/lib/jquery.fileupload-video.js',
'js/lib/jquery.fileupload-validate.js',
'js/lib/jquery.fileupload-ui.js',
'js/lib/jquery.fileupload-image.js',
'js/lib/jquery.iframe-transport.js',
'js/lib/jquery.ui.widget.js',
'js/lib/toastr.js',
'js/dss/*.coffee',
'js/dss/**/*.coffee',
'js/dss/apps/**/**/*.coffee',
),
'output_filename': 'js/a.js',
},
}

39
dss/psa.py Executable file
View File

@@ -0,0 +1,39 @@
from django.conf import global_settings
AUTHENTICATION_BACKENDS = global_settings.AUTHENTICATION_BACKENDS + (
'social.backends.open_id.OpenIdAuth',
'social.backends.google.GoogleOAuth2',
'social.backends.google.GooglePlusAuth',
'social.backends.twitter.TwitterOAuth',
'social.backends.yahoo.YahooOpenId',
'social.backends.facebook.FacebookOAuth2'
)
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.create_user',
'api.pipeline.save_profile',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
#SOCIAL_AUTH_GOOGLE_OAUTH2_USE_DEPRECATED_API = True
#SOCIAL_AUTH_GOOGLE_PLUS_USE_DEPRECATED_API = True
#SOCIAL_AUTH_GOOGLE_OAUTH2_IGNORE_DEFAULT_SCOPE = True
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
'https://mail.google.com/',
'https://www.googleapis.com/auth/admin.directory.user.readonly',
'https://www.googleapis.com/auth/admin.directory.orgunit.readonly',
'https://www.googleapis.com/auth/admin.directory.group.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
]
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

217
dss/settings.py Executable file
View File

@@ -0,0 +1,217 @@
# e Django settings for dss project.
import os
import mimetypes
from django.core.urlresolvers import reverse_lazy
import djcelery
from django.conf import global_settings
from dss import logsettings
from utils import here
from localsettings import *
from storagesettings import *
from paymentsettings import *
from psa import *
DEVELOPMENT = DEBUG
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('Fergal Moran', 'fergal.moran@gmail.com'),
)
MANAGERS = ADMINS
AUTH_PROFILE_MODULE = 'spa.UserProfile'
ALLOWED_HOSTS = ['*']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'deepsouthsounds',
'ADMINUSER': 'postgres',
'USER': DATABASE_USER,
'PASSWORD': DATABASE_PASSWORD,
'HOST': DATABASE_HOST,
}
}
import sys
if 'test' in sys.argv or 'test_coverage' in sys.argv:
print "Testing"
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
ROOT_URLCONF = 'dss.urls'
TIME_ZONE = 'Europe/Dublin'
LANGUAGE_CODE = 'en-ie'
SITE_ID = 1
USE_I18N = False
USE_L10N = True
s = True
SITE_ROOT = here('')
ADMIN_MEDIA_PREFIX = STATIC_URL + "grappelli/"
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'compressor.finders.CompressorFinder',
)
STATICFILES_DIRS = (
here('static'),
)
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
'django_facebook.context_processors.facebook',
'django.core.context_processors.request',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.contrib.auth.context_processors.auth',
# TODO: remove..
# `allauth` specific context processors
"allauth.account.context_processors.account",
"allauth.socialaccount.context_processors.socialaccount",
)
MIDDLEWARE_CLASSES = (
'django.middleware.gzip.GZipMiddleware',
'django.middleware.common.CommonMiddleware',
'user_sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
# 'htmlmin.middleware.HtmlMinifyMiddleware',
# 'htmlmin.middleware.MarkRequestMiddleware',
'django_user_agents.middleware.UserAgentMiddleware',
# 'spa.middleware.uploadify.SWFUploadMiddleware',
#'spa.middleware.sqlprinter.SqlPrintingMiddleware' if DEBUG else None,
# 'debug_toolbar.middleware.DebugToolbarMiddleware',
)
WSGI_APPLICATION = 'dss.wsgi.application'
TEMPLATE_DIRS = (here('templates'),)
INSTALLED_APPS = (
'grappelli',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'user_sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admindocs',
#'django_facebook',
'django_extensions',
'django_gravatar',
'djcelery',
'corsheaders',
'sorl.thumbnail',
'spa',
'spa.signals',
'core',
#'schedule',
'django_user_agents',
'social.apps.django_app.default',
# TODO: remove
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.twitter',
'south',
'dbbackup',
'djrill',
'rest_framework',
'rest_framework.authtoken',
'rest_framework_swagger',
)
# where to redirect users to after logging in
LOGIN_REDIRECT_URL = reverse_lazy('home')
LOGOUT_URL = reverse_lazy('home')
LOGGING = logsettings.LOGGING
FACEBOOK_APP_ID = '154504534677009'
djcelery.setup_loader()
AVATAR_STORAGE_DIR = MEDIA_ROOT + '/avatars/'
ACCOUNT_LOGOUT_REDIRECT_URL = '/'
INTERNAL_IPS = ('127.0.0.1', '86.44.166.21', '192.168.1.111')
TASTYPIE_DATETIME_FORMATTING = 'rfc-2822'
TASTYPIE_ALLOW_MISSING_SLASH = True
SENDFILE_ROOT = os.path.join(MEDIA_ROOT, 'mixes')
SENDFILE_URL = '/media/mixes'
SESSION_ENGINE = 'user_sessions.backends.db'
mimetypes.add_type("text/xml", ".plist", False)
HTML_MINIFY = not DEBUG
DEFAULT_FROM_EMAIL = 'DSS ChatBot <chatbot@deepsouthsounds.com>'
DEFAULT_HTTP_PROTOCOL = 'http'
EMAIL_BACKEND = 'djrill.mail.backends.djrill.DjrillBackend'
if DEBUG:
import mimetypes
mimetypes.add_type("image/png", ".png", True)
mimetypes.add_type("image/png", ".png", True)
mimetypes.add_type("application/x-font-woff", ".woff", True)
mimetypes.add_type("application/vnd.ms-fontobject", ".eot", True)
mimetypes.add_type("font/ttf", ".ttf", True)
mimetypes.add_type("font/otf", ".otf", True)
REALTIME_HEADERS = {
'content-type': 'application/json'
}
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
if 'test' in sys.argv:
try:
from test_settings import *
except ImportError:
pass
REST_FRAMEWORK = {
# Use hyperlinked styles by default.
# Only used if the `serializer_class` attribute is not set on a view.
'DEFAULT_MODEL_SERIALIZER_CLASS':
'rest_framework.serializers.HyperlinkedModelSerializer',
'DEFAULT_FILTER_BACKENDS': (
'rest_framework.filters.DjangoFilterBackend',
'rest_framework.filters.OrderingFilter',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'PAGINATE_BY': 12, # Default to 10
'PAGINATE_BY_PARAM': 'limit', # Allow client to override, using `?page_size=xxx`.
'MAX_PAGINATE_BY': 100 # Maximum limit allowed when using `?page_size=xxx`.}
}
DEFAULT_USER_IMAGE = 'assets/images/default-avatar-32.png'
DEFAULT_USER_NAME = 'Anonymouse'
DEFAULT_USER_TITLE = 'Just another DSS lover'
SITE_NAME = 'Deep South Sounds'

10
dss/test_settings.py Executable file
View File

@@ -0,0 +1,10 @@
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'dss_test.db',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}

34
dss/urls.py Executable file
View File

@@ -0,0 +1,34 @@
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.views.generic import TemplateView, RedirectView
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)),
url(r'^api/docs/', include('rest_framework_swagger.urls')),
url(r'^api/v2/', include('api.urls')),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
(r'^grappelli/', include('grappelli.urls')),
)
handler500 = 'spa.views.debug_500'
if settings.DEBUG:
from django.views.static import serve
_media_url = settings.MEDIA_URL
if _media_url.startswith('/'):
_media_url = _media_url[1:]
urlpatterns += patterns(
'',
(r'^%s(?P<path>.*)$' % _media_url,
serve,
{'document_root': settings.MEDIA_ROOT}))
del (_media_url, serve)

0
dss/warning_settings.py Executable file
View File

28
dss/wsgi.py Executable file
View File

@@ -0,0 +1,28 @@
"""
WSGI config for dss project.
This module contains the WSGI application used by Django's development server
and any production WSGI deployments. It should expose a module-level variable
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
this application via the ``WSGI_APPLICATION`` setting.
Usually you will have the standard Django WSGI application here, but it also
might make sense to replace the whole Django WSGI application with a custom one
that later delegates to the Django one. For example, you could introduce WSGI
middleware here, or combine a Django application with an application of another
framework.
"""
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dss.settings")
# This application object is used by any WSGI server configured to use this
# file. This includes Django's development server, if the WSGI_APPLICATION
# setting points here.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
# Apply WSGI middleware here.
# from helloworld.wsgi import HelloWorldApplication
# application = HelloWorldApplication(application)

10
manage.py Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dss.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)

5
pip_upgrade.py Executable file
View File

@@ -0,0 +1,5 @@
import pip
from subprocess import call
for dist in pip.get_installed_distributions():
call("pip install --upgrade " + dist.project_name, shell=True)

37
requirements.txt Executable file
View File

@@ -0,0 +1,37 @@
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

1
spa/__init__.py Executable file
View File

@@ -0,0 +1 @@
import signals

27
spa/admin.py Executable file
View File

@@ -0,0 +1,27 @@
from django.contrib import admin
from spa.models.genre import Genre
from spa.models.userprofile import UserProfile
from spa.models.chatmessage import ChatMessage
from spa.models.recurrence import Recurrence
from spa.models.release import Release
from spa.models.label import Label
from spa.models.mix import Mix
from spa.models.release import ReleaseAudio
from spa.models.venue import Venue
class DefaultAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user.get_profile()
obj.save()
admin.site.register(Mix)
admin.site.register(Genre)
admin.site.register(Label)
admin.site.register(Release, DefaultAdmin)
admin.site.register(ReleaseAudio)
admin.site.register(Venue)
admin.site.register(UserProfile)
admin.site.register(Recurrence)
admin.site.register(ChatMessage)

1
spa/api/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

48
spa/api/v1/ActivityResource.py Executable file
View File

@@ -0,0 +1,48 @@
import humanize
from tastypie.authentication import Authentication
from tastypie.authorization import Authorization
from tastypie.constants import ALL, ALL_WITH_RELATIONS
from spa.api.v1.BaseResource import BaseResource
from spa.models import UserProfile
from spa.models.activity import Activity
class ActivityResource(BaseResource):
class Meta:
queryset = Activity.objects.select_subclasses().order_by('-id')
resource_name = 'activity'
authorization = Authorization()
authentication = Authentication()
always_return_data = True
filtering = {
'user': ALL_WITH_RELATIONS
}
def dehydrate(self, bundle):
try:
if bundle.obj.user is not None:
user_name = bundle.obj.user.get_nice_name()
user_image = bundle.obj.user.get_small_profile_image()
user_profile = bundle.obj.user.get_profile_url()
else:
user_name = UserProfile.get_default_display_name()
user_image = UserProfile.get_default_avatar_image()
user_profile = ""
bundle.data["verb"] = bundle.obj.get_verb_past(),
bundle.data["object"] = bundle.obj.get_object_singular(),
bundle.data["item_name"] = bundle.obj.get_object_name(),
bundle.data["item_url"] = bundle.obj.get_object_url(),
bundle.data["user_name"] = user_name,
bundle.data["user_profile"] = user_profile,
bundle.data["user_image"] = user_image
return bundle
except AttributeError, ae:
self.logger.debug("AttributeError: Error dehydrating activity, %s" % ae.message)
except TypeError, te:
self.logger.debug("TypeError: Error dehydrating activity, %s" % te.message)
except Exception, ee:
self.logger.debug("Exception: Error dehydrating activity, %s" % ee.message)
return None

39
spa/api/v1/BaseResource.py Executable file
View File

@@ -0,0 +1,39 @@
import logging
from tastypie.resources import ModelResource
class BaseResource(ModelResource):
logger = logging.getLogger(__name__)
pass
def _remove_kwargs(self, *args, **kwargs):
for arg in args:
if arg in kwargs:
del kwargs['activity_sharing_networks_facebook']
return kwargs
@staticmethod
def hydrate_bitfield(field_name, bundle, object_field, choices, remove_field=True):
if not hasattr(bundle, field_name + '____processed'):
mask = 0
for choice in choices:
if choice[0] in bundle.data[field_name]:
if bundle.data[field_name][choice[0]]:
mask |= getattr(object_field, choice[0])
bundle.data[field_name] = mask
setattr(bundle, field_name + '____processed', True)
return bundle
@staticmethod
def dehydrate_bitfield(field_name, bundle, object_field, choices, remove_field=True):
if remove_field:
del bundle.data[field_name]
d = {}
for choice in choices:
d[choice[0]] = getattr(object_field, choice[0]).is_set
bundle.data[field_name] = d
return bundle

7
spa/api/v1/ChatResource.py Executable file
View File

@@ -0,0 +1,7 @@
from spa.api.v1.BaseResource import BaseResource
from spa.models.chatmessage import ChatMessage
class ChatResource(BaseResource):
class Meta:
queryset = ChatMessage.objects.all().order_by('-timestamp')
resource_name = 'chat'

66
spa/api/v1/CommentResource.py Executable file
View File

@@ -0,0 +1,66 @@
from tastypie import fields
from tastypie.authentication import Authentication
from tastypie.authorization import Authorization
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.http import HttpBadRequest, HttpMethodNotAllowed, HttpUnauthorized, HttpApplicationError, HttpNotImplemented
from spa.api.v1.BaseResource import BaseResource
from spa.models import Mix, UserProfile
from spa.models.activity import ActivityComment
from spa.models.comment import Comment
class CommentResource(BaseResource):
mix = fields.ToOneField('spa.api.v1.MixResource.MixResource', 'mix')
likes = fields.ToManyField('spa.api.v1.UserResource.UserResource',
'likes', related_name='favourites',
full=False, null=True)
class Meta:
queryset = Comment.objects.all().order_by('-date_created')
resource_name = 'comments'
filtering = {
"mix": ('exact',),
}
authorization = Authorization()
authentication = Authentication()
always_return_data = True
def dehydrate(self, bundle):
if bundle.obj.user is not None:
bundle.data['avatar_image'] = bundle.obj.user.get_profile().get_avatar_image()
bundle.data['user_url'] = bundle.obj.user.get_profile().get_absolute_url()
bundle.data['user_name'] = bundle.obj.user.get_profile().get_nice_name()
else:
bundle.data['avatar_image'] = UserProfile.get_default_avatar_image()
bundle.data['user_url'] = "/"
bundle.data['user_name'] = "Anonymouse"
if bundle.request.user.is_authenticated():
bundle.data['can_edit'] = bundle.request.user.is_staff or bundle.obj.user_id == bundle.request.user.id
else:
bundle.data['can_edit'] = False
return bundle
def obj_create(self, bundle, **kwargs):
bundle.data['user'] = bundle.request.user
try:
if 'mix_id' in bundle.data:
mix = Mix.objects.get_by_id_or_slug(bundle.data['mix_id'])
if mix is not None:
if bundle.request.user.is_authenticated():
ActivityComment(user=bundle.request.user.get_profile(), mix=mix).save()
return super(CommentResource, self).obj_create(bundle, user=bundle.request.user or None, mix=mix)
else:
ActivityComment(mix=mix).save()
return super(CommentResource, self).obj_create(bundle, mix=mix)
else:
return HttpBadRequest("Unable to find mix for supplied mix_id (candidate fields are slug & id).")
return HttpBadRequest("Missing mix_id field.")
except ImmediateHttpResponse, e:
self.logger.error("Error creating comment (%s)" % e.message)
return HttpUnauthorized("Git tae fuck!")
except Exception, e:
self.logger.error("Error creating comment (%s)" % e.message)
return HttpApplicationError("Unable to hydrate comment from supplied data.")

18
spa/api/v1/DebugResource.py Executable file
View File

@@ -0,0 +1,18 @@
from django.db.models import Count
from tastypie import fields
from tastypie.resources import ModelResource
from spa.models import UserProfile
class DebugResource(ModelResource):
total_tickets = fields.IntegerField(readonly=True)
class Meta:
queryset = UserProfile.objects.all()
ordering = ['total_tickets']
def get_object_list(self, request):
return super(DebugResource, self).get_object_list(request).annotate(total_tickets=Count('mixes', distinct=True))
def dehydrate_total_tickets(self, bundle):
return bundle.obj.total_tickets

41
spa/api/v1/EventResource.py Executable file
View File

@@ -0,0 +1,41 @@
from django.core.exceptions import ObjectDoesNotExist
import humanize
from tastypie.authorization import Authorization
from spa.api.v1.BaseResource import BaseResource
from spa.models.recurrence import Recurrence
"""
from spa.views.venue import Venue
from spa.views.event import Event
class EventResource(BackboneCompatibleResource):
class Meta:
queryset = Event.objects.all()
authorization = Authorization()
def obj_create(self, bundle, request=None, **kwargs):
bundle.data['user'] = {'pk': request.user.pk}
return super(EventResource, self).obj_create(bundle, request, user=request.user.get_profile())
def dehydrate(self, bundle):
bundle.data['item_url'] = 'event/%s' % bundle.obj.id
bundle.data['event_venue'] = bundle.obj.event_venue.venue_name
return bundle
def dehydrate_event_date(self, bundle):
return humanize.naturalday(bundle.obj.event_date)
def hydrate(self, bundle):
if 'event_venue' in bundle.data:
try:
venue = Venue.objects.get(venue_name__exact=bundle.data['event_venue'])
except ObjectDoesNotExist:
venue = Venue(venue_name=bundle.data['event_venue'], user=bundle.request.user)
venue.save()
bundle.obj.event_venue = venue
recurrence = Recurrence.objects.get(pk=bundle.data['event_recurrence_id'])
if recurrence != None:
bundle.obj.event_recurrence = recurrence
return bundle
"""

33
spa/api/v1/GenreResource.py Executable file
View File

@@ -0,0 +1,33 @@
from tastypie.authentication import Authentication
from tastypie.authorization import Authorization
from spa.api.v1.BaseResource import BaseResource
from spa.models import Genre
class GenreResource(BaseResource):
class Meta:
queryset = Genre.objects.all().order_by('description')
resource_name = 'genres'
excludes = ['resource_uri']
filtering = {
'slug': ('exact',),
}
authorization = Authorization()
authentication = Authentication()
always_return_data = True
def obj_create(self, bundle, **kwargs):
"""
Check to see if there is an existing genre for what was entered
"""
genre = Genre.objects.get(description=bundle.obj['description'])
if genre is not None:
bundle.obj = genre
return bundle
else:
ret = super(GenreResource, self).obj_create(bundle, bundle.request)
return ret

244
spa/api/v1/MixResource.py Executable file
View File

@@ -0,0 +1,244 @@
from django.conf.urls import url
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, InvalidPage
from django.db.models import Count
from django.http import Http404
from django.template.loader import render_to_string
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.constants import ALL_WITH_RELATIONS
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.fields import ToOneField
from tastypie.http import HttpGone, HttpUnauthorized
from tastypie.utils import trailing_slash
from dss import settings
from spa.api.v1.BaseResource import BaseResource
from spa.api.v1.CommentResource import CommentResource
from spa.api.v1.ActivityResource import ActivityResource
from spa.models.mix import Mix
from spa.models.show import Show
from spa.models.userprofile import UserProfile
class MixResource(BaseResource):
comments = fields.ToManyField('spa.api.v1.CommentResource.CommentResource',
'comments', null=True, full=True)
favourites = fields.ToManyField('spa.api.v1.UserResource.UserResource',
'favourites', related_name='favourites',
full=False, null=True)
likes = fields.ToManyField('spa.api.v1.UserResource.UserResource',
'likes', related_name='likes',
full=False, null=True)
genres = fields.ToManyField('spa.api.v1.GenreResource.GenreResource',
'genres', related_name='genres',
full=True, null=True)
class Meta:
queryset = Mix.objects.filter(is_active=True)
user = ToOneField('UserResource', 'user')
always_return_data = True
detail_uri_name = 'slug'
excludes = ['is_active', 'waveform-generated']
post_excludes = ['comments']
filtering = {'comments': ALL_WITH_RELATIONS,
'genres': ALL_WITH_RELATIONS,
'favourites': ALL_WITH_RELATIONS,
'likes': ALL_WITH_RELATIONS,
'title': ALL_WITH_RELATIONS,
'slug': ALL_WITH_RELATIONS, }
authorization = Authorization()
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/search%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('get_search'),
name="api_get_search"),
url(r"^(?P<resource_name>%s)/(?P<id>[\d]+)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_detail'),
name="api_dispatch_detail"),
url(r"^(?P<resource_name>%s)/random%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_random'), name="api_dispatch_random"),
url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d-]+)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
url(r"^(?P<resource_name>%s)/(?P<slug>\w[\w/-]*)/comments%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('get_comments'), name="api_get_comments"),
url(r"^(?P<resource_name>%s)/(?P<slug>\w[\w/-]*)/activity%s$" % (
self._meta.resource_name, trailing_slash()),
self.wrap_view('get_activity'), name="api_get_activity"),
]
def dispatch_random(self, request, **kwargs):
kwargs['pk'] = \
self._meta.queryset.values_list('pk', flat=True).order_by('?')[0]
return self.get_detail(request, **kwargs)
def get_comments(self, request, **kwargs):
try:
basic_bundle = self.build_bundle(request=request)
obj = self.cached_obj_get(bundle=basic_bundle,
**self.remove_api_resource_names(kwargs))
except ObjectDoesNotExist:
return HttpGone()
child_resource = CommentResource()
return child_resource.get_list(request, mix=obj)
def get_activity(self, request, **kwargs):
try:
basic_bundle = self.build_bundle(request=request)
obj = self.cached_obj_get(bundle=basic_bundle,
**self.remove_api_resource_names(kwargs))
except ObjectDoesNotExist:
return HttpGone()
child_resource = ActivityResource()
return child_resource.get_list(request, mix=obj)
def obj_create(self, bundle, **kwargs):
if 'is_featured' not in bundle.data:
bundle.data['is_featured'] = False
if 'download_allowed' not in bundle.data:
bundle.data['download_allowed'] = False
#AAAAAH - STOP BEING LAZY AND REMOVE THIS
if settings.DEBUG and bundle.request.user.is_anonymous():
bundle.data['user'] = UserProfile.objects.get(pk=2)
else:
bundle.data['user'] = bundle.request.user.get_profile()
ret = super(MixResource, self).obj_create(
bundle,
user=bundle.data['user'],
uid=bundle.data['upload-hash'],
extension=bundle.data['upload-extension'])
return ret
def obj_update(self, bundle, **kwargs):
#don't sync the mix_image, this has to be handled separately
bundle.data.pop('mix_image', None)
ret = super(MixResource, self).obj_update(bundle, bundle.request)
bundle.obj.update_favourite(bundle.request.user,
bundle.data['favourited'])
bundle.obj.update_liked(bundle.request.user,
bundle.data['liked'])
return ret
def apply_sorting(self, obj_list, options=None):
orderby = options.get('order_by', '')
if orderby == 'latest':
obj_list = obj_list.order_by('-id')
elif orderby == 'toprated':
obj_list = obj_list.annotate(
karma=Count('activity_likes')).order_by('-karma')
elif orderby == 'mostplayed':
obj_list = obj_list.annotate(
karma=Count('activity_plays')).order_by('-karma')
elif orderby == 'mostactive':
obj_list = obj_list.annotate(
karma=Count('comments')).order_by('-karma')
elif orderby == 'recommended':
obj_list = obj_list.annotate(
karma=Count('activity_likes')).order_by('-karma')
return obj_list
def apply_filters(self, request, applicable_filters):
semi_filtered = super(MixResource, self) \
.apply_filters(request, applicable_filters) \
.filter(waveform_generated=True)
f_user = request.GET.get('user', None)
if request.GET.get('stream'):
if request.user.is_anonymous():
raise ImmediateHttpResponse(
HttpUnauthorized("Only logged in users have a stream")
)
semi_filtered = semi_filtered.filter(
user__in=request.user.get_profile().following.all())
if request.GET.get('for_show'):
semi_filtered = semi_filtered.filter(show__isnull=True)
if f_user is not None:
semi_filtered = semi_filtered.filter(user__slug=f_user)
elif len(applicable_filters) == 0:
semi_filtered = semi_filtered.filter(is_featured=True)
return semi_filtered
def dehydrate_mix_image(self, bundle):
return bundle.obj.get_image_url(size="160x110")
def dehydrate(self, bundle):
bundle.data['waveform_url'] = bundle.obj.get_waveform_url()
bundle.data['audio_src'] = bundle.obj.get_stream_url()
bundle.data['user_name'] = bundle.obj.user.get_nice_name()
bundle.data['user_profile_url'] = bundle.obj.user.get_absolute_url()
bundle.data['user_profile_image'] = \
bundle.obj.user.get_small_profile_image()
bundle.data['item_url'] = '/mix/%s' % bundle.obj.slug
bundle.data['download_allowed'] = bundle.obj.download_allowed
bundle.data['favourite_count'] = bundle.obj.favourites.count()
bundle.data['play_count'] = bundle.obj.activity_plays.count()
bundle.data['download_count'] = bundle.obj.activity_downloads.count()
bundle.data['like_count'] = bundle.obj.activity_likes.count()
bundle.data['tooltip'] = render_to_string('inc/player_tooltip.html',
{'item': bundle.obj})
bundle.data['comment_count'] = bundle.obj.comments.count()
bundle.data['liked'] = bundle.obj.is_liked(bundle.request.user)
if bundle.request.user.is_authenticated():
bundle.data['can_edit'] = bundle.request.user.is_staff or \
bundle.obj.user_id == bundle.request.user.get_profile().id
else:
bundle.data['can_edit'] = False
if bundle.request.user.is_authenticated():
bundle.data['favourited'] = bundle.obj.favourites.filter(
user=bundle.request.user).count() != 0
else:
bundle.data['favourited'] = False
return bundle
def get_search(self, request, **kwargs):
self.method_check(request, allowed=['get'])
self.is_authenticated(request)
self.throttle_check(request)
# Do the query.
sqs = Mix.objects.filter(title__icontains=request.GET.get('q', ''))
paginator = Paginator(sqs, 20)
try:
page = paginator.page(int(request.GET.get('page', 1)))
except InvalidPage:
raise Http404("Sorry, no results on that page.")
objects = []
for result in page.object_list:
bundle = self.build_bundle(obj=result, request=request)
bundle = self.full_dehydrate(bundle)
objects.append(bundle)
object_list = {'objects': objects, }
self.log_throttled_access(request)
return self.create_response(request, object_list)

View File

@@ -0,0 +1,33 @@
from tastypie.authentication import SessionAuthentication
from tastypie.authorization import DjangoAuthorization
from spa.api.v1.BaseResource import BaseResource
from spa.models.notification import Notification
from spa.models.userprofile import UserProfile
class NotificationResource(BaseResource):
class Meta:
queryset = Notification.objects.order_by('-id')
resource_name = 'notification'
authentication = SessionAuthentication()
authorization = DjangoAuthorization()
always_return_data = True
excludes = ['accepted_date']
def authorized_read_list(self, object_list, bundle):
return object_list.filter(to_user=bundle.request.user)
def dehydrate(self, bundle):
if bundle.obj.from_user is not None:
bundle.data['user_url'] = bundle.obj.from_user.get_absolute_url()
bundle.data['user_image'] = bundle.obj.from_user.get_sized_avatar_image(42, 42)
bundle.data['user_name'] = bundle.obj.from_user.get_nice_name()
else:
bundle.data['user_url'] = "#"
bundle.data['user_image'] = UserProfile.get_default_avatar_image()
bundle.data['user_name'] = UserProfile.get_default_display_name()
return bundle
def alter_list_data_to_serialize(self, request, data):
data['meta']['is_new'] = Notification.objects.filter(to_user=request.user, accepted_date__isnull=True).count()
return data

82
spa/api/v1/PlaylistResource.py Executable file
View File

@@ -0,0 +1,82 @@
from django.db.models import Count
from django.conf.urls import url
from tastypie.authentication import SessionAuthentication, Authentication
from tastypie.authorization import DjangoAuthorization, Authorization
from tastypie import fields
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.http import HttpUnauthorized
from tastypie.utils import trailing_slash
from spa.api.v1.BaseResource import BaseResource
from spa.models import Playlist, Mix, UserProfile
class PlaylistResource(BaseResource):
user = fields.ToOneField('spa.api.v1.UserResource.UserResource', 'user')
mixes = fields.ManyToManyField('spa.api.v1.MixResource.MixResource', 'mixes', full=True, null=True)
class Meta:
queryset = Playlist.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count')
always_return_data = True
excludes = ['public']
authentication = Authentication()
authorization = Authorization()
def authorized_read_list(self, object_list, bundle):
if bundle.request.user.is_authenticated():
return object_list.filter(user=bundle.request.user)
raise ImmediateHttpResponse(
HttpUnauthorized("Git tae fuck")
)
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<id>[\d]+)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_detail'),
name="api_dispatch_detail"),
url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d-]+)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
def hydrate(self, bundle):
bundle.obj.user = bundle.request.user.get_profile()
return bundle
def dehydrate(self, bundle):
bundle.data['playlist_image'] = bundle.obj.get_image_url()
bundle.data['item_url'] = '/playlist/%s' % bundle.obj.slug
return bundle
def obj_update(self, bundle, skip_errors=False, **kwargs):
if 'playlist_image' in kwargs: del kwargs['playlist_image']
if 'item_url' in kwargs: del kwargs['item_url']
mixes = bundle.data['mixes']
bundle.data.pop('mixes')
result = super(PlaylistResource, self).obj_update(bundle, **kwargs)
if mixes:
for mix_item in mixes:
result.obj.mixes.add(Mix.objects.get(pk=mix_item['id']))
result.obj.save()
return result
def obj_create(self, bundle, **kwargs):
try:
mixes = bundle.data['mixes']
bundle.data.pop('mixes')
result = super(PlaylistResource, self).obj_create(bundle, **kwargs)
if mixes:
for mix_item in mixes:
result.obj.mixes.add(Mix.objects.get(pk=mix_item['id']))
result.obj.save()
return result
except Exception, ex:
print ex

View File

@@ -0,0 +1,17 @@
from tastypie import fields
from spa.api.v1.BaseResource import BaseResource
from spa.models.release import ReleaseAudio
class ReleaseAudioResource(BaseResource):
release = fields.ToOneField('spa.api.v1.ReleaseResource.ReleaseResource', 'release')
class Meta:
queryset = ReleaseAudio.objects.all()
resource_name = 'audio'
filtering = {
"release": ('exact',),
}
def dehydrate(self, bundle):
bundle.data['waveform_url'] = bundle.obj.get_waveform_url()
return bundle

41
spa/api/v1/ReleaseResource.py Executable file
View File

@@ -0,0 +1,41 @@
import datetime
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.constants import ALL_WITH_RELATIONS
from spa.api.v1.BaseResource import BaseResource
from spa.models import Label
from spa.models.release import Release
from django.core.exceptions import ObjectDoesNotExist
class ReleaseResource(BaseResource):
release_audio = fields.ToManyField('spa.api.v1.ReleaseAudioResource.ReleaseAudioResource', 'release_audio', 'release', null=True, blank=True)
class Meta:
queryset = Release.objects.all()
filtering = {
'release_audio' : ALL_WITH_RELATIONS
}
authorization = Authorization()
def obj_create(self, bundle, request=None, **kwargs):
bundle.data['user'] = {'pk': request.user.pk}
return super(ReleaseResource, self).obj_create(bundle, request, user=request.user.get_profile())
def hydrate(self, bundle):
if 'release_label' in bundle.data:
try:
label = Label.objects.get(name__exact=bundle.data['release_label'])
except ObjectDoesNotExist:
label = Label(name=bundle.data['release_label'])
label.save()
bundle.obj.release_label = label
return bundle
def dehydrate(self, bundle):
bundle.data['release_label'] = bundle.obj.release_label.name
bundle.data['item_url'] = 'release/%s' % bundle.obj.id
bundle.data['mode'] = 'release'
return bundle
def dehydrate_release_image(self, bundle):
return bundle.obj.get_image_url()

34
spa/api/v1/ShowResource.py Executable file
View File

@@ -0,0 +1,34 @@
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.http import HttpBadRequest
from spa.api.v1.BaseResource import BaseResource
from spa.models import Show
from spa.models.show import ShowOverlapException
DATE_FORMAT = '%d/%m/%Y %H:%M:%S'
class ShowResource(BaseResource):
mix = fields.ToOneField('spa.api.v1.MixResource.MixResource',
'mix', null=False, full=False)
class Meta:
queryset = Show.objects.all()
authorization = Authorization()
resource_name = 'shows'
def obj_create(self, bundle, **kwargs):
try:
return super(ShowResource, self).obj_create(bundle, **kwargs)
except ShowOverlapException:
raise ImmediateHttpResponse(
HttpBadRequest("This event overlaps with an existing event")
)
except Exception, ex:
raise ImmediateHttpResponse(
HttpBadRequest(ex.message)
)

172
spa/api/v1/UserResource.py Executable file
View File

@@ -0,0 +1,172 @@
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db.models import Count, Q, F
from tastypie import fields
from tastypie.authentication import Authentication
from tastypie.authorization import Authorization
from django.conf.urls import url
from tastypie.constants import ALL, ALL_WITH_RELATIONS
from tastypie.http import HttpGone, HttpMultipleChoices
from tastypie.utils import trailing_slash
from tastypie_msgpack import Serializer
from dss import settings
from spa.api.v1.BaseResource import BaseResource
from spa.api.v1.PlaylistResource import PlaylistResource
from spa.models.basemodel import BaseModel
from spa.models.userprofile import UserProfile
from spa.models.mix import Mix
from core.tasks import update_geo_info_task
class UserResource(BaseResource):
following = fields.ToManyField(to='self', attribute='following', related_name='following', null=True)
followers = fields.ToManyField(to='self', attribute='followers', related_name='followers', null=True)
favourites = fields.ToManyField('spa.api.v1.MixResource.MixResource', 'favourites', null=True)
playlists = fields.ToManyField('spa.api.v1.PlaylistResource.PlaylistResource', 'playlists',
related_name='user', null=True, full=True)
class Meta:
queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count')
serializer = Serializer()
resource_name = 'user'
if not settings.DEBUG:
excludes = ['is_active', 'is_staff', 'is_superuser', 'password']
ordering = ['mix_count']
filtering = {
'slug': ALL,
'display_name': ALL,
'following': ALL_WITH_RELATIONS,
'followers': ALL_WITH_RELATIONS,
'favourites': ALL_WITH_RELATIONS,
'playlists': ALL_WITH_RELATIONS,
}
authorization = Authorization()
authentication = Authentication()
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<pk>\d+)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d_.-]+)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
def apply_filters(self, request, applicable_filters):
semi_filtered = super(UserResource, self).apply_filters(request, applicable_filters)
q = request.GET.get('q', None)
if q is not None:
semi_filtered = semi_filtered.filter(
Q(user__first_name__icontains=q) |
Q(user__last_name__icontains=q) |
Q(display_name__icontains=q)
)
return semi_filtered
def obj_create(self, bundle, **kwargs):
return super(UserResource, self).obj_create(bundle, **kwargs)
def obj_update(self, bundle, skip_errors=False, **kwargs):
return super(UserResource, self).obj_update(bundle, skip_errors, **kwargs)
def _create_playlist(self, request):
pass
def get_playlists(self, request, **kwargs):
if request.method == 'POST':
return self._create_playlist(request)
try:
basic_bundle = self.build_bundle(request=request)
obj = self.cached_obj_get(bundle=basic_bundle,
**self.remove_api_resource_names(kwargs))
except ObjectDoesNotExist:
return HttpGone()
child_resource = PlaylistResource()
return child_resource.get_list(request, mix=obj)
def dehydrate_description(self, bundle):
return bundle.obj.get_profile_description()
def dehydrate(self, bundle):
del bundle.data['activity_sharing_networks']
bundle.data['display_name'] = bundle.obj.get_nice_name()
bundle.data['avatar_image'] = bundle.obj.get_avatar_image()
bundle = BaseResource.dehydrate_bitfield(
bundle=bundle,
field_name='email_notifications',
object_field=bundle.obj.email_notifications,
choices=UserProfile.NOTIFICATION_CHOICES,
)
bundle = BaseResource.dehydrate_bitfield(
bundle=bundle,
field_name='activity_sharing_facebook',
object_field=bundle.obj.activity_sharing_facebook,
choices=UserProfile.NOTIFICATION_CHOICES,
)
bundle = BaseResource.dehydrate_bitfield(
bundle=bundle,
field_name='activity_sharing_twitter',
object_field=bundle.obj.activity_sharing_twitter,
choices=UserProfile.NOTIFICATION_CHOICES,
)
if bundle.obj.user.id == bundle.request.user.id:
bundle.data['email'] = bundle.obj.email
bundle.data['first_name'] = bundle.obj.first_name
bundle.data['last_name'] = bundle.obj.last_name
bundle.data['like_count'] = Mix.objects.filter(likes__user=bundle.obj).count()
bundle.data['favourite_count'] = Mix.objects.filter(favourites__user=bundle.obj).count()
# bundle.data['follower_count'] = bundle.obj.followers.count()
bundle.data['following_count'] = bundle.obj.following.count()
bundle.data['is_following'] = bundle.obj.is_follower(bundle.request.user)
bundle.data['url'] = bundle.obj.get_profile_url()
bundle.data['date_joined'] = bundle.obj.user.date_joined
bundle.data['last_login'] = bundle.obj.user.last_login
bundle.data['mix_count'] = bundle.obj.mix_count
bundle.data['thumbnail'] = bundle.obj.get_small_profile_image()
return bundle
def hydrate(self, bundle):
bundle = BaseResource.hydrate_bitfield(
bundle=bundle,
field_name='email_notifications',
object_field=UserProfile.email_notifications,
choices=UserProfile.NOTIFICATION_CHOICES,
)
bundle = BaseResource.hydrate_bitfield(
bundle=bundle,
field_name='activity_sharing_facebook',
object_field=UserProfile.activity_sharing_facebook,
choices=UserProfile.NOTIFICATION_CHOICES,
)
bundle = BaseResource.hydrate_bitfield(
bundle=bundle,
field_name='activity_sharing_twitter',
object_field=UserProfile.activity_sharing_twitter,
choices=UserProfile.NOTIFICATION_CHOICES,
)
return bundle
def get_followers(self, request, **kwargs):
try:
basic_bundle = self.build_bundle(request=request)
obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
except ObjectDoesNotExist:
return HttpGone()
except MultipleObjectsReturned:
return HttpMultipleChoices("More than one resource is found at this URI.")
child_resource = UserResource()
return child_resource.get_list(request, followers__in=obj)

1
spa/api/v1/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

16
spa/api/v1/auth.py Executable file
View File

@@ -0,0 +1,16 @@
from tastypie.authorization import Authorization
class UserOwnsRowAuthorisation(Authorization):
"""
If the user is already authenticated by a django session it will
allow the request (useful for ajax calls) .
In addition, we will check that the user owns the row being updated
or is an admin
"""
def apply_limits(self, request, object_list):
if request and hasattr(request, 'user'):
return object_list.filter(author__username=request.user.username)
return object_list.none()

1
spa/embedding/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

7
spa/embedding/urls.py Executable file
View File

@@ -0,0 +1,7 @@
from django.conf.urls import patterns, url
urlpatterns = patterns(
'',
url(r'^mix/(?P<mix_id>\d+)/$', 'spa.embedding.views.mix', name='embed_mix'),
url(r'^mix/(?P<slug>[\w\d_.-]+)/$', 'spa.embedding.views.mix', name='embed_mix_slug'),
)

34
spa/embedding/views.py Executable file
View File

@@ -0,0 +1,34 @@
from django.contrib.sites.models import Site
from django.http import Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from spa.models import Mix
def mix(request, **args):
try:
if 'mix_id' in args:
mix = Mix.objects.get(pk=args['mix_id'])
else:
mix = Mix.objects.get(slug=args['slug'])
except Mix.DoesNotExist:
raise Http404
image = mix.get_image_url('1500x1500')
audio_url = mix.get_stream_url()
mix_url = mix.get_absolute_url()
payload = {
"description": mix.description.replace('<br />', '\n'),
"title": mix.title,
"image_url": image,
"audio_url": audio_url,
"mix_url": 'http://%s%s' % (Site.objects.get_current().domain, mix_url)
}
response = render_to_response(
'inc/embed/mix.html',
payload,
context_instance=RequestContext(request)
)
response['X-XSS-Protection'] = 0
response['X-Frame-Options'] = 'IGNORE'
return response

1
spa/management/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

View File

@@ -0,0 +1,9 @@
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
pass
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,15 @@
from django.core.management.base import NoArgsCommand
import timeside
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
audio_file = '/home/fergalm/Dropbox/Private/deepsouthsounds.com/working/sample.mp3'
decoder = timeside.decoder.FileDecoder(audio_file)
grapher = timeside.grapher.Spectrogram(width=1920, height=1080)
(decoder | grapher).run()
grapher.render('d:\spectrogram.png')
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,49 @@
from django.core.management.base import NoArgsCommand
from libcloud.storage.types import Provider
from libcloud.storage.providers import get_driver
from core.utils.url import url_path_join
from dss import settings
from spa.models.mix import Mix
from datetime import datetime, timedelta
from django.db.models import Count
import os
import urlparse
from os.path import isfile, join, basename
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
cls = get_driver(Provider.AZURE_BLOBS)
driver = cls(settings.AZURE_ACCOUNT_NAME, settings.AZURE_ACCOUNT_KEY)
container = driver.get_container(container_name=settings.AZURE_CONTAINER)
#.filter(upload_date__lte=datetime.today() - timedelta(days=180)) \
mixes = Mix.objects \
.exclude(archive_path__isnull=False) \
.annotate(num_plays=Count('activity_plays')) \
.order_by('num_plays')
for mix in mixes:
if os.path.isfile(mix.get_absolute_path()):
print "Uploading file for: %s" % mix.slug
file_name = "%s.%s" % (mix.uid, mix.filetype)
archive_path = url_path_join(settings.AZURE_ITEM_BASE_URL, settings.AZURE_CONTAINER, file_name)
with open(mix.get_absolute_path(), 'rb') as iterator:
obj = driver.upload_object_via_stream(
iterator=iterator,
container=container,
object_name=file_name
)
print "Uploaded"
mix.archive_path = archive_path
mix.save()
expired_path = join(settings.MEDIA_ROOT, "mixes/archived")
new_file = os.path.join(expired_path, basename(iterator.name))
os.rename(iterator.name, new_file)
print "done- file is %s" % mix.archive_path
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,18 @@
from django.core.management.base import NoArgsCommand
from core.utils.cdn import upload_to_azure
from spa.models import Mix
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
mixes = Mix.objects.filter(archive_updated=False)
for mix in mixes:
blob_name, download_name = mix.get_cdn_details()
upload_to_azure(blob_name, download_name)
mix.archive_updated = True
mix.save()
except Exception, ex:
print "Fatal error, bailing. {0}".format(ex.message)

View File

@@ -0,0 +1,14 @@
import humanize
from django.core.management.base import NoArgsCommand
from spa.models.activity import Activity
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
activity = Activity.objects.get(pk=13437)
if activity is not None:
date = humanize.naturaltime(activity.date.replace(tzinfo=None))
print date
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,14 @@
from django.core.management.base import NoArgsCommand
from spa.models import Mix
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
#l = Mix.objects.filter(slug='dss-on-deepvibes-radio-17th-july-jamie-o-sullivan')[0]
l = Mix.objects.filter(favourites__slug='fergalmoran')[0]
for fav in l.favourites.all():
print fav.slug
pass
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,19 @@
from django.contrib.auth.models import User
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
users = User.objects.all()
for user in users:
try:
if user.get_profile() is None:
print "Invalid user: %s" % user.username
except:
print "Invalid user: %s" % user.username
user.save()
pass
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,10 @@
from django.core.management.base import NoArgsCommand
from spa.models import Mix
class Command(NoArgsCommand):
def handle(self, *args, **options):
candidates = Mix.objects.filter(waveform_generated=False)
for mix in candidates:
print "Deleting: %s" % mix.title
mix.delete()

View File

@@ -0,0 +1,30 @@
from dircache import listdir
import os
from django.core.management.base import NoArgsCommand
from os.path import isfile, join
from dss import settings
from spa.models import Mix
class Command(NoArgsCommand):
def handle(self, *args, **options):
try:
print "Starting"
mixes_path = join(settings.MEDIA_ROOT, "mixes")
expired_path = join(settings.MEDIA_ROOT, "mixes/expired")
files = [f for f in listdir(mixes_path) if isfile(join(mixes_path, f))]
for f in files:
uid = os.path.splitext(f)[0]
try:
Mix.objects.get(uid=uid)
except Mix.DoesNotExist:
new_file = os.path.join(expired_path, f)
os.rename(os.path.join(mixes_path, f), new_file)
print "Moved %s to %s" % (f, new_file)
except Exception, ex:
print "Error in file: %s" % ex.message
except Exception, ex:
print "Error: %s" % ex.message

View File

@@ -0,0 +1,18 @@
import random
from django.core.management.base import NoArgsCommand
from spa.models.comment import Comment
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
comments = Comment.objects.all()
for comment in comments:
mix = comment.mix
time_index = random.randrange(50, comment.mix.duration)
comment.time_index = time_index
comment.save()
print "Timeindex: %d Mix: %s Comment: %s" % (time_index, comment.mix.slug, comment.comment)
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,44 @@
from allauth.socialaccount.models import SocialAccount
from django.core.files.base import ContentFile
from django.core.management.base import NoArgsCommand
from requests import request, ConnectionError
from spa.models.userprofile import UserProfile
def save_image(profile, url):
try:
response = request('GET', url)
response.raise_for_status()
except ConnectionError:
pass
else:
profile.avatar_image.save(u'',
ContentFile(response.content),
save=False)
profile.save()
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
for user in UserProfile.objects.all():
try:
print "Getting image for {0}".format(user.slug)
social_account = SocialAccount.objects.get(user=user.user)
if social_account:
try:
provider_account = social_account.get_provider_account()
if provider_account:
avatar_url = provider_account.get_avatar_url()
save_image(user, avatar_url)
except Exception, ex:
print ex.message
else:
print "No account for {0}".format(user.slug)
except SocialAccount.DoesNotExist:
pass
except Exception, ex:
print "Debug exception: %s" % ex.message
except Exception, ex:
print "Debug exception: %s" % ex.message

View File

@@ -0,0 +1,31 @@
from django.core.management.base import NoArgsCommand, CommandError
from django.template.defaultfilters import slugify
from core.utils.audio import Mp3FileNotFoundException
from core.utils.audio.mp3 import mp3_length
from core.utils.url import unique_slugify
from spa.models import Mix
class Command(NoArgsCommand):
help = "Updates audio files with their durations"
def handle(self, *args, **options):
try:
candidates = Mix.objects.all()
for mix in candidates:
try:
if mix.duration is None:
print "Finding duration for: %s" % mix.title
length = mp3_length(mix.get_absolute_path())
print "\tLength: %d" % length
mix.duration = length
if mix.slug == 'Invalid':
print "Slugifying mix: %s" % mix.title
mix.slug = unique_slugify(mix, mix.title)
print "\tNew title: %s" % mix.slug
mix.save()
except Mp3FileNotFoundException, me:
mix.delete()
print me.message
except Exception, ex:
raise CommandError(ex.message)

View File

@@ -0,0 +1,48 @@
from optparse import make_option
import os
from django.core.management.base import NoArgsCommand, BaseCommand
from spa.models.mix import Mix
from core.tasks import create_waveform_task
class Command(BaseCommand):
help = "Generate all outstanding waveforms"
option_list = BaseCommand.option_list + (
make_option('--nocelery',
action='store_true',
dest='nocelery',
default=False,
help='Dispatch calls to celery broker'),
)
@staticmethod
def _get_file(mix):
#Check for file in mix directory
processed_file = ""
try:
processed_file = mix.get_absolute_path()
if not os.path.isfile(processed_file):
processed_file = mix.get_cache_path()
if not os.path.isfile(processed_file):
print "File for [%s] not found tried\n\t%s\n\t%s" % (mix.title, processed_file, processed_file)
return ""
except Exception, ex:
print "Error generating waveform: %s" % ex.message
return processed_file
def handle(self, *args, **options):
print "Scanning for missing waveforms"
unprocessed = Mix.objects.filter(waveform_generated=False)
for mix in unprocessed:
print "Found %s" % mix.slug
mix_file = self._get_file(mix)
if mix_file is not "":
if options['nocelery']:
create_waveform_task(in_file=mix_file, uid=mix.uid)
else:
create_waveform_task.delay(in_file=mix_file, uid=mix.uid)

View File

@@ -0,0 +1,75 @@
import os
from django.core.management.base import NoArgsCommand
from core.utils.waveform import generate_waveform
from dss import settings
from spa.models.mix import Mix
class Command(NoArgsCommand):
def _download_file(self, url, file_name):
import urllib2
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
file_buffer = u.read(block_sz)
if not file_buffer:
break
file_size_dl += len(file_buffer)
f.write(file_buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status += chr(8) * (len(status) + 1)
print status,
f.close()
def _convert_remote(self):
mixes = Mix.objects.exclude(waveform_version=2)
for mix in mixes:
# download audio file to temp path
print "Starting to process: %s" % mix.slug
file_name = "/tmp/%s.mp3" % mix.uid
url = mix.get_stream_url()
print "Downloading: %s To: %s" % (url, file_name)
self._download_file(url, file_name)
if not os.path.isfile(file_name):
print "File failed to download"
else:
# process waveform
generate_waveform(file_name, )
# update mix.waveform_version to 2
# delete cached file
os.remove(file_name)
print "Done %s" % mix.slug
def handle_noargs(self, **options):
try:
mixes = Mix.objects.exclude(waveform_version=2)
for mix in mixes:
from PIL import Image
import glob
output_file = '{0}/waveforms/{1}.{2}'.format(settings.MEDIA_ROOT, mix.uid, 'png')
if os.path.exists(output_file):
try:
print 'Processing: %s' % mix.slug
im = Image.open(output_file)
w, h = im.size
im.crop((0, 0, w, h / 2)).save(output_file)
except Exception:
print "Exception with image: %s" % output_file
else:
print "Skipping: %s" % mix.slug
mix.waveform_version = 2
mix.save()
pass
except Exception, ex:
print "Debug exception: %s" % ex.message

1
spa/middleware/__init__.py Executable file
View File

@@ -0,0 +1 @@
__author__ = 'fergalm'

56
spa/middleware/sqlprinter.py Executable file
View File

@@ -0,0 +1,56 @@
import os
from django.db import connection
from django.conf import settings
def terminal_width():
"""
Function to compute the terminal width.
WARNING: This is not my code, but I've been using it forever and
I don't remember where it came from.
"""
width = 0
try:
import struct, fcntl, termios
s = struct.pack('HHHH', 0, 0, 0, 0)
x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
width = struct.unpack('HHHH', x)[1]
except:
pass
if width <= 0:
try:
width = int(os.environ['COLUMNS'])
except:
pass
if width <= 0:
width = 80
return width
class SqlPrintingMiddleware(object):
"""
Middleware which prints out a list of all SQL queries done
for each view that is processed. This is only useful for debugging.
"""
def process_response(self, request, response):
if not settings.DEBUG:
return
indentation = 2
if len(connection.queries) > 0 and settings.DEBUG:
width = 10000 #terminal_width()
total_time = 0.0
for query in connection.queries:
nice_sql = query['sql'].replace('"', '').replace(',', ', ')
sql = "\033[1;31m[%s]\033[0m %s" % (query['time'], nice_sql)
total_time += float(query['time'])
while len(sql) > width - indentation:
print "%s%s" % (" " * indentation, sql[:width - indentation])
sql = sql[width - indentation:]
print "%s%s\n" % (" " * indentation, sql)
replace_tuple = (" " * indentation, str(total_time))
print "%s\033[1;32m[TOTAL TIME: %s seconds]\033[0m" % replace_tuple
return response

View File

@@ -0,0 +1,39 @@
"""
Tightens up response content by removed superflous line breaks and whitespace.
By Doug Van Horn
---- CHANGES ----
v1.1 - 31st May 2011
Cal Leeming [Simplicity Media Ltd]
Modified regex to strip leading/trailing white space from every line, not just those with blank \n.
---- TODO ----
* Ensure whitespace isn't stripped from within <pre> or <code> or <textarea> tags.
"""
import re
class StripWhitespaceMiddleware(object):
"""
Strips leading and trailing whitespace from response content.
"""
def __init__(self):
self.whitespace = re.compile('^\s*\n', re.MULTILINE)
# self.whitespace_lead = re.compile('^\s+', re.MULTILINE)
# self.whitespace_trail = re.compile('\s+$', re.MULTILINE)
def process_response(self, request, response):
if "text" in response['Content-Type']:
if hasattr(self, 'whitespace_lead'):
response.content = self.whitespace_lead.sub('', response.content)
if hasattr(self, 'whitespace_trail'):
response.content = self.whitespace_trail.sub('\n', response.content)
# Uncomment the next line to remove empty lines
if hasattr(self, 'whitespace'):
response.content = self.whitespace.sub('', response.content)
return response
else:
return response

9
spa/middleware/uploadify.py Executable file
View File

@@ -0,0 +1,9 @@
from django.conf import settings
from django.core.urlresolvers import reverse
class SWFUploadMiddleware(object):
def process_request(self, request):
if (request.method == 'POST') and\
(request.path == reverse('jfu_upload')) and\
request.POST.has_key(settings.SESSION_COOKIE_NAME):
request.COOKIES[settings.SESSION_COOKIE_NAME] = request.POST[settings.SESSION_COOKIE_NAME]

472
spa/migrations/0001_initial.py Executable file
View File

@@ -0,0 +1,472 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'UserProfile'
db.create_table('spa_userprofile', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], unique=True)),
('avatar_type', self.gf('django.db.models.fields.CharField')(default='social', max_length=15)),
('avatar_image', self.gf('django.db.models.fields.files.ImageField')(max_length=100, blank=True)),
('display_name', self.gf('django.db.models.fields.CharField')(max_length=35, blank=True)),
('description', self.gf('django.db.models.fields.CharField')(max_length=2048, blank=True)),
('slug', self.gf('django.db.models.fields.CharField')(default=None, max_length=35, null=True, blank=True)),
('activity_sharing', self.gf('django.db.models.fields.IntegerField')(default=0)),
('activity_sharing_networks', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('spa', ['UserProfile'])
# Adding model 'ChatMessage'
db.create_table('spa_chatmessage', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('message', self.gf('django.db.models.fields.TextField')()),
('timestamp', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='chat_messages', null=True, to=orm['spa.UserProfile'])),
))
db.send_create_signal('spa', ['ChatMessage'])
# Adding model '_Lookup'
db.create_table('spa__lookup', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('description', self.gf('django.db.models.fields.CharField')(max_length=100)),
))
db.send_create_signal('spa', ['_Lookup'])
# Adding model 'Recurrence'
db.create_table('spa_recurrence', (
('_lookup_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Lookup'], unique=True, primary_key=True)),
))
db.send_create_signal('spa', ['Recurrence'])
# Adding model 'Genre'
db.create_table('spa_genre', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('description', self.gf('django.db.models.fields.CharField')(max_length=100)),
('slug', self.gf('django.db.models.fields.CharField')(max_length=100, null=True)),
))
db.send_create_signal('spa', ['Genre'])
# Adding model '_Activity'
db.create_table('spa__activity', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)),
('uid', self.gf('django.db.models.fields.CharField')(max_length=50, null=True, blank=True)),
('date', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
))
db.send_create_signal('spa', ['_Activity'])
# Adding model 'MixPlay'
db.create_table('spa_mixplay', (
('_activity_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Activity'], unique=True, primary_key=True)),
('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='plays', to=orm['spa.Mix'])),
))
db.send_create_signal('spa', ['MixPlay'])
# Adding model 'MixDownload'
db.create_table('spa_mixdownload', (
('_activity_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Activity'], unique=True, primary_key=True)),
('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='downloads', to=orm['spa.Mix'])),
))
db.send_create_signal('spa', ['MixDownload'])
# Adding model 'Mix'
db.create_table('spa_mix', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
('description', self.gf('django.db.models.fields.TextField')()),
('upload_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2013, 3, 12, 0, 0))),
('mix_image', self.gf('django.db.models.fields.files.ImageField')(max_length=100, blank=True)),
('local_file', self.gf('django.db.models.fields.files.FileField')(max_length=100, blank=True)),
('download_url', self.gf('django.db.models.fields.CharField')(max_length=255)),
('stream_url', self.gf('django.db.models.fields.CharField')(max_length=255)),
('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)),
('is_featured', self.gf('django.db.models.fields.BooleanField')(default=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.UserProfile'])),
('waveform_generated', self.gf('django.db.models.fields.BooleanField')(default=False)),
('uid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=38, blank=True)),
('download_allowed', self.gf('django.db.models.fields.BooleanField')(default=False)),
))
db.send_create_signal('spa', ['Mix'])
# Adding M2M table for field genres on 'Mix'
db.create_table('spa_mix_genres', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('mix', models.ForeignKey(orm['spa.mix'], null=False)),
('genre', models.ForeignKey(orm['spa.genre'], null=False))
))
db.create_unique('spa_mix_genres', ['mix_id', 'genre_id'])
# Adding model 'Comment'
db.create_table('spa_comment', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('mix', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='comments', null=True, to=orm['spa.Mix'])),
('comment', self.gf('django.db.models.fields.CharField')(max_length=1024)),
('date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
('time_index', self.gf('django.db.models.fields.IntegerField')()),
))
db.send_create_signal('spa', ['Comment'])
# Adding model 'Venue'
db.create_table('spa_venue', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('venue_name', self.gf('django.db.models.fields.CharField')(max_length=250)),
('venue_address', self.gf('django.db.models.fields.CharField')(max_length=1024)),
('venue_image', self.gf('django.db.models.fields.files.ImageField')(max_length=100, blank=True)),
))
db.send_create_signal('spa', ['Venue'])
# Adding model 'Event'
db.create_table('spa_event', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('event_venue', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.Venue'])),
('event_date', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2013, 3, 12, 0, 0))),
('event_time', self.gf('django.db.models.fields.TimeField')(default=datetime.datetime(2013, 3, 12, 0, 0))),
('date_created', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2013, 3, 12, 0, 0))),
('event_title', self.gf('django.db.models.fields.CharField')(max_length=250)),
('event_description', self.gf('tinymce.views.HTMLField')()),
('event_recurrence', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.Recurrence'])),
))
db.send_create_signal('spa', ['Event'])
# Adding M2M table for field attendees on 'Event'
db.create_table('spa_event_attendees', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('event', models.ForeignKey(orm['spa.event'], null=False)),
('user', models.ForeignKey(orm['auth.user'], null=False))
))
db.create_unique('spa_event_attendees', ['event_id', 'user_id'])
# Adding model 'Label'
db.create_table('spa_label', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
))
db.send_create_signal('spa', ['Label'])
# Adding model 'MixLike'
db.create_table('spa_mixlike', (
('_activity_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Activity'], unique=True, primary_key=True)),
('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='likes', to=orm['spa.Mix'])),
))
db.send_create_signal('spa', ['MixLike'])
# Adding model 'MixFavourite'
db.create_table('spa_mixfavourite', (
('_activity_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Activity'], unique=True, primary_key=True)),
('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['spa.Mix'])),
))
db.send_create_signal('spa', ['MixFavourite'])
# Adding model 'Tracklist'
db.create_table('spa_tracklist', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tracklist', to=orm['spa.Mix'])),
('index', self.gf('django.db.models.fields.SmallIntegerField')()),
('timeindex', self.gf('django.db.models.fields.TimeField')(null=True)),
('description', self.gf('django.db.models.fields.CharField')(max_length=255)),
('artist', self.gf('django.db.models.fields.CharField')(max_length=255)),
('title', self.gf('django.db.models.fields.CharField')(max_length=255)),
('remixer', self.gf('django.db.models.fields.CharField')(max_length=255)),
('label', self.gf('django.db.models.fields.CharField')(max_length=255)),
))
db.send_create_signal('spa', ['Tracklist'])
# Adding model 'PurchaseLink'
db.create_table('spa_purchaselink', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('track', self.gf('django.db.models.fields.related.ForeignKey')(related_name='purchase_link', to=orm['spa.Tracklist'])),
('url', self.gf('django.db.models.fields.URLField')(max_length=200)),
('provider', self.gf('django.db.models.fields.CharField')(max_length=255)),
))
db.send_create_signal('spa', ['PurchaseLink'])
# Adding model 'Release'
db.create_table('spa_release', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('release_artist', self.gf('django.db.models.fields.CharField')(max_length=100)),
('release_title', self.gf('django.db.models.fields.CharField')(max_length=100)),
('release_description', self.gf('django.db.models.fields.TextField')()),
('release_image', self.gf('django.db.models.fields.files.ImageField')(max_length=100, blank=True)),
('release_label', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.Label'])),
('release_date', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2013, 3, 12, 0, 0))),
('embed_code', self.gf('django.db.models.fields.TextField')(blank=True)),
('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.UserProfile'])),
))
db.send_create_signal('spa', ['Release'])
# Adding model 'ReleaseAudio'
db.create_table('spa_releaseaudio', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('local_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
('release', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='release_audio', null=True, to=orm['spa.Release'])),
('description', self.gf('django.db.models.fields.TextField')()),
))
db.send_create_signal('spa', ['ReleaseAudio'])
def backwards(self, orm):
# Deleting model 'UserProfile'
db.delete_table('spa_userprofile')
# Deleting model 'ChatMessage'
db.delete_table('spa_chatmessage')
# Deleting model '_Lookup'
db.delete_table('spa__lookup')
# Deleting model 'Recurrence'
db.delete_table('spa_recurrence')
# Deleting model 'Genre'
db.delete_table('spa_genre')
# Deleting model '_Activity'
db.delete_table('spa__activity')
# Deleting model 'MixPlay'
db.delete_table('spa_mixplay')
# Deleting model 'MixDownload'
db.delete_table('spa_mixdownload')
# Deleting model 'Mix'
db.delete_table('spa_mix')
# Removing M2M table for field genres on 'Mix'
db.delete_table('spa_mix_genres')
# Deleting model 'Comment'
db.delete_table('spa_comment')
# Deleting model 'Venue'
db.delete_table('spa_venue')
# Deleting model 'Event'
db.delete_table('spa_event')
# Removing M2M table for field attendees on 'Event'
db.delete_table('spa_event_attendees')
# Deleting model 'Label'
db.delete_table('spa_label')
# Deleting model 'MixLike'
db.delete_table('spa_mixlike')
# Deleting model 'MixFavourite'
db.delete_table('spa_mixfavourite')
# Deleting model 'Tracklist'
db.delete_table('spa_tracklist')
# Deleting model 'PurchaseLink'
db.delete_table('spa_purchaselink')
# Deleting model 'Release'
db.delete_table('spa_release')
# Deleting model 'ReleaseAudio'
db.delete_table('spa_releaseaudio')
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'})
},
'spa._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
},
'spa._lookup': {
'Meta': {'object_name': '_Lookup'},
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'spa.genre': {
'Meta': {'object_name': 'Genre'},
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
},
'spa.label': {
'Meta': {'object_name': 'Label'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']},
'_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_ormbases': ['spa._Activity']},
'_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']},
'_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']},
'_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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']},
'_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'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 3, 12, 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', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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'}),
'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']"}),
'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': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '35', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'spa.venue': {
'Meta': {'object_name': 'Venue'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "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']

View File

@@ -0,0 +1,222 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'UserFollows'
db.create_table('spa_userfollows', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user_from', self.gf('django.db.models.fields.related.OneToOneField')(related_name='followers', unique=True, to=orm['spa.UserProfile'])),
('user_to', self.gf('django.db.models.fields.related.OneToOneField')(related_name='following', unique=True, to=orm['spa.UserProfile'])),
))
db.send_create_signal('spa', ['UserFollows'])
def backwards(self, orm):
# Deleting model 'UserFollows'
db.delete_table('spa_userfollows')
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'})
},
'spa._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
},
'spa._lookup': {
'Meta': {'object_name': '_Lookup'},
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'spa.genre': {
'Meta': {'object_name': 'Genre'},
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
},
'spa.label': {
'Meta': {'object_name': 'Label'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 3, 12, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']},
'_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_ormbases': ['spa._Activity']},
'_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']},
'_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']},
'_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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']},
'_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'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 3, 12, 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', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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'}),
'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']"}),
'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.userfollows': {
'Meta': {'object_name': 'UserFollows'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user_from': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'followers'", 'unique': 'True', 'to': "orm['spa.UserProfile']"}),
'user_to': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'following'", 'unique': 'True', 'to': "orm['spa.UserProfile']"})
},
'spa.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '35', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'spa.venue': {
'Meta': {'object_name': 'Venue'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "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']

View File

@@ -0,0 +1,220 @@
# -*- coding: 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 'Mix.duration'
db.add_column(u'spa_mix', 'duration',
self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Mix.duration'
db.delete_column(u'spa_mix', 'duration')
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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'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._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'})
},
'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'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 19, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 19, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 4, 19, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 4, 19, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 19, 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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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']"}),
'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.userfollows': {
'Meta': {'object_name': 'UserFollows'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user_from': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'followers'", 'unique': 'True', 'to': "orm['spa.UserProfile']"}),
'user_to': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'following'", 'unique': 'True', 'to': "orm['spa.UserProfile']"})
},
'spa.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '35', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
'spa.venue': {
'Meta': {'object_name': 'Venue'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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']

View File

@@ -0,0 +1,221 @@
# -*- coding: 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 'Mix.slug'
db.add_column(u'spa_mix', 'slug',
self.gf('django.db.models.fields.SlugField')(default='Invalid', max_length=50),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Mix.slug'
db.delete_column(u'spa_mix', 'slug')
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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'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._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'})
},
'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'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 23, 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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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']"}),
'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.userfollows': {
'Meta': {'object_name': 'UserFollows'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user_from': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'followers'", 'unique': 'True', 'to': "orm['spa.UserProfile']"}),
'user_to': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'following'", 'unique': 'True', 'to': "orm['spa.UserProfile']"})
},
'spa.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '35', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
'spa.venue': {
'Meta': {'object_name': 'Venue'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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']

View File

@@ -0,0 +1,225 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Changing field 'UserProfile.slug'
db.alter_column(u'spa_userprofile', 'slug', self.gf('django.db.models.fields.SlugField')(max_length=50, null=True))
# Adding index on 'UserProfile', fields ['slug']
db.create_index(u'spa_userprofile', ['slug'])
def backwards(self, orm):
# Removing index on 'UserProfile', fields ['slug']
db.delete_index(u'spa_userprofile', ['slug'])
# Changing field 'UserProfile.slug'
db.alter_column(u'spa_userprofile', 'slug', self.gf('django.db.models.fields.CharField')(max_length=35, 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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'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._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'})
},
'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'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 4, 23, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 23, 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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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']"}),
'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.userfollows': {
'Meta': {'object_name': 'UserFollows'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user_from': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'followers'", 'unique': 'True', 'to': "orm['spa.UserProfile']"}),
'user_to': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'following'", 'unique': 'True', 'to': "orm['spa.UserProfile']"})
},
'spa.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
'spa.venue': {
'Meta': {'object_name': 'Venue'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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']

View File

@@ -0,0 +1,219 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Changing field 'Mix.title'
db.alter_column(u'spa_mix', 'title', self.gf('django.db.models.fields.CharField')(max_length=150))
def backwards(self, orm):
# Changing field 'Mix.title'
db.alter_column(u'spa_mix', 'title', self.gf('django.db.models.fields.CharField')(max_length=50))
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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'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._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'})
},
'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'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'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', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 24, 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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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']"}),
'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.userfollows': {
'Meta': {'object_name': 'UserFollows'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user_from': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'followers'", 'unique': 'True', 'to': "orm['spa.UserProfile']"}),
'user_to': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'following'", 'unique': 'True', 'to': "orm['spa.UserProfile']"})
},
'spa.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
'spa.venue': {
'Meta': {'object_name': 'Venue'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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']

View File

@@ -0,0 +1,219 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Changing field 'UserProfile.user'
db.alter_column(u'spa_userprofile', 'user_id', self.gf('django.db.models.fields.related.OneToOneField')(unique=True, to=orm['auth.User']))
def backwards(self, orm):
# Changing field 'UserProfile.user'
db.alter_column(u'spa_userprofile', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], unique=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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'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._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'})
},
'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'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 4, 24, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 24, 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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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']"}),
'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.userfollows': {
'Meta': {'object_name': 'UserFollows'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user_from': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'followers'", 'unique': 'True', 'to': "orm['spa.UserProfile']"}),
'user_to': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'following'", 'unique': 'True', 'to': "orm['spa.UserProfile']"})
},
'spa.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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']

View File

@@ -0,0 +1,224 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting model 'UserFollows'
db.delete_table(u'spa_userfollows')
# Changing field 'Mix.title'
db.alter_column(u'spa_mix', 'title', self.gf('django.db.models.fields.CharField')(max_length=150))
def backwards(self, orm):
# Adding model 'UserFollows'
db.create_table(u'spa_userfollows', (
('user_to', self.gf('django.db.models.fields.related.OneToOneField')(related_name='following', unique=True, to=orm['spa.UserProfile'])),
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user_from', self.gf('django.db.models.fields.related.OneToOneField')(related_name='followers', unique=True, to=orm['spa.UserProfile'])),
))
db.send_create_signal('spa', ['UserFollows'])
# Changing field 'Mix.title'
db.alter_column(u'spa_mix', 'title', self.gf('django.db.models.fields.CharField')(max_length=50))
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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'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._activity': {
'Meta': {'object_name': '_Activity'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'})
},
'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'})
},
'spa.chatmessage': {
'Meta': {'object_name': 'ChatMessage'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'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': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
'time_index': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
'spa.event': {
'Meta': {'object_name': 'Event'},
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 30, 0, 0)'}),
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 30, 0, 0)'}),
'event_description': ('tinymce.views.HTMLField', [], {}),
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 4, 30, 0, 0)'}),
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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'})
},
'spa.mix': {
'Meta': {'object_name': 'Mix'},
'description': ('django.db.models.fields.TextField', [], {}),
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'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', [], {'default': 'datetime.datetime(2013, 4, 30, 0, 0)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}),
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'spa.mixdownload': {
'Meta': {'object_name': 'MixDownload', '_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': "'downloads'", 'to': "orm['spa.Mix']"})
},
'spa.mixfavourite': {
'Meta': {'object_name': 'MixFavourite', '_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': "'favourites'", 'to': "orm['spa.Mix']"})
},
'spa.mixlike': {
'Meta': {'object_name': 'MixLike', '_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': "'likes'", 'to': "orm['spa.Mix']"})
},
'spa.mixplay': {
'Meta': {'object_name': 'MixPlay', '_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': "'plays'", 'to': "orm['spa.Mix']"})
},
'spa.purchaselink': {
'Meta': {'object_name': 'PurchaseLink'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 4, 30, 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'}),
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'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']"}),
'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': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}),
'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']

Some files were not shown because too many files have changed in this diff Show More