mirror of
https://github.com/fergalmoran/dss.api.git
synced 2025-12-25 18:58:19 +00:00
Merge branch 'master' into develop
This commit is contained in:
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
FROM python:2.7
|
||||
ENV PYTHONBUFFERED 1
|
||||
|
||||
RUN mkdir /code
|
||||
RUN mkdir /srv/logs
|
||||
RUN mkdir /files
|
||||
RUN mkdir /files/static
|
||||
RUN mkdir /files/media
|
||||
RUN mkdir /files/cache
|
||||
RUN mkdir /files/cache/mixes
|
||||
RUN mkdir /files/cache/waveforms
|
||||
RUN mkdir /files/tmp
|
||||
|
||||
WORKDIR /code
|
||||
ADD requirements.txt /code/
|
||||
RUN pip install -r requirements.txt
|
||||
RUN apt-get update && apt-get install -y sox lame vim \
|
||||
libboost-program-options-dev libsox-fmt-mp3 postgresql-client
|
||||
|
||||
ADD . /code/
|
||||
|
||||
RUN adduser --disabled-password --gecos '' djworker
|
||||
RUN chown djworker /files -R
|
||||
RUN chown djworker /srv/logs -R
|
||||
RUN export PATH=$PATH:/mnt/bin/
|
||||
13
api/auth.py
13
api/auth.py
@@ -1,5 +1,6 @@
|
||||
from calendar import timegm
|
||||
import datetime
|
||||
import logging
|
||||
from rest_framework import permissions
|
||||
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
||||
from rest_framework.response import Response
|
||||
@@ -15,11 +16,9 @@ from rest_framework import parsers
|
||||
from social.apps.django_app.utils import psa
|
||||
from dss import settings
|
||||
|
||||
|
||||
logger = logging.getLogger('spa')
|
||||
@psa()
|
||||
def auth_by_token(request, backend):
|
||||
token = request.data.get('access_token')
|
||||
user = request.user
|
||||
user = request.backend.do_auth(
|
||||
access_token=request.data.get('access_token')
|
||||
)
|
||||
@@ -27,7 +26,7 @@ def auth_by_token(request, backend):
|
||||
return user if user else None
|
||||
|
||||
|
||||
class FacebookView(APIView):
|
||||
class SocialLoginHandler(APIView):
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
|
||||
def post(self, request, format=None):
|
||||
@@ -38,9 +37,10 @@ class FacebookView(APIView):
|
||||
try:
|
||||
user = auth_by_token(request, backend)
|
||||
except Exception, e:
|
||||
logger.exception(e)
|
||||
return Response({
|
||||
'status': 'Bad request',
|
||||
'message': 'Could not authenticate with the provided token' if settings.DEBUG else e.message
|
||||
'message': e.message
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
if user:
|
||||
@@ -57,7 +57,8 @@ class FacebookView(APIView):
|
||||
)
|
||||
|
||||
response_data = {
|
||||
'token': jwt_encode_handler(payload)
|
||||
'token': jwt_encode_handler(payload),
|
||||
'session': user.userprofile.get_session_id()
|
||||
}
|
||||
|
||||
return Response(response_data)
|
||||
|
||||
@@ -22,9 +22,16 @@ class ChatHelper(ActivityHelper):
|
||||
# do some persistence stuff with the chat
|
||||
from core.realtime import chat
|
||||
|
||||
user = self.get_session(request)
|
||||
#user = self.get_session(request)
|
||||
u = request.user
|
||||
if not u.is_anonymous():
|
||||
image = u.userprofile.get_sized_avatar_image(32, 32)
|
||||
user = u.userprofile.get_nice_name()
|
||||
else:
|
||||
image = settings.DEFAULT_USER_IMAGE
|
||||
user = settings.DEFAULT_USER_NAME
|
||||
|
||||
chat.post_chat(request.data['user'], request.data['message'])
|
||||
chat.post_chat(request.data['user'], image, user, request.data['message'])
|
||||
return Response(request.data['message'], HTTP_201_CREATED)
|
||||
|
||||
|
||||
|
||||
@@ -449,9 +449,11 @@ class ActivitySerializer(serializers.HyperlinkedModelSerializer):
|
||||
|
||||
|
||||
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')
|
||||
from_user = InlineUserProfileSerializer(source='get_from_user', read_only=True)
|
||||
notification_url = serializers.ReadOnlyField()
|
||||
verb = serializers.ReadOnlyField()
|
||||
target = serializers.ReadOnlyField()
|
||||
date = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = Notification
|
||||
@@ -459,10 +461,12 @@ class NotificationSerializer(serializers.HyperlinkedModelSerializer):
|
||||
'id',
|
||||
'notification_url',
|
||||
'from_user',
|
||||
'display_name',
|
||||
'avatar_image',
|
||||
'verb',
|
||||
'target',
|
||||
'target_desc',
|
||||
'type',
|
||||
'date',
|
||||
'accepted_date',
|
||||
)
|
||||
|
||||
def get_display_name(self, obj):
|
||||
|
||||
36
api/urls.py
36
api/urls.py
@@ -1,21 +1,44 @@
|
||||
from django.conf.urls import patterns, url, include
|
||||
from rest_framework import permissions
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
||||
|
||||
from api import views, auth, helpers
|
||||
from api.auth import FacebookView
|
||||
from api.auth import SocialLoginHandler
|
||||
from rest_framework.views import status
|
||||
from rest_framework.response import Response
|
||||
from core.realtime import activity
|
||||
|
||||
router = DefaultRouter() # trailing_slash=True)
|
||||
|
||||
router.register(r'user', views.UserProfileViewSet)
|
||||
router.register(r'mix', views.MixViewSet)
|
||||
|
||||
|
||||
router.register(r'notification', views.NotificationViewSet)
|
||||
router.register(r'hitlist', views.HitlistViewSet)
|
||||
router.register(r'comments', views.CommentViewSet)
|
||||
router.register(r'activity', views.ActivityViewSet, base_name='activity')
|
||||
router.register(r'genre', views.GenreViewSet, base_name='genre')
|
||||
|
||||
|
||||
class DebugView(APIView):
|
||||
permission_classes = (IsAuthenticated, )
|
||||
authentication_classes = (JSONWebTokenAuthentication, )
|
||||
|
||||
def post(self, request, format=None):
|
||||
try:
|
||||
activity.post_activity('user:message', request.user.userprofile.get_session_id(), 'Hello Sailor')
|
||||
except Exception, ex:
|
||||
print ex.message
|
||||
|
||||
return Response({
|
||||
'status': request.user.first_name,
|
||||
'message': 'Sailor'
|
||||
}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^', include(router.urls)),
|
||||
@@ -26,17 +49,18 @@ urlpatterns = patterns(
|
||||
url(r'_search/$', views.SearchResultsView.as_view()),
|
||||
url(r'^', include(router.urls)),
|
||||
|
||||
#url(r'^login/', auth.ObtainAuthToken.as_view()),
|
||||
#url(r'^logout/', auth.ObtainLogout.as_view()),
|
||||
url(r'^_login/', SocialLoginHandler.as_view()),
|
||||
url(r'^token-refresh/', 'rest_framework_jwt.views.refresh_jwt_token'),
|
||||
|
||||
# url(r'^_tr/', RefreshToken.as_view()),
|
||||
url(r'^__u/checkslug', helpers.UserSlugCheckHelper.as_view()),
|
||||
url(r'^__u/', auth.ObtainUser.as_view()),
|
||||
|
||||
|
||||
url(r'^_act/play', helpers.ActivityPlayHelper.as_view()),
|
||||
url(r'^_chat/', helpers.ChatHelper.as_view()),
|
||||
url(r'^_login/', FacebookView.as_view()),
|
||||
|
||||
|
||||
url(r'^__debug/', DebugView.as_view()),
|
||||
|
||||
url('', include('social.apps.django_app.urls', namespace='social')),
|
||||
)
|
||||
|
||||
50
api/views.py
50
api/views.py
@@ -17,9 +17,8 @@ from rest_framework.status import HTTP_202_ACCEPTED, HTTP_401_UNAUTHORIZED, HTTP
|
||||
HTTP_200_OK, HTTP_204_NO_CONTENT
|
||||
|
||||
from api import serializers
|
||||
from core.utils.cdn import upload_to_azure
|
||||
from dss import settings
|
||||
from core.tasks import create_waveform_task, archive_mix_task
|
||||
from spa import tasks
|
||||
from spa.models.genre import Genre
|
||||
from spa.models.activity import ActivityPlay
|
||||
from spa.models.mix import Mix
|
||||
@@ -27,7 +26,7 @@ from spa.models.comment import Comment
|
||||
from spa.models.notification import Notification
|
||||
from spa.models.userprofile import UserProfile
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logging.getLogger('spa')
|
||||
|
||||
|
||||
class AnonymousWriteUserDelete(BasePermission):
|
||||
@@ -121,10 +120,10 @@ class AttachedImageUploadView(views.APIView):
|
||||
parser_classes = (FileUploadParser,)
|
||||
|
||||
def post(self, request):
|
||||
if request.FILES['file'] is None or request.data.get('data') is None:
|
||||
if request.data['file'] is None or request.data.get('data') is None:
|
||||
return Response(status=HTTP_400_BAD_REQUEST)
|
||||
|
||||
file_obj = request.FILES['file']
|
||||
file_obj = request.data['file']
|
||||
file_hash = request.data.get('data')
|
||||
try:
|
||||
mix = Mix.objects.get(uid=file_hash)
|
||||
@@ -134,6 +133,8 @@ class AttachedImageUploadView(views.APIView):
|
||||
return Response(HTTP_202_ACCEPTED)
|
||||
except ObjectDoesNotExist:
|
||||
return Response(status=HTTP_404_NOT_FOUND)
|
||||
except Exception, ex:
|
||||
logger.exception(ex)
|
||||
|
||||
return Response(status=HTTP_401_UNAUTHORIZED)
|
||||
|
||||
@@ -161,26 +162,43 @@ class PartialMixUploadView(views.APIView):
|
||||
# noinspection PyBroadException
|
||||
def post(self, request):
|
||||
try:
|
||||
logger.info("Received post file")
|
||||
uid = request.META.get('HTTP_UPLOAD_HASH')
|
||||
in_file = request.FILES['file'] if request.FILES else None
|
||||
in_file = request.data['file'] if request.data else None
|
||||
file_name, extension = os.path.splitext(in_file.name)
|
||||
|
||||
logger.info("Constructing storage")
|
||||
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'
|
||||
|
||||
logger.info("Storage constructed")
|
||||
|
||||
try:
|
||||
logger.debug("Received input file")
|
||||
logger.debug("Storage is {0}".format(file_storage.base_location))
|
||||
input_file = os.path.join(file_storage.base_location, cache_file)
|
||||
|
||||
# Chain the waveform & archive tasks together
|
||||
# Probably not the best place for them but will do for now
|
||||
# First argument to archive_mix_task is not specified as it is piped from create_waveform_task
|
||||
(create_waveform_task.s(input_file, uid) |
|
||||
archive_mix_task.s(filetype='mp3', uid=uid)).delay()
|
||||
# First argument to upload_to_cdn_task is not specified as it is piped from create_waveform_task
|
||||
|
||||
except Exception:
|
||||
logger.debug("Processing input_file: {0}".format(input_file))
|
||||
logger.debug("Connecting to broker: {0}".format(settings.BROKER_URL))
|
||||
|
||||
from celery import group, chain
|
||||
(
|
||||
tasks.create_waveform_task.s(input_file, uid) |
|
||||
tasks.upload_to_cdn_task.subtask(('mp3', uid, 'mixes'), immutable=True) |
|
||||
tasks.upload_to_cdn_task.subtask(('png', uid, 'waveforms'), immutable=True) |
|
||||
tasks.notify_subscriber.subtask((request.user.userprofile.get_session_id(), uid), immutable=True)
|
||||
).delay()
|
||||
logger.debug("Waveform task started")
|
||||
|
||||
except Exception, ex:
|
||||
logger.exception(ex)
|
||||
response = \
|
||||
'Unable to connect to waveform generation task, there may be a delay in getting your mix online'
|
||||
'Unable to connect to rabbitmq, there may be a delay in getting your mix online'
|
||||
|
||||
file_dict = {
|
||||
'response': response,
|
||||
@@ -209,12 +227,13 @@ class ActivityViewSet(viewsets.ModelViewSet):
|
||||
|
||||
ret = ActivityPlay.objects.filter(mix__user=user).order_by("-id")
|
||||
|
||||
if len(ret) >0:
|
||||
logger.debug("Activity returned: %s".format(ret[0].get_object_slug()))
|
||||
if len(ret) > 0:
|
||||
logger.debug("Activity returned: {0}".format(ret[0].get_object_slug()))
|
||||
return ret
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
class DownloadItemView(views.APIView):
|
||||
def get(self, request, *args, **kwargs):
|
||||
try:
|
||||
@@ -234,7 +253,10 @@ class NotificationViewSet(viewsets.ModelViewSet):
|
||||
if not user.is_authenticated():
|
||||
raise PermissionDenied("Not allowed")
|
||||
|
||||
return Notification.objects.filter(to_user=user).order_by('-date')[0:5]
|
||||
return Notification.objects.filter(to_user=user).order_by('-date')
|
||||
|
||||
def perform_update(self, serializer):
|
||||
return super(NotificationViewSet, self).perform_update(serializer)
|
||||
|
||||
|
||||
class GenreViewSet(viewsets.ModelViewSet):
|
||||
|
||||
BIN
bin/wav2png
Executable file
BIN
bin/wav2png
Executable file
Binary file not shown.
@@ -1,9 +1,10 @@
|
||||
import redis
|
||||
import json
|
||||
from dss import settings
|
||||
|
||||
|
||||
def post_activity(channel, session, message):
|
||||
r = redis.StrictRedis(host='localhost', port=6379, db=0)
|
||||
r = redis.StrictRedis(host=settings.REDIS_HOST, port=6379, db=0)
|
||||
response = r.publish(channel, json.dumps({'session': session, 'message': message}))
|
||||
print "Message sent: {0}".format(response)
|
||||
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
import json
|
||||
import datetime
|
||||
import redis
|
||||
from dss import settings
|
||||
|
||||
|
||||
def post_chat(session, message):
|
||||
r = redis.StrictRedis(host='localhost', port=6379, db=0)
|
||||
response = r.publish('chat', json.dumps({'session': session, 'message': message}))
|
||||
def post_chat(session, image, user, message):
|
||||
r = redis.StrictRedis(host=settings.REDIS_HOST, port=6379, db=0)
|
||||
payload = json.dumps({
|
||||
'session': session,
|
||||
'message': message,
|
||||
'user': user,
|
||||
'image': image,
|
||||
'date': datetime.datetime.now().isoformat()
|
||||
})
|
||||
response = r.publish('chat', payload)
|
||||
print "Message sent: {0}".format(response)
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import shutil
|
||||
from celery.task import task
|
||||
import os
|
||||
from core.utils.cdn import upload_to_azure
|
||||
from spa.signals import waveform_generated_signal
|
||||
|
||||
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
|
||||
waveform_generated_signal.send(sender=None, uid=uid)
|
||||
return new_file
|
||||
else:
|
||||
print "Outfile is missing"
|
||||
|
||||
|
||||
@task(time_limit=3600)
|
||||
def archive_mix_task(in_file, filetype, uid):
|
||||
print "Sending {0} to azure".format(uid)
|
||||
try:
|
||||
upload_to_azure(in_file, filetype, uid)
|
||||
except Exception, ex:
|
||||
print "Unable to upload: %s".format(ex.message)
|
||||
|
||||
@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,41 +1,43 @@
|
||||
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
|
||||
|
||||
from dss import settings
|
||||
from dss.storagesettings import AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY, AZURE_CONTAINER
|
||||
|
||||
def upload_to_azure(in_file, filetype, uid):
|
||||
|
||||
def upload_file_to_azure(in_file, file_name, container_name=settings.AZURE_CONTAINER):
|
||||
if os.path.isfile(in_file):
|
||||
print "Uploading file for: %s" % in_file
|
||||
file_name = "%s.%s" % (uid, filetype)
|
||||
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 upload_stream_to_azure(iterator, file_name, container_name=container_name)
|
||||
else:
|
||||
print "infile not found"
|
||||
return None
|
||||
|
||||
|
||||
def set_azure_details(blob_name, download_name):
|
||||
def upload_stream_to_azure(iterator, file_name, container_name=settings.AZURE_CONTAINER):
|
||||
cls = get_driver(Provider.AZURE_BLOBS)
|
||||
driver = cls(settings.AZURE_ACCOUNT_NAME, settings.AZURE_ACCOUNT_KEY)
|
||||
container = driver.get_container(container_name)
|
||||
obj = driver.upload_object_via_stream(
|
||||
iterator=iterator,
|
||||
container=container,
|
||||
object_name=file_name
|
||||
)
|
||||
return obj
|
||||
|
||||
|
||||
def set_azure_details(blob_name, download_name, container_name=AZURE_CONTAINER):
|
||||
try:
|
||||
blob_service = BlobService(AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY)
|
||||
blob = blob_service.get_blob(AZURE_CONTAINER, blob_name)
|
||||
blob = blob_service.get_blob(container_name, blob_name)
|
||||
if blob:
|
||||
blob_service.set_blob_properties(
|
||||
AZURE_CONTAINER,
|
||||
container_name,
|
||||
blob_name,
|
||||
x_ms_blob_content_type='application/octet-stream',
|
||||
x_ms_blob_content_disposition='attachment;filename="{0}"'.format(download_name)
|
||||
@@ -47,3 +49,29 @@ def set_azure_details(blob_name, download_name):
|
||||
print "No blob found for: %s" % download_name
|
||||
except Exception, ex:
|
||||
print "Error processing blob %s: %s" % (download_name, ex.message)
|
||||
|
||||
|
||||
def file_exists(url):
|
||||
import httplib
|
||||
from urlparse import urlparse
|
||||
p = urlparse(url)
|
||||
c = httplib.HTTPConnection(p.netloc)
|
||||
c.request("HEAD", p.path)
|
||||
|
||||
r = c.getresponse()
|
||||
return r.status == 200
|
||||
|
||||
|
||||
def enumerate_objects(container):
|
||||
blob_service = BlobService(AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY)
|
||||
blobs = blob_service.list_blobs(container)
|
||||
items = []
|
||||
for blob in blobs:
|
||||
items.append(blob.name)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def delete_object(container, name):
|
||||
blob_service = BlobService(AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY)
|
||||
blob_service.delete_blob(container, name)
|
||||
@@ -5,19 +5,21 @@ 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), '')
|
||||
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
|
||||
# remove double slashes
|
||||
ret = urlparse.urljoin(url, urlparse.urlparse(url).path.replace('//', '/'))
|
||||
return ret
|
||||
|
||||
@@ -90,11 +92,13 @@ def _slug_strip(value, 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
|
||||
return url
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
from __future__ import absolute_import
|
||||
from .celeryconf import app as celery_app
|
||||
|
||||
19
dss/celeryconf.py
Normal file
19
dss/celeryconf.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import logging
|
||||
|
||||
from celery import Celery
|
||||
|
||||
logger = logging.getLogger('dss')
|
||||
|
||||
# set the default Django settings module for the 'celery' program.
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dss.settings')
|
||||
|
||||
from django.conf import settings
|
||||
app = Celery('dss')
|
||||
|
||||
# Using a string here means the worker will not have to
|
||||
# pickle the object when using Windows.
|
||||
app.config_from_object('django.conf:settings')
|
||||
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
from dss import localsettings
|
||||
|
||||
if os.name == 'posix':
|
||||
@@ -20,11 +21,14 @@ LOGGING = {
|
||||
},
|
||||
'handlers': {
|
||||
'file': {
|
||||
'level': 'DEBUG',
|
||||
'level': 'INFO',
|
||||
'class': 'logging.FileHandler',
|
||||
'filename': LOG_FILE,
|
||||
'formatter': 'verbose'
|
||||
},
|
||||
}, 'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'stream': sys.stdout,
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
@@ -33,7 +37,7 @@ LOGGING = {
|
||||
'level': 'DEBUG',
|
||||
},
|
||||
'spa': {
|
||||
'handlers': ['file'],
|
||||
'handlers': ['file', 'console'],
|
||||
'level': 'DEBUG',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# e Django settings for dss project.
|
||||
import os
|
||||
import mimetypes
|
||||
from datetime import timedelta
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
import djcelery
|
||||
from django.conf import global_settings
|
||||
|
||||
from utils import here
|
||||
@@ -29,7 +29,6 @@ DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': DATABASE_NAME,
|
||||
'ADMINUSER': 'postgres',
|
||||
'USER': DATABASE_USER,
|
||||
'PASSWORD': DATABASE_PASSWORD,
|
||||
'HOST': DATABASE_HOST,
|
||||
@@ -38,7 +37,6 @@ DATABASES = {
|
||||
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'
|
||||
@@ -70,19 +68,13 @@ TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
|
||||
'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.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
@@ -104,7 +96,7 @@ INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'user_sessions',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
@@ -112,17 +104,16 @@ INSTALLED_APPS = (
|
||||
#'django_facebook',
|
||||
'django_extensions',
|
||||
'django_gravatar',
|
||||
'djcelery',
|
||||
'corsheaders',
|
||||
'sorl.thumbnail',
|
||||
'djcelery',
|
||||
'spa',
|
||||
'tinymce',
|
||||
'gunicorn',
|
||||
'spa.signals',
|
||||
'core',
|
||||
#'schedule',
|
||||
'django_user_agents',
|
||||
|
||||
'storages',
|
||||
'social.apps.django_app.default',
|
||||
|
||||
# TODO: remove
|
||||
@@ -138,7 +129,6 @@ INSTALLED_APPS = (
|
||||
'djrill',
|
||||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
'rest_framework_swagger',
|
||||
)
|
||||
|
||||
# where to redirect users to after logging in
|
||||
@@ -147,7 +137,6 @@ LOGOUT_URL = reverse_lazy('home')
|
||||
|
||||
FACEBOOK_APP_ID = '154504534677009'
|
||||
|
||||
djcelery.setup_loader()
|
||||
|
||||
AVATAR_STORAGE_DIR = MEDIA_ROOT + '/avatars/'
|
||||
ACCOUNT_LOGOUT_REDIRECT_URL = '/'
|
||||
@@ -160,7 +149,7 @@ TASTYPIE_ALLOW_MISSING_SLASH = True
|
||||
SENDFILE_ROOT = os.path.join(MEDIA_ROOT, 'mixes')
|
||||
SENDFILE_URL = '/media/mixes'
|
||||
|
||||
SESSION_ENGINE = 'user_sessions.backends.db'
|
||||
#SESSION_ENGINE = 'user_sessions.backends.db'
|
||||
|
||||
mimetypes.add_type("text/xml", ".plist", False)
|
||||
|
||||
@@ -216,4 +205,12 @@ DEFAULT_USER_NAME = 'Anonymouse'
|
||||
DEFAULT_USER_TITLE = 'Just another DSS lover'
|
||||
|
||||
SITE_NAME = 'Deep South Sounds'
|
||||
THUMBNAIL_PREFIX = 'cache/_tn/'
|
||||
THUMBNAIL_PREFIX = '_tn/'
|
||||
|
||||
# THUMBNAIL_STORAGE = 'storages.backends.azure_storage.AzureStorage'
|
||||
|
||||
JWT_AUTH = {
|
||||
'JWT_EXPIRATION_DELTA': timedelta(seconds=900),
|
||||
'JWT_ALLOW_REFRESH': True,
|
||||
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=30),
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ 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')),
|
||||
(r'^social/', include('spa.social.urls')),
|
||||
(r'^arges/', include('spa.social.urls')),
|
||||
url(r'', include('user_sessions.urls', 'user_sessions')),
|
||||
url(r'^', include('api.urls')),
|
||||
)
|
||||
handler500 = 'spa.views.debug_500'
|
||||
|
||||
if settings.DEBUG:
|
||||
from django.views.static import serve
|
||||
|
||||
22
dss/wsgi.py
22
dss/wsgi.py
@@ -1,28 +1,6 @@
|
||||
"""
|
||||
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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Django>=1.6,<1.7
|
||||
Django==1.6.11
|
||||
django-extensions
|
||||
django-sendfile
|
||||
Werkzeug
|
||||
@@ -9,14 +9,15 @@ django-dirtyfields
|
||||
django-storages
|
||||
django-user-sessions
|
||||
django-cors-headers
|
||||
django-rest-swagger
|
||||
six==1.6.0
|
||||
django-filter
|
||||
django-grappelli
|
||||
django-grappelli==2.5.7
|
||||
django-model_utils
|
||||
django-dbbackup
|
||||
django-user-agents
|
||||
south
|
||||
redis
|
||||
django-celery
|
||||
|
||||
sorl-thumbnail
|
||||
|
||||
@@ -26,15 +27,15 @@ 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
|
||||
django-allauth
|
||||
django-tinymce
|
||||
apache-libcloud
|
||||
mandrill
|
||||
djrill
|
||||
|
||||
djangorestframework
|
||||
djangorestframework-jwt
|
||||
celery
|
||||
|
||||
djangorestframework==3.1.3
|
||||
djangorestframework-jwt==1.6.0
|
||||
drf-nested-routers
|
||||
django-celery
|
||||
pillow
|
||||
django-gravatar2
|
||||
|
||||
@@ -43,4 +44,4 @@ mutagen
|
||||
django-enumfield
|
||||
|
||||
ipython
|
||||
ipdb
|
||||
ipdb
|
||||
|
||||
2
run_celery.sh
Executable file
2
run_celery.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
su -m djworker -c "python manage.py celeryd"
|
||||
2
run_web.sh
Executable file
2
run_web.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
su -m djworker -c "python manage.py runserver_plus 0.0.0.0:8000"
|
||||
@@ -1,21 +1,19 @@
|
||||
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
||||
from django.db.models import Count, Q, F
|
||||
from django.db.models import Count, Q
|
||||
from django.conf.urls import url
|
||||
|
||||
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):
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
from django.core.management.base import NoArgsCommand, BaseCommand
|
||||
import os
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from core.utils.cdn import upload_to_azure
|
||||
from core.utils import cdn
|
||||
from spa.models import Mix
|
||||
|
||||
|
||||
def _update_azure_headers():
|
||||
ms = Mix.objects.all()
|
||||
for m in ms:
|
||||
cdn.set_azure_details('{0}.mp3'.format(m.uid), 'Deep South Sounds - {0}'.format(m.title), 'mixes')
|
||||
|
||||
def _check_missing_mixes():
|
||||
ms = Mix.objects.all()
|
||||
found = 0
|
||||
for m in ms:
|
||||
url = m.get_download_url()
|
||||
if not cdn.file_exists(url):
|
||||
file = '/mnt/dev/working/Dropbox/Development/deepsouthsounds.com/media/mixes/{0}.mp3'.format(m.uid)
|
||||
if os.path.isfile(file):
|
||||
print '* {0}'.format(file)
|
||||
#cdn.upload_file_to_azure(file, '{0}.mp3'.format(m.uid), 'mixes')
|
||||
found += 1
|
||||
else:
|
||||
found += 1
|
||||
print '({0}){1} - {2}'.format(found, m.slug, m.uid)
|
||||
|
||||
print '{0} of {1} missing'.format(found, Mix.objects.count())
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
@@ -18,7 +42,7 @@ class Command(BaseCommand):
|
||||
mixes = Mix.objects.filter(archive_updated=False)
|
||||
for mix in mixes:
|
||||
blob_name, download_name = mix.get_cdn_details()
|
||||
upload_to_azure(blob_name, "mp3", download_name)
|
||||
cdn.upload_file_to_azure(blob_name, "mp3", download_name)
|
||||
mix.archive_updated = True
|
||||
mix.save()
|
||||
|
||||
@@ -26,4 +50,11 @@ class Command(BaseCommand):
|
||||
print "Fatal error, bailing. {0}".format(ex.message)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
pass
|
||||
if len(args) == 0:
|
||||
print "Commands are \n\t_check_missing_mixes"
|
||||
elif args[0] == 'check_missing_mix':
|
||||
_check_missing_mixes()
|
||||
elif args[0] == 'update_azure_headers':
|
||||
_update_azure_headers()
|
||||
else:
|
||||
print "Commands are \n\tcheck_missing_mix"
|
||||
|
||||
15
spa/management/commands/create_notifications.py
Executable file
15
spa/management/commands/create_notifications.py
Executable file
@@ -0,0 +1,15 @@
|
||||
from django.core.management.base import NoArgsCommand
|
||||
from spa import models
|
||||
|
||||
|
||||
class Command(NoArgsCommand):
|
||||
def handle_noargs(self, **options):
|
||||
try:
|
||||
models.Notification.objects.all().delete()
|
||||
act = models.Activity.objects.all().order_by('-id').select_subclasses()
|
||||
for a in act:
|
||||
print "Creating for: {0}".format(a)
|
||||
a.create_notification(accept=True)
|
||||
|
||||
except Exception, ex:
|
||||
print "Debug exception: %s" % ex.message
|
||||
@@ -1,21 +1,42 @@
|
||||
import urllib2
|
||||
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
from django.core.files.base import ContentFile
|
||||
from azure.storage import BlobService
|
||||
from django.core.files.base import File
|
||||
from django.core.files.temp import NamedTemporaryFile
|
||||
from django.core.management.base import NoArgsCommand
|
||||
from requests import request, ConnectionError
|
||||
|
||||
from dss import storagesettings
|
||||
from spa.models.userprofile import UserProfile
|
||||
|
||||
|
||||
def save_image(profile, url):
|
||||
|
||||
img = NamedTemporaryFile(delete=True)
|
||||
img.write(urllib2.urlopen(url).read())
|
||||
|
||||
img.flush()
|
||||
profile.avatar_image.save(str(profile.id), File(img))
|
||||
|
||||
|
||||
def save_image_to_azure(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()
|
||||
service = BlobService(
|
||||
account_name=storagesettings.AZURE_ACCOUNT_NAME,
|
||||
account_key=storagesettings.AZURE_ACCOUNT_KEY)
|
||||
|
||||
service.put_block_blob_from_bytes(
|
||||
'avatars',
|
||||
profile.id,
|
||||
response.content,
|
||||
x_ms_blob_content_type=response.headers['content-type']
|
||||
)
|
||||
|
||||
|
||||
class Command(NoArgsCommand):
|
||||
@@ -31,6 +52,7 @@ class Command(NoArgsCommand):
|
||||
if provider_account:
|
||||
avatar_url = provider_account.get_avatar_url()
|
||||
save_image(user, avatar_url)
|
||||
user.save()
|
||||
except Exception, ex:
|
||||
print ex.message
|
||||
else:
|
||||
|
||||
22
spa/management/commands/tidy_cdn.py
Executable file
22
spa/management/commands/tidy_cdn.py
Executable file
@@ -0,0 +1,22 @@
|
||||
import os
|
||||
from django.core.management.base import NoArgsCommand
|
||||
from core.utils import cdn
|
||||
from spa.models import Mix
|
||||
|
||||
|
||||
class Command(NoArgsCommand):
|
||||
def handle_noargs(self, **options):
|
||||
try:
|
||||
print 'Enumerating items'
|
||||
items = cdn.enumerate_objects('mixes')
|
||||
for item in items:
|
||||
# Check if we have a corresponding mix
|
||||
uid, type = os.path.splitext(item)
|
||||
try:
|
||||
Mix.objects.get(uid=uid)
|
||||
except Mix.DoesNotExist:
|
||||
# no mix found - delete the blob
|
||||
cdn.delete_object('mixes', item)
|
||||
print "Deleting blob: {0}".format(uid)
|
||||
except Exception, ex:
|
||||
print "Debug exception: %s" % ex.message
|
||||
@@ -1,10 +1,11 @@
|
||||
from optparse import make_option
|
||||
import os
|
||||
from django.core.management.base import NoArgsCommand, BaseCommand
|
||||
from spa.management.commands import helpers
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from spa.management.commands import helpers
|
||||
from spa.models.mix import Mix
|
||||
from core.tasks import create_waveform_task
|
||||
from spa.tasks import create_waveform_task
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -40,7 +41,7 @@ class Command(BaseCommand):
|
||||
return processed_file
|
||||
|
||||
except Exception, ex:
|
||||
print "Error generating waveform: %s" % ex.message
|
||||
print "Error generating waveform: {0}".format(ex.message)
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Notification.notification_text'
|
||||
db.delete_column(u'spa_notification', 'notification_text')
|
||||
|
||||
# Deleting field 'Notification.notification_html'
|
||||
db.delete_column(u'spa_notification', 'notification_html')
|
||||
|
||||
# Deleting field 'Notification.notification_url'
|
||||
db.delete_column(u'spa_notification', 'notification_url')
|
||||
|
||||
# Adding field 'Notification.type'
|
||||
db.add_column(u'spa_notification', 'type',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=200, null=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# User chose to not deal with backwards NULL issues for 'Notification.notification_text'
|
||||
raise RuntimeError("Cannot reverse this migration. 'Notification.notification_text' and its values cannot be restored.")
|
||||
|
||||
# The following code is provided here to aid in writing a correct migration # Adding field 'Notification.notification_text'
|
||||
db.add_column(u'spa_notification', 'notification_text',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=1024),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
# User chose to not deal with backwards NULL issues for 'Notification.notification_html'
|
||||
raise RuntimeError("Cannot reverse this migration. 'Notification.notification_html' and its values cannot be restored.")
|
||||
|
||||
# The following code is provided here to aid in writing a correct migration # Adding field 'Notification.notification_html'
|
||||
db.add_column(u'spa_notification', 'notification_html',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=1024),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Notification.notification_url'
|
||||
db.add_column(u'spa_notification', 'notification_url',
|
||||
self.gf('django.db.models.fields.URLField')(max_length=200, null=True),
|
||||
keep_default=False)
|
||||
|
||||
# Deleting field 'Notification.type'
|
||||
db.delete_column(u'spa_notification', 'type')
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'spa._lookup': {
|
||||
'Meta': {'object_name': '_Lookup'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.activity': {
|
||||
'Meta': {'object_name': 'Activity'},
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.activitycomment': {
|
||||
'Meta': {'object_name': 'ActivityComment', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_comments'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activitydownload': {
|
||||
'Meta': {'object_name': 'ActivityDownload', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_downloads'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityfavourite': {
|
||||
'Meta': {'object_name': 'ActivityFavourite', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_favourites'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityfollow': {
|
||||
'Meta': {'object_name': 'ActivityFollow', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_follow'", 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.activitylike': {
|
||||
'Meta': {'object_name': 'ActivityLike', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_likes'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityplay': {
|
||||
'Meta': {'object_name': 'ActivityPlay', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_plays'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.chatmessage': {
|
||||
'Meta': {'object_name': 'ChatMessage'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'message': ('django.db.models.fields.TextField', [], {}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.comment': {
|
||||
'Meta': {'object_name': 'Comment'},
|
||||
'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'liked_comments'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'time_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.genre': {
|
||||
'Meta': {'object_name': 'Genre'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
|
||||
},
|
||||
'spa.label': {
|
||||
'Meta': {'object_name': 'Label'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.mix': {
|
||||
'Meta': {'ordering': "('-id',)", 'object_name': 'Mix'},
|
||||
'archive_path': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
|
||||
'archive_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {}),
|
||||
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'filetype': ('django.db.models.fields.CharField', [], {'default': "'mp3'", 'max_length': '10'}),
|
||||
'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'likes'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'mp3tags_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
|
||||
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
|
||||
'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mixes'", 'to': "orm['spa.UserProfile']"}),
|
||||
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'waveform_version': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
'spa.notification': {
|
||||
'Meta': {'ordering': "('-id',)", 'object_name': 'Notification'},
|
||||
'accepted_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'from_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notifications'", 'null': 'True', 'to': "orm['spa.UserProfile']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'target': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_notications'", 'to': "orm['spa.UserProfile']"}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'})
|
||||
},
|
||||
'spa.playlist': {
|
||||
'Meta': {'object_name': 'Playlist'},
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mixes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Mix']", 'symmetrical': 'False'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'playlists'", 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.purchaselink': {
|
||||
'Meta': {'object_name': 'PurchaseLink'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
|
||||
},
|
||||
'spa.recurrence': {
|
||||
'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']},
|
||||
u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'spa.release': {
|
||||
'Meta': {'object_name': 'Release'},
|
||||
'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2015, 8, 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', [], {}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"})
|
||||
},
|
||||
'spa.tracklist': {
|
||||
'Meta': {'object_name': 'Tracklist'},
|
||||
'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'index': ('django.db.models.fields.SmallIntegerField', [], {}),
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
||||
},
|
||||
'spa.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile'},
|
||||
'activity_sharing_facebook': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'activity_sharing_twitter': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
|
||||
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
|
||||
'email_notifications': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_known_session': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'spa.venue': {
|
||||
'Meta': {'object_name': 'Venue'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
|
||||
'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['spa']
|
||||
274
spa/migrations/0072_auto__add_field_notification_target_desc.py
Normal file
274
spa/migrations/0072_auto__add_field_notification_target_desc.py
Normal file
@@ -0,0 +1,274 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Notification.target_desc'
|
||||
db.add_column(u'spa_notification', 'target_desc',
|
||||
self.gf('django.db.models.fields.CharField')(max_length=200, null=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'Notification.target_desc'
|
||||
db.delete_column(u'spa_notification', 'target_desc')
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'spa._lookup': {
|
||||
'Meta': {'object_name': '_Lookup'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.activity': {
|
||||
'Meta': {'object_name': 'Activity'},
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.activitycomment': {
|
||||
'Meta': {'object_name': 'ActivityComment', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_comments'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activitydownload': {
|
||||
'Meta': {'object_name': 'ActivityDownload', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_downloads'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityfavourite': {
|
||||
'Meta': {'object_name': 'ActivityFavourite', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_favourites'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityfollow': {
|
||||
'Meta': {'object_name': 'ActivityFollow', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_follow'", 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.activitylike': {
|
||||
'Meta': {'object_name': 'ActivityLike', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_likes'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityplay': {
|
||||
'Meta': {'object_name': 'ActivityPlay', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_plays'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.chatmessage': {
|
||||
'Meta': {'object_name': 'ChatMessage'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'message': ('django.db.models.fields.TextField', [], {}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.comment': {
|
||||
'Meta': {'object_name': 'Comment'},
|
||||
'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'liked_comments'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'time_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.genre': {
|
||||
'Meta': {'object_name': 'Genre'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
|
||||
},
|
||||
'spa.label': {
|
||||
'Meta': {'object_name': 'Label'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.mix': {
|
||||
'Meta': {'ordering': "('-id',)", 'object_name': 'Mix'},
|
||||
'archive_path': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
|
||||
'archive_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {}),
|
||||
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'filetype': ('django.db.models.fields.CharField', [], {'default': "'mp3'", 'max_length': '10'}),
|
||||
'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'likes'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'mp3tags_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
|
||||
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
|
||||
'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mixes'", 'to': "orm['spa.UserProfile']"}),
|
||||
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'waveform_version': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
'spa.notification': {
|
||||
'Meta': {'ordering': "('-id',)", 'object_name': 'Notification'},
|
||||
'accepted_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'from_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notifications'", 'null': 'True', 'to': "orm['spa.UserProfile']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'target': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'target_desc': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_notications'", 'to': "orm['spa.UserProfile']"}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'})
|
||||
},
|
||||
'spa.playlist': {
|
||||
'Meta': {'object_name': 'Playlist'},
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mixes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Mix']", 'symmetrical': 'False'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'playlists'", 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.purchaselink': {
|
||||
'Meta': {'object_name': 'PurchaseLink'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
|
||||
},
|
||||
'spa.recurrence': {
|
||||
'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']},
|
||||
u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'spa.release': {
|
||||
'Meta': {'object_name': 'Release'},
|
||||
'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2015, 8, 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', [], {}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"})
|
||||
},
|
||||
'spa.tracklist': {
|
||||
'Meta': {'object_name': 'Tracklist'},
|
||||
'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'index': ('django.db.models.fields.SmallIntegerField', [], {}),
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
||||
},
|
||||
'spa.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile'},
|
||||
'activity_sharing_facebook': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'activity_sharing_twitter': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
|
||||
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
|
||||
'email_notifications': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_known_session': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'spa.venue': {
|
||||
'Meta': {'object_name': 'Venue'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'object_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2015, 8, 12, 0, 0)', 'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
|
||||
'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['spa']
|
||||
@@ -1,11 +1,9 @@
|
||||
import abc
|
||||
from django.contrib.auth.models import AnonymousUser, User
|
||||
from datetime import datetime
|
||||
|
||||
from allauth.socialaccount.models import SocialToken
|
||||
from datetime import datetime
|
||||
from django.db import models
|
||||
from model_utils.managers import InheritanceManager
|
||||
|
||||
from open_facebook import OpenFacebook
|
||||
|
||||
from core.utils.url import wrap_full
|
||||
@@ -62,27 +60,20 @@ class Activity(BaseModel):
|
||||
print ex.message
|
||||
pass
|
||||
|
||||
def create_notification(self):
|
||||
def create_notification(self, accept=False):
|
||||
try:
|
||||
notification = Notification()
|
||||
notification.from_user = self.user
|
||||
notification.to_user = self.get_target_user()
|
||||
notification.notification_text = "%s %s %s" % (
|
||||
self.user.get_nice_name() if self.user is not None else "Anonymouse",
|
||||
self.get_verb_past(),
|
||||
self.get_object_name_for_notification())
|
||||
|
||||
notification.notification_html = "<a href='%s'>%s</a> %s <a href='%s'>%s</a>" % (
|
||||
wrap_full(self.user.get_profile_url() if self.user is not None else ""),
|
||||
self.user.get_nice_name() if self.user is not None else "Anonymouse",
|
||||
self.get_verb_past(),
|
||||
wrap_full(self.get_object_url()),
|
||||
self.get_object_name_for_notification()
|
||||
)
|
||||
|
||||
notification.notification_url = self.get_object_url()
|
||||
notification.verb = self.get_verb_past()
|
||||
notification.target = self.get_object_name()
|
||||
notification.type = self.get_object_type()
|
||||
notification.target = self.get_object_slug()
|
||||
notification.target_desc = self.get_object_name()
|
||||
|
||||
if accept:
|
||||
notification.accepted_date = datetime.now()
|
||||
|
||||
notification.save()
|
||||
except Exception, ex:
|
||||
print "Error creating activity notification: %s" % ex.message
|
||||
|
||||
@@ -10,7 +10,7 @@ from dss import localsettings, settings
|
||||
|
||||
|
||||
class BaseModel(models.Model):
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logging.getLogger('dss')
|
||||
|
||||
object_created = models.DateTimeField(auto_now_add=True, default=datetime.now())
|
||||
object_updated = models.DateTimeField(auto_now=True, default=datetime.now(), db_index=True)
|
||||
@@ -33,11 +33,8 @@ class BaseModel(models.Model):
|
||||
def get_image_url(self, image, default):
|
||||
try:
|
||||
if os.path.isfile(image.path):
|
||||
images_root = localsettings.IMAGE_URL if hasattr(localsettings,
|
||||
'IMAGE_URL') else "%s" % settings.MEDIA_URL
|
||||
ret = "%s/%s/%s" % (settings.STATIC_URL, images_root, image)
|
||||
ret = "{0}/{1}".format(settings.MEDIA_URL, image)
|
||||
return url.urlclean(ret)
|
||||
|
||||
except Exception, ex:
|
||||
pass
|
||||
|
||||
|
||||
@@ -102,4 +102,6 @@ try:
|
||||
from south.modelsinspector import add_introspection_rules
|
||||
add_introspection_rules([], ['^spa\.models.fields\.MultiSelectField'])
|
||||
except ImportError:
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import os
|
||||
import rfc822
|
||||
import urlparse
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
import os
|
||||
from django.utils.encoding import smart_str
|
||||
from sorl.thumbnail import get_thumbnail
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import models
|
||||
@@ -19,8 +18,7 @@ from dss import settings, localsettings
|
||||
from spa.models.userprofile import UserProfile
|
||||
from spa.models.basemodel import BaseModel
|
||||
from core.utils.file import generate_save_file_name
|
||||
from PIL import Image
|
||||
import glob
|
||||
from core.utils import cdn
|
||||
|
||||
|
||||
class Engine(Engine):
|
||||
@@ -104,7 +102,7 @@ class Mix(BaseModel):
|
||||
|
||||
self.clean_image('mix_image', Mix)
|
||||
# Check for the unlikely event that the waveform has been generated
|
||||
if os.path.isfile(self.get_waveform_path()):
|
||||
if cdn.file_exists('{0}{1}.png'.format(localsettings.WAVEFORM_URL, self.uid)):
|
||||
self.waveform_generated = True
|
||||
try:
|
||||
self.duration = mp3_length(self.get_absolute_path())
|
||||
@@ -170,7 +168,7 @@ class Mix(BaseModel):
|
||||
try:
|
||||
if self.mix_image.name and self.mix_image.storage.exists(self.mix_image.name):
|
||||
ret = get_thumbnail(self.mix_image, size, crop='center')
|
||||
return "%s/%s" % (settings.MEDIA_URL, ret.name)
|
||||
return url.urlclean("%s/%s" % (settings.MEDIA_URL, ret.name))
|
||||
else:
|
||||
return self.user.get_sized_avatar_image(170, 170)
|
||||
except Exception, ex:
|
||||
|
||||
@@ -13,12 +13,10 @@ class Notification(BaseModel):
|
||||
from_user = models.ForeignKey('spa.UserProfile', related_name='notifications', null=True, blank=True)
|
||||
date = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
notification_text = models.CharField(max_length=1024)
|
||||
notification_html = models.CharField(max_length=1024)
|
||||
notification_url = models.URLField(null=True)
|
||||
|
||||
verb = models.CharField(max_length=200, null=True)
|
||||
type = models.CharField(max_length=200, null=True)
|
||||
target = models.CharField(max_length=200, null=True)
|
||||
target_desc = models.CharField(max_length=200, null=True)
|
||||
|
||||
accepted_date = models.DateTimeField(null=True)
|
||||
|
||||
@@ -29,8 +27,7 @@ class Notification(BaseModel):
|
||||
def get_notification_url(self):
|
||||
return '/api/v1/notification/%s' % self.id
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
def __save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
|
||||
if self._activity.should_send_email():
|
||||
self.send_notification_email()
|
||||
@@ -81,3 +78,6 @@ class Notification(BaseModel):
|
||||
|
||||
except mandrill.Error, e: # Mandrill errors are thrown as exceptions
|
||||
print 'A mandrill error occurred: %s - %s' % (e.__class__, e)
|
||||
|
||||
def get_from_user(self):
|
||||
return UserProfile.get_user(self.from_user)
|
||||
|
||||
7
spa/models/session.py
Normal file
7
spa/models/session.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.db import models
|
||||
from spa.models import BaseModel, UserProfile
|
||||
|
||||
|
||||
class Session(BaseModel):
|
||||
jwt_token = models.CharField(max_length=2048)
|
||||
user = models.ForeignKey(UserProfile)
|
||||
@@ -139,6 +139,9 @@ class UserProfile(BaseModel):
|
||||
except Exception, e:
|
||||
self.logger.error("Unable to create profile slug: %s", e.message)
|
||||
|
||||
def get_session_id(self):
|
||||
return str(self.id)
|
||||
|
||||
def toggle_favourite(self, mix, value):
|
||||
try:
|
||||
if value:
|
||||
|
||||
@@ -4,6 +4,7 @@ from django.db.models.signals import post_save, pre_save, m2m_changed
|
||||
from django.dispatch import Signal, receiver
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from core.realtime import activity
|
||||
|
||||
from core.utils.audio.mp3 import mp3_length
|
||||
from spa.models.activity import ActivityFollow
|
||||
@@ -18,11 +19,12 @@ def _waveform_generated_callback(sender, **kwargs):
|
||||
print "Updating model with waveform"
|
||||
try:
|
||||
uid = kwargs['uid']
|
||||
path = kwargs['path']
|
||||
if uid is not None:
|
||||
mix = Mix.objects.get(uid=uid)
|
||||
if mix is not None:
|
||||
mix.waveform_generated = True
|
||||
mix.duration = mp3_length(mix.get_absolute_path())
|
||||
mix.duration = mp3_length(path)
|
||||
mix.save(update_fields=["waveform_generated", "duration"])
|
||||
|
||||
except ObjectDoesNotExist:
|
||||
|
||||
62
spa/tasks.py
Executable file
62
spa/tasks.py
Executable file
@@ -0,0 +1,62 @@
|
||||
from celery.task import task
|
||||
import os
|
||||
import logging
|
||||
from core.realtime import activity
|
||||
|
||||
from core.utils import cdn
|
||||
from spa.signals import waveform_generated_signal
|
||||
|
||||
try:
|
||||
from django.contrib.gis.geoip import GeoIP
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from core.utils.waveform import generate_waveform
|
||||
from dss import settings
|
||||
|
||||
logger = logging.getLogger('dss')
|
||||
|
||||
|
||||
@task(time_limit=3600)
|
||||
def create_waveform_task(in_file, uid):
|
||||
out_file = os.path.join(settings.CACHE_ROOT, 'waveforms/%s.png' % uid)
|
||||
logger.info("Creating waveform \n\tIn: %s\n\tOut: %s" % (in_file, out_file))
|
||||
generate_waveform(in_file, out_file)
|
||||
if os.path.isfile(out_file):
|
||||
logger.info("Waveform generated successfully")
|
||||
waveform_generated_signal.send(sender=None, uid=uid, path=in_file)
|
||||
return out_file
|
||||
else:
|
||||
logger.error("Outfile is missing")
|
||||
|
||||
|
||||
@task(timse_limit=3600)
|
||||
def upload_to_cdn_task(filetype, uid, container_name):
|
||||
source_file = os.path.join(settings.CACHE_ROOT, '{0}/{1}.{2}'.format(container_name, uid, filetype))
|
||||
logger.info("Sending {0} to azure".format(uid))
|
||||
try:
|
||||
file_name = "{0}.{1}".format(uid, filetype)
|
||||
cdn.upload_file_to_azure(source_file, file_name, container_name)
|
||||
return source_file
|
||||
except Exception, ex:
|
||||
logger.error("Unable to upload: {0}".format(ex.message))
|
||||
|
||||
|
||||
@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:
|
||||
logger.exception(e)
|
||||
pass
|
||||
|
||||
|
||||
@task
|
||||
def notify_subscriber(session_id, uid):
|
||||
if session_id is not None:
|
||||
activity.post_activity('user:message', session_id, {'type': 'waveform', 'target': uid})
|
||||
Reference in New Issue
Block a user