mirror of
https://github.com/fergalmoran/dss.api.git
synced 2025-12-28 20:30:44 +00:00
Pre feature branch
This commit is contained in:
2
INSTALL
2
INSTALL
@@ -1,6 +1,6 @@
|
|||||||
#curl -u hb_client_2862_1:j2CbCM8H -H 'Accept: application/json' -H 'Content-type: application/json' http://c1.lon2.dediserve.com/virtual_machines.xml
|
#curl -u hb_client_2862_1:j2CbCM8H -H 'Accept: application/json' -H 'Content-type: application/json' http://c1.lon2.dediserve.com/virtual_machines.xml
|
||||||
|
|
||||||
apt-get install git python-virtualenv postgresql-common libsndfile1-dev libpng++-dev libpng12-dev libboost-program-options-dev libjpeg-dev python-dev libsox-fmt-mp3
|
apt-get install git python-virtualenv postgresql-common libsndfile1-dev libpng++-dev libpng12-dev libboost-program-options-dev libjpeg-dev python-dev libsox-fmt-mp3 postgresql-server-dev-all postgresql-client
|
||||||
virtualenv env
|
virtualenv env
|
||||||
source env/bin/activate
|
source env/bin/activate
|
||||||
|
|
||||||
|
|||||||
122
api/auth.py
Executable file → Normal file
122
api/auth.py
Executable file → Normal file
@@ -1,121 +1 @@
|
|||||||
from requests import HTTPError
|
__author__ = 'fergalm'
|
||||||
from rest_framework import parsers
|
|
||||||
from rest_framework.authentication import get_authorization_header
|
|
||||||
from rest_framework.authtoken.models import Token
|
|
||||||
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework.status import *
|
|
||||||
from rest_framework.views import APIView
|
|
||||||
from rest_framework import status
|
|
||||||
from rest_framework import renderers
|
|
||||||
from social.apps.django_app.utils import strategy, load_strategy, load_backend
|
|
||||||
from dss import settings
|
|
||||||
|
|
||||||
|
|
||||||
class LoginException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@strategy()
|
|
||||||
def register_by_access_token(request, backend):
|
|
||||||
auth = get_authorization_header(request).split()
|
|
||||||
if not auth or auth[0].lower() != b'social':
|
|
||||||
raise LoginException("Unable to register_by_access_token: No token header provided")
|
|
||||||
|
|
||||||
access_token = auth[1]
|
|
||||||
return request.backend.do_auth(access_token)
|
|
||||||
"""
|
|
||||||
class RefreshTokenView(APIView):
|
|
||||||
serializer_class = AuthTokenSerializer
|
|
||||||
model = Token
|
|
||||||
|
|
||||||
def post(self, request):
|
|
||||||
# Here we call PSA to authenticate like we would if we used PSA on server side.
|
|
||||||
try:
|
|
||||||
backend = request.META.get('HTTP_AUTH_BACKEND')
|
|
||||||
if backend is None:
|
|
||||||
# Work around django test client oddness
|
|
||||||
return Response("No Auth-Backend header specified", HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
user = refresh_access_token(request, backend)
|
|
||||||
|
|
||||||
# If user is active we get or create the REST token and send it back with user data
|
|
||||||
if user and user.is_active:
|
|
||||||
token, created = Token.objects.get_or_create(user=user)
|
|
||||||
return Response({
|
|
||||||
'slug': user.userprofile.slug,
|
|
||||||
'token': token.key
|
|
||||||
})
|
|
||||||
except LoginException, ex:
|
|
||||||
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
|
||||||
except HTTPError, ex:
|
|
||||||
if ex.response.status_code == 400:
|
|
||||||
return Response(ex.message, HTTP_401_UNAUTHORIZED)
|
|
||||||
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
|
||||||
"""
|
|
||||||
|
|
||||||
class ObtainAuthToken(APIView):
|
|
||||||
serializer_class = AuthTokenSerializer
|
|
||||||
model = Token
|
|
||||||
|
|
||||||
def post(self, request):
|
|
||||||
# Here we call PSA to authenticate like we would if we used PSA on server side.
|
|
||||||
try:
|
|
||||||
backend = request.META.get('HTTP_AUTH_BACKEND')
|
|
||||||
if backend is None:
|
|
||||||
# Work around django test client oddness
|
|
||||||
return Response("No Auth-Backend header specified", HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
user = register_by_access_token(request, backend)
|
|
||||||
|
|
||||||
# If user is active we get or create the REST token and send it back with user data
|
|
||||||
if user and user.is_active:
|
|
||||||
token, created = Token.objects.get_or_create(user=user)
|
|
||||||
return Response({
|
|
||||||
'slug': user.userprofile.slug,
|
|
||||||
'token': token.key
|
|
||||||
})
|
|
||||||
except LoginException, ex:
|
|
||||||
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
|
||||||
except HTTPError, ex:
|
|
||||||
if ex.response.status_code == 400:
|
|
||||||
return Response(ex.message, HTTP_401_UNAUTHORIZED)
|
|
||||||
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
|
|
||||||
class ObtainUser(APIView):
|
|
||||||
throttle_classes = ()
|
|
||||||
permission_classes = ()
|
|
||||||
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
|
||||||
renderer_classes = (renderers.JSONRenderer,)
|
|
||||||
serializer_class = AuthTokenSerializer
|
|
||||||
model = Token
|
|
||||||
|
|
||||||
def get(self, request):
|
|
||||||
if request.META.get('HTTP_AUTHORIZATION'):
|
|
||||||
|
|
||||||
auth = request.META.get('HTTP_AUTHORIZATION').split()
|
|
||||||
|
|
||||||
if not auth or auth[0].lower() != b'token' or len(auth) != 2:
|
|
||||||
msg = 'Invalid token header. No credentials provided.'
|
|
||||||
return Response(msg, status=status.HTTP_401_UNAUTHORIZED)
|
|
||||||
|
|
||||||
token = Token.objects.get(key=auth[1])
|
|
||||||
if token and token.user.is_active:
|
|
||||||
return Response({'id': token.user_id, 'name': token.user.username, 'firstname': token.user.first_name,
|
|
||||||
'userRole': 'user', 'token': token.key})
|
|
||||||
else:
|
|
||||||
return Response(status=status.HTTP_401_UNAUTHORIZED)
|
|
||||||
|
|
||||||
|
|
||||||
class ObtainLogout(APIView):
|
|
||||||
throttle_classes = ()
|
|
||||||
permission_classes = ()
|
|
||||||
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
|
||||||
renderer_classes = (renderers.JSONRenderer,)
|
|
||||||
serializer_class = AuthTokenSerializer
|
|
||||||
model = Token
|
|
||||||
|
|
||||||
# Logout le user
|
|
||||||
def get(self, request):
|
|
||||||
return Response({'User': ''})
|
|
||||||
|
|||||||
@@ -4,21 +4,35 @@ from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_201_CREATED, HTTP_2
|
|||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from dss import settings
|
from dss import settings
|
||||||
from spa.models import Mix, UserProfile
|
from spa.models import Mix, UserProfile
|
||||||
|
from core.utils import session
|
||||||
|
|
||||||
class Helper(APIView):
|
class Helper(APIView):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ActivityHelper(APIView):
|
class ActivityHelper(APIView):
|
||||||
pass
|
def get_session(self, request):
|
||||||
|
sessions = session.get_active_sessions(request.session)
|
||||||
|
|
||||||
|
return sessions[0]
|
||||||
|
|
||||||
|
|
||||||
|
class ChatHelper(ActivityHelper):
|
||||||
|
def post(self, request):
|
||||||
|
# do some persistence stuff with the chat
|
||||||
|
from core.realtime import chat
|
||||||
|
|
||||||
|
user = self.get_session(request)
|
||||||
|
|
||||||
|
chat.post_chat(request.DATA['user'], request.DATA['message'])
|
||||||
|
return Response(request.DATA['message'], HTTP_201_CREATED)
|
||||||
|
|
||||||
|
|
||||||
class ActivityPlayHelper(ActivityHelper):
|
class ActivityPlayHelper(ActivityHelper):
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
if 'id' in self.request.QUERY_PARAMS:
|
if 'id' in self.request.query_params:
|
||||||
try:
|
try:
|
||||||
mix = Mix.objects.get(slug=self.request.QUERY_PARAMS.get('id'))
|
mix = Mix.objects.get(slug=self.request.query_params.get('id'))
|
||||||
mix.add_play(request.user)
|
mix.add_play(request.user)
|
||||||
data = {
|
data = {
|
||||||
'user': request.user.userprofile.get_nice_name() if request.user.is_authenticated() else settings.DEFAULT_USER_NAME,
|
'user': request.user.userprofile.get_nice_name() if request.user.is_authenticated() else settings.DEFAULT_USER_NAME,
|
||||||
@@ -34,7 +48,7 @@ class ActivityPlayHelper(ActivityHelper):
|
|||||||
class UserSlugCheckHelper(Helper):
|
class UserSlugCheckHelper(Helper):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
try:
|
try:
|
||||||
UserProfile.objects.get(slug=self.request.QUERY_PARAMS.get('slug'))
|
UserProfile.objects.get(slug=self.request.query_params.get('slug'))
|
||||||
return Response(status=HTTP_204_NO_CONTENT)
|
return Response(status=HTTP_204_NO_CONTENT)
|
||||||
except UserProfile.DoesNotExist:
|
except UserProfile.DoesNotExist:
|
||||||
return Response(status=HTTP_200_OK)
|
return Response(status=HTTP_200_OK)
|
||||||
|
|||||||
120
api/old_auth.py
Executable file
120
api/old_auth.py
Executable file
@@ -0,0 +1,120 @@
|
|||||||
|
from requests import HTTPError
|
||||||
|
from rest_framework import parsers
|
||||||
|
from rest_framework.authentication import get_authorization_header
|
||||||
|
from rest_framework.authtoken.models import Token
|
||||||
|
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.status import *
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework import renderers
|
||||||
|
from social.apps.django_app.utils import psa
|
||||||
|
|
||||||
|
|
||||||
|
class LoginException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@psa()
|
||||||
|
def register_by_access_token(request, backend):
|
||||||
|
auth = get_authorization_header(request).split()
|
||||||
|
if not auth or auth[0].lower() != b'social':
|
||||||
|
raise LoginException("Unable to register_by_access_token: No token header provided")
|
||||||
|
|
||||||
|
access_token = auth[1]
|
||||||
|
return request.backend.do_auth(access_token)
|
||||||
|
"""
|
||||||
|
class RefreshTokenView(APIView):
|
||||||
|
serializer_class = AuthTokenSerializer
|
||||||
|
model = Token
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
# Here we call PSA to authenticate like we would if we used PSA on server side.
|
||||||
|
try:
|
||||||
|
backend = request.META.get('HTTP_AUTH_BACKEND')
|
||||||
|
if backend is None:
|
||||||
|
# Work around django test client oddness
|
||||||
|
return Response("No Auth-Backend header specified", HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
user = refresh_access_token(request, backend)
|
||||||
|
|
||||||
|
# If user is active we get or create the REST token and send it back with user data
|
||||||
|
if user and user.is_active:
|
||||||
|
token, created = Token.objects.get_or_create(user=user)
|
||||||
|
return Response({
|
||||||
|
'slug': user.userprofile.slug,
|
||||||
|
'token': token.key
|
||||||
|
})
|
||||||
|
except LoginException, ex:
|
||||||
|
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
||||||
|
except HTTPError, ex:
|
||||||
|
if ex.response.status_code == 400:
|
||||||
|
return Response(ex.message, HTTP_401_UNAUTHORIZED)
|
||||||
|
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
||||||
|
"""
|
||||||
|
|
||||||
|
class ObtainAuthToken(APIView):
|
||||||
|
serializer_class = AuthTokenSerializer
|
||||||
|
model = Token
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
# Here we call PSA to authenticate like we would if we used PSA on server side.
|
||||||
|
try:
|
||||||
|
backend = request.META.get('HTTP_AUTH_BACKEND')
|
||||||
|
if backend is None:
|
||||||
|
# Work around django test client oddness
|
||||||
|
return Response("No Auth-Backend header specified", HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
user = register_by_access_token(request, backend)
|
||||||
|
|
||||||
|
# If user is active we get or create the REST token and send it back with user data
|
||||||
|
if user and user.is_active:
|
||||||
|
token, created = Token.objects.get_or_create(user=user)
|
||||||
|
return Response({
|
||||||
|
'slug': user.userprofile.slug,
|
||||||
|
'token': token.key
|
||||||
|
})
|
||||||
|
except LoginException, ex:
|
||||||
|
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
||||||
|
except HTTPError, ex:
|
||||||
|
if ex.response.status_code == 400:
|
||||||
|
return Response(ex.message, HTTP_401_UNAUTHORIZED)
|
||||||
|
return Response(ex.message, HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
class ObtainUser(APIView):
|
||||||
|
throttle_classes = ()
|
||||||
|
permission_classes = ()
|
||||||
|
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
||||||
|
renderer_classes = (renderers.JSONRenderer,)
|
||||||
|
serializer_class = AuthTokenSerializer
|
||||||
|
model = Token
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
if request.META.get('HTTP_AUTHORIZATION'):
|
||||||
|
|
||||||
|
auth = request.META.get('HTTP_AUTHORIZATION').split()
|
||||||
|
|
||||||
|
if not auth or auth[0].lower() != b'token' or len(auth) != 2:
|
||||||
|
msg = 'Invalid token header. No credentials provided.'
|
||||||
|
return Response(msg, status=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
|
||||||
|
token = Token.objects.get(key=auth[1])
|
||||||
|
if token and token.user.is_active:
|
||||||
|
return Response({'id': token.user_id, 'name': token.user.username, 'firstname': token.user.first_name,
|
||||||
|
'userRole': 'user', 'token': token.key})
|
||||||
|
else:
|
||||||
|
return Response(status=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
|
||||||
|
|
||||||
|
class ObtainLogout(APIView):
|
||||||
|
throttle_classes = ()
|
||||||
|
permission_classes = ()
|
||||||
|
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
||||||
|
renderer_classes = (renderers.JSONRenderer,)
|
||||||
|
serializer_class = AuthTokenSerializer
|
||||||
|
model = Token
|
||||||
|
|
||||||
|
# Logout le user
|
||||||
|
def get(self, request):
|
||||||
|
return Response({'User': ''})
|
||||||
@@ -34,6 +34,7 @@ urlpatterns = patterns(
|
|||||||
|
|
||||||
|
|
||||||
url(r'^_act/play', helpers.ActivityPlayHelper.as_view()),
|
url(r'^_act/play', helpers.ActivityPlayHelper.as_view()),
|
||||||
|
url(r'^_chat/', helpers.ChatHelper.as_view()),
|
||||||
|
|
||||||
url('', include('social.apps.django_app.urls', namespace='social')),
|
url('', include('social.apps.django_app.urls', namespace='social')),
|
||||||
)
|
)
|
||||||
|
|||||||
14
api/views.py
14
api/views.py
@@ -75,10 +75,10 @@ class UserProfileViewSet(viewsets.ModelViewSet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if 'following' in self.request.QUERY_PARAMS:
|
if 'following' in self.request.query_params:
|
||||||
ret = UserProfile.objects.filter(following__slug__in=[self.request.QUERY_PARAMS['following']])
|
ret = UserProfile.objects.filter(following__slug__in=[self.request.query_params['following']])
|
||||||
elif 'followers' in self.request.QUERY_PARAMS:
|
elif 'followers' in self.request.query_params:
|
||||||
ret = UserProfile.objects.filter(followers__slug__in=[self.request.QUERY_PARAMS['followers']])
|
ret = UserProfile.objects.filter(followers__slug__in=[self.request.query_params['followers']])
|
||||||
else:
|
else:
|
||||||
ret = super(UserProfileViewSet, self).get_queryset()
|
ret = super(UserProfileViewSet, self).get_queryset()
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ class MixViewSet(viewsets.ModelViewSet):
|
|||||||
return Response({'url': mix.get_stream_url()})
|
return Response({'url': mix.get_stream_url()})
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if 'friends' in self.request.QUERY_PARAMS:
|
if 'friends' in self.request.query_params:
|
||||||
if self.request.user.is_authenticated():
|
if self.request.user.is_authenticated():
|
||||||
rows = Mix.objects.filter(user__in=self.request.user.userprofile.following.all())
|
rows = Mix.objects.filter(user__in=self.request.user.userprofile.following.all())
|
||||||
return rows
|
return rows
|
||||||
@@ -242,10 +242,10 @@ class GenreViewSet(viewsets.ModelViewSet):
|
|||||||
serializer_class = serializers.GenreSerializer
|
serializer_class = serializers.GenreSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if 'q' in self.request.QUERY_PARAMS:
|
if 'q' in self.request.query_params:
|
||||||
rows = Genre.objects \
|
rows = Genre.objects \
|
||||||
.annotate(used=Count('mix')) \
|
.annotate(used=Count('mix')) \
|
||||||
.filter(description__icontains=self.request.QUERY_PARAMS['q']) \
|
.filter(description__icontains=self.request.query_params['q']) \
|
||||||
.only('description') \
|
.only('description') \
|
||||||
.order_by('-used')
|
.order_by('-used')
|
||||||
return rows
|
return rows
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
import requests
|
import redis
|
||||||
from core.serialisers import json
|
import json
|
||||||
from dss import localsettings, settings
|
|
||||||
|
|
||||||
|
|
||||||
def post_activity(session_id, activity_url):
|
def post_activity(channel, session, message):
|
||||||
payload = {
|
r = redis.StrictRedis(host='localhost', port=6379, db=0)
|
||||||
'sessionid': session_id,
|
response = r.publish(channel, json.dumps({'session': session, 'message': message}))
|
||||||
'message': activity_url
|
print "Message sent: {0}".format(response)
|
||||||
}
|
|
||||||
data = json.dumps(payload)
|
if __name__ == '__main__':
|
||||||
r = requests.post(localsettings.REALTIME_HOST + 'activity', data=data, headers=settings.REALTIME_HEADERS)
|
post_activity('site:broadcast', '3a596ca6c97065a67aca3dc4a3ba230d688cf413', 'bargle')
|
||||||
if r.status_code == 200:
|
|
||||||
return ""
|
|
||||||
else:
|
|
||||||
return r.text
|
|
||||||
|
|||||||
8
core/realtime/chat.py
Normal file
8
core/realtime/chat.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import json
|
||||||
|
import redis
|
||||||
|
|
||||||
|
|
||||||
|
def post_chat(session, message):
|
||||||
|
r = redis.StrictRedis(host='localhost', port=6379, db=0)
|
||||||
|
response = r.publish('chat', json.dumps({'session': session, 'message': message}))
|
||||||
|
print "Message sent: {0}".format(response)
|
||||||
20
core/utils/session.py
Normal file
20
core/utils/session.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from django.contrib.sessions.models import Session
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_sessions(session):
|
||||||
|
# Query all non-expired sessions
|
||||||
|
# use timezone.now() instead of datetime.now() in latest versions of Django
|
||||||
|
sessions = Session.objects.filter(expire_date__gte=timezone.now())
|
||||||
|
if session is not None:
|
||||||
|
sessions = sessions.filter(session_id=session.id)
|
||||||
|
uid_list = []
|
||||||
|
|
||||||
|
# Build a list of user ids from that query
|
||||||
|
for session in sessions:
|
||||||
|
data = session.get_decoded()
|
||||||
|
uid_list.append(data.get('_auth_user_id', None))
|
||||||
|
|
||||||
|
# Query all logged in users based on id list
|
||||||
|
from spa.models import UserProfile
|
||||||
|
return UserProfile.objects.filter(user_id__in=uid_list)
|
||||||
@@ -16,6 +16,7 @@ django-model_utils
|
|||||||
django-dbbackup
|
django-dbbackup
|
||||||
django-user-agents
|
django-user-agents
|
||||||
south
|
south
|
||||||
|
redis
|
||||||
|
|
||||||
sorl-thumbnail
|
sorl-thumbnail
|
||||||
|
|
||||||
@@ -24,6 +25,8 @@ git+git://github.com/Azure/azure-sdk-for-python.git#azure
|
|||||||
git+git://github.com/tschellenbach/Django-facebook.git#django-facebook
|
git+git://github.com/tschellenbach/Django-facebook.git#django-facebook
|
||||||
git+git://github.com/llazzaro/django-scheduler.git#django-scheduler
|
git+git://github.com/llazzaro/django-scheduler.git#django-scheduler
|
||||||
git+git://github.com/omab/python-social-auth.git#egg=python-social-auth
|
git+git://github.com/omab/python-social-auth.git#egg=python-social-auth
|
||||||
|
django-allauth
|
||||||
|
django-tinymce
|
||||||
apache-libcloud
|
apache-libcloud
|
||||||
mandrill
|
mandrill
|
||||||
djrill
|
djrill
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dirtyfields import DirtyFieldsMixin
|
import json
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import simplejson
|
|
||||||
from core.utils import url
|
from core.utils import url
|
||||||
from dss import localsettings, settings
|
from dss import localsettings, settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BaseModel(models.Model):
|
class BaseModel(models.Model):
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ class BaseModel(models.Model):
|
|||||||
app_label = 'spa'
|
app_label = 'spa'
|
||||||
|
|
||||||
def tosimplejson(self):
|
def tosimplejson(self):
|
||||||
return simplejson.dump(self)
|
return json.dumps(self)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_lookup(cls, filter_field, transform=None, filter=None):
|
def get_lookup(cls, filter_field, transform=None, filter=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user