inline django 1.9 version of ox.django

This commit is contained in:
j 2016-02-20 09:06:41 +00:00
parent 970f3f605d
commit 051a3578b4
74 changed files with 712 additions and 138 deletions

View File

@ -3,7 +3,7 @@
import unicodedata
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -6,11 +6,11 @@ from django.conf import settings
import ox
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
from item.models import Item

View File

@ -7,8 +7,8 @@ from django.shortcuts import render, redirect
from django.conf import settings
from django.http import HttpResponse
from ox.django.shortcuts import json_response, render_to_json_response
from ox.django.decorators import login_required_json
from oxdjango.shortcuts import json_response, render_to_json_response
from oxdjango.decorators import login_required_json
import ox
from ox.utils import json, ET
@ -18,7 +18,7 @@ import models
from user.models import init_user
from changelog.models import add_changelog
from ox.django.api import actions
from oxdjango.api import actions
def intro(request):
return render(request, 'intro.html', {'settings': settings})

View File

@ -6,7 +6,7 @@ import archive.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -35,7 +35,7 @@ class Migration(migrations.Migration):
('version', models.CharField(default=b'', max_length=255, null=True)),
('size', models.BigIntegerField(default=0)),
('duration', models.FloatField(null=True)),
('info', ox.django.fields.DictField(default={})),
('info', oxdjango.fields.DictField(default={})),
('video_codec', models.CharField(max_length=255)),
('pixel_format', models.CharField(max_length=255)),
('display_aspect_ratio', models.CharField(max_length=255)),
@ -96,11 +96,11 @@ class Migration(migrations.Migration):
('media', models.FileField(blank=True, default=None, upload_to=archive.models.get_path)),
('available', models.BooleanField(default=False)),
('oshash', models.CharField(db_index=True, max_length=16, null=True)),
('info', ox.django.fields.DictField(default={})),
('info', oxdjango.fields.DictField(default={})),
('duration', models.FloatField(default=0)),
('aspect_ratio', models.FloatField(default=0)),
('cuts', ox.django.fields.TupleField(default=[])),
('color', ox.django.fields.TupleField(default=[])),
('cuts', oxdjango.fields.TupleField(default=[])),
('color', oxdjango.fields.TupleField(default=[])),
('volume', models.FloatField(default=0)),
('error', models.TextField(blank=True, default=b'')),
('file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='streams', to='archive.File')),

View File

@ -12,7 +12,7 @@ from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import pre_delete
from ox.django import fields
from oxdjango import fields
import ox
import ox.iso

View File

@ -4,22 +4,21 @@ from __future__ import division
import os.path
from datetime import datetime
from django import forms
from django.shortcuts import get_object_or_404, redirect, render
from django.conf import settings
from django.db.models import Count, Q
from celery.utils import get_full_cls_name
from celery.backends import default_backend
import ox
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.views import task_status
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from item import utils
from item.models import get_item, Item
from item.views import parse_query
import item.tasks
from ox.django.api import actions
from oxdjango.api import actions
from changelog.models import add_changelog
import models
@ -358,7 +357,21 @@ def taskStatus(request, data):
task_id = data['taskId']
else:
task_id = data['task_id']
response = task_status(request, task_id)
response = json_response(status=200, text='ok')
status = default_backend.get_status(task_id)
res = default_backend.get_result(task_id)
response['data'] = {
'id': task_id,
'status': status,
'result': res
}
if status in default_backend.EXCEPTION_STATES:
traceback = default_backend.get_traceback(task_id)
response['data'].update({
'result': str(res.args[0]),
'exc': get_full_cls_name(res.__class__),
'traceback': traceback
})
return render_to_json_response(response)
actions.register(taskStatus, cache=False)

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('type', models.CharField(db_index=True, max_length=255)),
('value', ox.django.fields.DictField(default={})),
('value', oxdjango.fields.DictField(default={})),
],
),
migrations.CreateModel(
@ -31,7 +31,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('action', models.CharField(db_index=True, max_length=255)),
('data', ox.django.fields.DictField(default={})),
('data', oxdjango.fields.DictField(default={})),
('created', models.DateTimeField(db_index=True)),
('changeid', models.TextField()),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='changelog', to=settings.AUTH_USER_MODEL)),

View File

@ -6,7 +6,7 @@ from datetime import datetime
from django.contrib.auth.models import User
from django.db import models
from ox.django import fields
from oxdjango import fields
import ox
import websocket

View File

@ -4,10 +4,10 @@ from __future__ import division
import ox
from ox.django.decorators import admin_required_json
from ox.django.shortcuts import render_to_json_response, json_response
from oxdjango.decorators import admin_required_json
from oxdjango.shortcuts import render_to_json_response, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
from user.decorators import capability_required_json

View File

@ -5,7 +5,7 @@ import unicodedata
from django.db.models import Q, Manager
from django.conf import settings
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id, get_by_id

View File

@ -4,9 +4,9 @@ from __future__ import division
from django.conf import settings
from ox.utils import json
from ox.django.shortcuts import render_to_json_response, json_response
from oxdjango.shortcuts import render_to_json_response, json_response
from ox.django.api import actions
from oxdjango.api import actions
from annotation.models import Annotation
from item.models import Item

View File

@ -3,7 +3,7 @@
from django.db.models import Q, Manager
import ox
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
def parseCondition(condition, user, item=None):
'''

View File

@ -6,10 +6,10 @@ from glob import glob
import ox
from ox.utils import json
from ox.django.api import actions
from ox.django.decorators import login_required_json
from ox.django.http import HttpFileResponse
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from oxdjango.api import actions
from oxdjango.decorators import login_required_json
from oxdjango.http import HttpFileResponse
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from django import forms
from django.db.models import Sum

View File

@ -2,7 +2,7 @@
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
def parseCondition(condition, user):

View File

@ -6,7 +6,7 @@ from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import edit.models
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -47,10 +47,10 @@ class Migration(migrations.Migration):
('status', models.CharField(default=b'private', max_length=20)),
('description', models.TextField(default=b'')),
('rightslevel', models.IntegerField(db_index=True, default=0)),
('query', ox.django.fields.DictField(default={b'static': True})),
('query', oxdjango.fields.DictField(default={b'static': True})),
('type', models.CharField(default=b'static', max_length=255)),
('icon', models.ImageField(blank=True, default=None, null=True, upload_to=edit.models.get_icon_path)),
('poster_frames', ox.django.fields.TupleField(default=[], editable=False)),
('poster_frames', oxdjango.fields.TupleField(default=[], editable=False)),
('subscribed_users', models.ManyToManyField(related_name='subscribed_edits', to=settings.AUTH_USER_MODEL)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='edits', to=settings.AUTH_USER_MODEL)),
],

View File

@ -11,7 +11,7 @@ from urllib import quote
import tempfile
import ox
from ox.django.fields import DictField, TupleField
from oxdjango.fields import DictField, TupleField
from django.conf import settings
from django.db import models, transaction
from django.db.models import Max

View File

@ -5,12 +5,12 @@ import os
import re
import ox
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from django.db import transaction
from django.db.models import Max
from ox.django.http import HttpFileResponse
from ox.django.api import actions
from oxdjango.http import HttpFileResponse
from oxdjango.api import actions
from django.conf import settings
from item import utils

View File

@ -3,7 +3,7 @@
from django.db.models import Q, Manager
import ox
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
def namePredicate(op, value):

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -36,8 +36,8 @@ class Migration(migrations.Migration):
('modified', models.DateTimeField(auto_now=True)),
('type', models.CharField(max_length=255)),
('name', models.CharField(max_length=255)),
('alternativeNames', ox.django.fields.TupleField(default=[])),
('data', ox.django.fields.DictField(default={}, editable=False)),
('alternativeNames', oxdjango.fields.TupleField(default=[])),
('data', oxdjango.fields.DictField(default={}, editable=False)),
('matches', models.IntegerField(default=0)),
('name_sort', models.CharField(max_length=255, null=True)),
('name_find', models.TextField(default=b'')),

View File

@ -14,7 +14,7 @@ from django.db.models.signals import pre_delete, post_init
from django.conf import settings
import ox
from ox.django import fields
from oxdjango import fields
from person.models import get_name_sort
from item.utils import get_by_id

View File

@ -4,10 +4,10 @@ from __future__ import division
import ox
from ox.utils import json
from ox.django.api import actions
from ox.django.decorators import login_required_json
from ox.django.http import HttpFileResponse
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from oxdjango.api import actions
from oxdjango.decorators import login_required_json
from oxdjango.http import HttpFileResponse
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from django import forms
from django.conf import settings

View File

@ -3,7 +3,7 @@
import unicodedata
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals
from django.db import migrations, models
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -26,7 +26,7 @@ class Migration(migrations.Migration):
('name_sort', models.CharField(db_index=True, max_length=255, null=True)),
('name_find', models.TextField(default=b'')),
('wikipediaId', models.CharField(blank=True, max_length=1000)),
('alternativeNames', ox.django.fields.TupleField(default=[])),
('alternativeNames', oxdjango.fields.TupleField(default=[])),
('start', models.CharField(default=b'', max_length=255)),
('startTime', models.BigIntegerField(default=None, null=True)),
('end', models.CharField(default=b'', max_length=255)),

View File

@ -5,7 +5,7 @@ from __future__ import division, with_statement
from django.db import models, transaction
from django.contrib.auth.models import User
import ox
from ox.django import fields
from oxdjango import fields
from annotation.models import Annotation, get_matches, get_super_matches
from item.models import Item

View File

@ -7,10 +7,10 @@ from django.conf import settings
import ox
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
from changelog.models import add_changelog

View File

@ -12,7 +12,7 @@ from django.contrib.auth.models import Group
import models
import utils
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
def get_operator(op, type='str'):
return {

View File

@ -6,7 +6,7 @@ from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import item.models
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -62,9 +62,9 @@ class Migration(migrations.Migration):
('level', models.IntegerField(db_index=True)),
('public_id', models.CharField(blank=True, max_length=128, unique=True)),
('oxdbId', models.CharField(blank=True, max_length=42, null=True, unique=True)),
('external_data', ox.django.fields.DictField(default={}, editable=False)),
('data', ox.django.fields.DictField(default={}, editable=False)),
('json', ox.django.fields.DictField(default={}, editable=False)),
('external_data', oxdjango.fields.DictField(default={}, editable=False)),
('data', oxdjango.fields.DictField(default={}, editable=False)),
('json', oxdjango.fields.DictField(default={}, editable=False)),
('poster', models.ImageField(blank=True, default=None, upload_to=item.models.get_poster_path)),
('poster_source', models.TextField(blank=True)),
('poster_height', models.IntegerField(default=0)),
@ -72,7 +72,7 @@ class Migration(migrations.Migration):
('poster_frame', models.FloatField(default=-1)),
('icon', models.ImageField(blank=True, default=None, upload_to=item.models.get_icon_path)),
('torrent', models.FileField(blank=True, default=None, max_length=1000, upload_to=item.models.get_torrent_path)),
('stream_info', ox.django.fields.DictField(default={}, editable=False)),
('stream_info', oxdjango.fields.DictField(default={}, editable=False)),
('stream_aspect', models.FloatField(default=1.3333333333333333)),
],
),

View File

@ -22,7 +22,7 @@ from django.db.models.signals import pre_delete
from django.utils import datetime_safe
import ox
from ox.django import fields
from oxdjango import fields
import ox.web.imdb
import ox.image

View File

@ -18,9 +18,9 @@ from django.conf import settings
from ox.utils import json, ET
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.http import HttpFileResponse
import ox
import models
@ -33,7 +33,7 @@ from clip.models import Clip
from user.models import has_capability
from changelog.models import add_changelog
from ox.django.api import actions
from oxdjango.api import actions
def _order_query(qs, sort, prefix='sort__'):
@ -241,7 +241,7 @@ def find(request, data):
r = {}
if m:
if not isinstance(m, dict):
m = json.loads(m, object_hook=ox.django.fields.from_json)
m = json.loads(m, object_hook=oxdjango.fields.from_json)
for p in _p:
r[p] = m.get(p)
if 'clip_qs' in query:

View File

@ -3,7 +3,7 @@
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
def parseCondition(condition, user):
'''

View File

@ -6,7 +6,7 @@ from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import itemlist.models
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -27,13 +27,13 @@ class Migration(migrations.Migration):
('modified', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255)),
('status', models.CharField(default=b'private', max_length=20)),
('query', ox.django.fields.DictField(default={b'static': True})),
('query', oxdjango.fields.DictField(default={b'static': True})),
('type', models.CharField(default=b'static', max_length=255)),
('description', models.TextField(default=b'')),
('icon', models.ImageField(blank=True, default=None, upload_to=itemlist.models.get_icon_path)),
('view', models.TextField(default=itemlist.models.get_listview)),
('sort', ox.django.fields.TupleField(default=itemlist.models.get_listsort, editable=False)),
('poster_frames', ox.django.fields.TupleField(default=[], editable=False)),
('sort', oxdjango.fields.TupleField(default=itemlist.models.get_listsort, editable=False)),
('poster_frames', oxdjango.fields.TupleField(default=[], editable=False)),
('numberofitems', models.IntegerField(default=0)),
],
),

View File

@ -12,7 +12,7 @@ from django.contrib.auth.models import User
from django.conf import settings
import ox
from ox.django.fields import DictField, TupleField
from oxdjango.fields import DictField, TupleField
from archive import extract
import managers

View File

@ -8,13 +8,13 @@ from django.db.models import Max, Sum
from django.db import transaction
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.http import HttpFileResponse
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.http import HttpFileResponse
import models
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
from item.models import Item
from user.tasks import update_numberoflists

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -5,10 +5,10 @@ from __future__ import division
import ox
from ox.utils import json
from ox.django.decorators import admin_required_json
from ox.django.shortcuts import render_to_json_response, json_response
from oxdjango.decorators import admin_required_json
from oxdjango.shortcuts import render_to_json_response, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item import utils

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -4,11 +4,11 @@ from __future__ import division
import ox
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.api import actions
from oxdjango.api import actions
from changelog.models import add_changelog
import models

View File

View File

@ -0,0 +1 @@
from actions import actions

View File

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
import inspect
import sys
from django.conf import settings
from ..shortcuts import render_to_json_response, json_response
def autodiscover():
# Register api actions from all installed apps
from importlib import import_module
from django.utils.module_loading import module_has_submodule
for app in settings.INSTALLED_APPS:
if app != 'api':
mod = import_module(app)
try:
import_module('%s.views'%app)
except:
if module_has_submodule(mod, 'views'):
raise
def trim(docstring):
if not docstring:
return ''
# Convert tabs to spaces (following the normal Python rules)
# and split into a list of lines:
lines = docstring.expandtabs().splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxint
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Remove indentation (first line is special):
trimmed = [lines[0].strip()]
if indent < sys.maxint:
for line in lines[1:]:
trimmed.append(line[indent:].rstrip())
# Strip off trailing and leading blank lines:
while trimmed and not trimmed[-1]:
trimmed.pop()
while trimmed and not trimmed[0]:
trimmed.pop(0)
# Return a single string:
return '\n'.join(trimmed)
class ApiActions(dict):
properties = {}
versions = {}
def __init__(self):
def api(request, data):
'''
Returns a list of all api actions
takes {
code: boolean, // if true, return source code (optional)
docs: boolean // if true, return doc strings (optional)
}
returns {
actions: {
name: {
cache: boolean, // if false, don't cache results
code: string, // source code
doc: string // doc strings
},
... // more actions
}
}
'''
docs = data.get('docs', False)
code = data.get('code', False)
version = getattr(request, 'version', None)
if version:
_actions = self.versions.get(version, {}).keys()
_actions = list(set(_actions + self.keys()))
else:
_actions = self.keys()
_actions.sort()
actions = {}
for a in _actions:
actions[a] = self.properties[a]
if docs:
actions[a]['doc'] = self.doc(a, version)
if code:
actions[a]['code'] = self.code(a, version)
response = json_response({'actions': actions})
return render_to_json_response(response)
self.register(api)
def doc(self, name, version=None):
if version:
f = self.versions[version].get(name, self.get(name))
else:
f = self[name]
return trim(f.__doc__)
def code(self, name, version=None):
if version:
f = self.versions[version].get(name, self.get(name))
else:
f = self[name]
if name != 'api' and hasattr(f, 'func_closure') and f.func_closure:
fc = filter(lambda c: hasattr(c.cell_contents, '__call__'), f.func_closure)
f = fc[len(fc)-1].cell_contents
info = f.func_code.co_filename[len(settings.PROJECT_ROOT)+1:]
info = u'%s:%s' % (info, f.func_code.co_firstlineno)
return info, trim(inspect.getsource(f))
def register(self, method, action=None, cache=True, version=None):
if not action:
action = method.func_name
if version:
if not version in self.versions:
self.versions[version] = {}
self.versions[version][action] = method
else:
self[action] = method
self.properties[action] = {'cache': cache}
def unregister(self, action):
if action in self:
del self[action]
actions = ApiActions()
def error(request, data):
'''
This action is used to test API error codes. It should return a 503 error.
'''
success = error_is_success
return render_to_json_response({})
actions.register(error)

View File

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.conf.urls import url
import views
import actions
actions.autodiscover()
urlpatterns = [
url(r'^$', views.api),
]

View File

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
import json
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from ..shortcuts import render_to_json_response, json_response
from actions import actions
def api(request):
if request.META['REQUEST_METHOD'] == "OPTIONS":
response = render_to_json_response({'status': {'code': 200,
'text': 'use POST'}})
response['Access-Control-Allow-Origin'] = '*'
return response
if request.META['REQUEST_METHOD'] != "POST" or (
not 'action' in request.POST and request.META.get('CONTENT_TYPE') != 'application/json'
):
methods = actions.keys()
api = []
for f in sorted(methods):
api.append({'name': f,
'doc': actions.doc(f).replace('\n', '<br>\n')})
context = RequestContext(request, {
'api': api,
'settings': settings,
'sitename': settings.SITENAME
})
return render_to_response('api.html', context)
if request.META.get('CONTENT_TYPE') == 'application/json':
r = json.loads(request.body)
action = r['action']
data = r.get('data', {})
else:
action = request.POST['action']
data = json.loads(request.POST.get('data', '{}'))
version = getattr(request, 'version', None)
if version:
f = actions.versions.get(version, {}).get(action, actions.get(action))
else:
f = actions.get(action)
if f:
response = f(request, data)
else:
response = render_to_json_response(json_response(status=400,
text='Unknown action %s' % action))
response['Access-Control-Allow-Origin'] = '*'
return response

View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
try:
from django.contrib.auth.decorators import wraps
except:
from django.utils.functional import wraps
from shortcuts import render_to_json_response
def login_required_json(function=None):
"""
Decorator for views that checks that the user is logged in
return json error if not logged in.
"""
def _wrapped_view(request, *args, **kwargs):
if request.user.is_authenticated():
return function(request, *args, **kwargs)
return render_to_json_response({'status': {'code': 401, 'text': 'login required'}})
return wraps(function)(_wrapped_view)
def admin_required_json(function=None):
"""
Decorator for views that checks that the user is logged in
return json error if not logged in.
"""
def _wrapped_view(request, *args, **kwargs):
if request.user.is_authenticated() and request.user.profile.get_level() == 'admin':
return function(request, *args, **kwargs)
return render_to_json_response({'status': {'code': 403, 'text': 'permission denied'}})
return wraps(function)(_wrapped_view)

View File

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import time
import datetime
import copy
from django.db import models
from django.utils import datetime_safe
from six import string_types
from ox.utils import json
def to_json(python_object):
if isinstance(python_object, datetime.datetime):
if python_object.year < 1900:
tt = python_object.timetuple()
value = '%d-%02d-%02dT%02d:%02d%02dZ' % tuple(list(tt)[:6])
else:
value = python_object.strftime('%Y-%m-%dT%H:%M:%SZ')
return {'__class__': 'datetime.datetime',
'__value__': value}
if isinstance(python_object, datetime_safe.datetime):
return {'__class__': 'datetime.datetime',
'__value__': python_object.strftime('%Y-%m-%dT%H:%M:%SZ')}
if isinstance(python_object, time.struct_time):
return {'__class__': 'time.asctime',
'__value__': time.asctime(python_object)}
try:
if isinstance(python_object, bytes):
return {'__class__': 'bytes',
'__value__': list(python_object)}
except:
pass
raise TypeError(repr(python_object) + ' is not JSON serializable')
def from_json(json_object):
if '__class__' in json_object:
if json_object['__class__'] == 'bytes':
return bytes(json_object['__value__'])
if json_object['__class__'] == 'datetime_safe.datetime' \
or json_object['__class__'] == 'datetime.datetime':
return datetime_safe.datetime.strptime(json_object['__value__'], '%Y-%m-%dT%H:%M:%SZ')
if json_object['__class__'] == 'time.asctime':
return time.strptime(json_object['__value__'])
return json_object
class DictField(models.TextField):
_type = dict
def loads(self, value):
return json.loads(value, object_hook=from_json)
def dumps(self, obj):
return json.dumps(obj, default=to_json, ensure_ascii=False)
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
if isinstance(value, self._type):
return value
try:
value = self.loads(value)
except:
raise Exception('failed to parse value: %s' % value)
if value is not None:
assert isinstance(value, self._type)
return value
def get_prep_value(self, value):
if isinstance(value, self._type):
value = self.dumps(value)
if value is not None:
assert isinstance(value, string_types)
value = models.TextField.get_prep_value(self, value)
return value
def get_default(self):
if self.has_default():
if callable(self.default):
return self.default()
return copy.deepcopy(self.default)
return super(DictField, self).get_default()
class TupleField(DictField):
_type = (tuple, list)
def loads(self, value):
value = DictField.loads(self, value)
if isinstance(value, list):
value = tuple(value)
return value
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^oxdjango\.fields\.DictField"])
add_introspection_rules([], ["^oxdjango\.fields\.TupleField"])
except:
pass

58
pandora/oxdjango/http.py Normal file
View File

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import os
import mimetypes
from datetime import datetime, timedelta
from six.moves.urllib.parse import quote
from django.http import HttpResponse, Http404
from django.conf import settings
def HttpFileResponse(path, content_type=None, filename=None):
if not os.path.exists(path):
raise Http404
if not content_type:
content_type = mimetypes.guess_type(path)[0]
if not content_type:
content_type = 'application/octet-stream'
if getattr(settings, 'XACCELREDIRECT', False):
response = HttpResponse()
response['Content-Length'] = os.stat(path).st_size
for PREFIX in ('STATIC', 'MEDIA'):
root = getattr(settings, PREFIX+'_ROOT', '')
url = getattr(settings, PREFIX+'_URL', '')
if root and path.startswith(root):
path = url + path[len(root)+1:]
if not isinstance(path, bytes):
path = path.encode('utf-8')
response['X-Accel-Redirect'] = path
if content_type:
response['Content-Type'] = content_type
elif getattr(settings, 'XSENDFILE', False):
response = HttpResponse()
if not isinstance(path, bytes):
path = path.encode('utf-8')
response['X-Sendfile'] = path
if content_type:
response['Content-Type'] = content_type
response['Content-Length'] = os.stat(path).st_size
else:
response = HttpResponse(open(path), content_type=content_type)
if filename:
if not isinstance(filename, bytes):
filename = filename.encode('utf-8')
response['Content-Disposition'] = "attachment; filename*=UTF=8''%s" % quote(filename)
response['Expires'] = datetime.strftime(datetime.utcnow() + timedelta(days=1), "%a, %d-%b-%Y %H:%M:%S GMT")
def allow_access():
for key in ('X-Accel-Redirect', 'X-Sendfile'):
if key in response:
del response[key]
response['Access-Control-Allow-Origin'] = '*'
response.allow_access = allow_access
return response

View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from .shortcuts import HttpErrorJson, render_to_json_response
class ExceptionMiddleware(object):
def process_exception(self, request, exception):
if isinstance(exception, HttpErrorJson):
return render_to_json_response(exception.response)
return None
class ChromeFrameMiddleware(object):
def process_response(self, request, response):
response['X-UA-Compatible'] = 'chrome=1'
return response

58
pandora/oxdjango/query.py Normal file
View File

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models.sql import Query
from django.db.models.sql.compiler import SQLCompiler
from django.db import connections
import django.db.models.query
'''
models.py:
-----------------------------------
from oxdjango.query import QuerySet
class Manager(models.Manager):
def get_query_set(self):
return QuerySet(self.model)
class Model(models.Model):
...
objects = Manager()
'''
class NullLastSQLCompiler(SQLCompiler):
def get_order_by(self):
result = super(NullLastSQLCompiler, self).get_order_by()
if self.query.nulls_last and result \
and self.connection.vendor == 'postgresql':
return [(expr, (sql + ' NULLS LAST', params, is_ref))
for (expr, (sql, params, is_ref)) in result]
return result
class NullsLastQuery(Query):
nulls_last = False
def clone(self, *args, **kwargs):
obj = super(NullsLastQuery, self).clone(*args, **kwargs)
obj.nulls_last = self.nulls_last
return obj
def get_compiler(self, using=None, connection=None):
if using is None and connection is None:
raise ValueError("Need either using or connection")
if using:
connection = connections[using]
return NullLastSQLCompiler(self, connection, using)
class QuerySet(django.db.models.query.QuerySet):
def __init__(self, model=None, query=None, using=None, **kwargs):
super(QuerySet, self).__init__(model=model, query=query, using=None, **kwargs)
self.query = query or NullsLastQuery(self.model)
def order_by(self, *args, **kwargs):
nulls_last = kwargs.pop('nulls_last', False)
obj = super(QuerySet, self).order_by(*args, **kwargs)
obj.query.nulls_last = nulls_last
return obj

View File

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import print_function
import datetime
from django.utils import datetime_safe
from django.http import HttpResponse, Http404
import json
from django.conf import settings
class HttpErrorJson(Http404):
def __init__(self, response):
self.response = response
def json_response(data=None, status=200, text='ok'):
if not data:
data = {}
return {'status': {'code': status, 'text': text}, 'data': data}
def _to_json(python_object):
if isinstance(python_object, datetime.datetime):
if python_object.year < 1900:
tt = python_object.timetuple()
return '%d-%02d-%02dT%02d:%02d%02dZ' % tuple(list(tt)[:6])
return python_object.strftime('%Y-%m-%dT%H:%M:%SZ')
if isinstance(python_object, datetime_safe.datetime):
return python_object.strftime('%Y-%m-%dT%H:%M:%SZ')
raise TypeError(u'%s %s is not JSON serializable' % (repr(python_object), type(python_object)))
def render_to_json_response(dictionary, content_type="text/json", status=200):
indent=None
if settings.DEBUG:
content_type = "text/javascript"
indent = 2
if getattr(settings, 'JSON_DEBUG', False):
print(json.dumps(dictionary, indent=2, default=_to_json, ensure_ascii=False).encode('utf-8'))
return HttpResponse(json.dumps(dictionary, indent=indent, default=_to_json,
ensure_ascii=False).encode('utf-8'), content_type=content_type, status=status)
def get_object_or_404_json(klass, *args, **kwargs):
from django.shortcuts import _get_queryset
queryset = _get_queryset(klass)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
response = {'status': {'code': 404,
'text': '%s not found' % queryset.model._meta.object_name}}
raise HttpErrorJson(response)

47
pandora/oxdjango/utils.py Normal file
View File

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.http import HttpResponse,Http404
from django.core.servers.basehttp import FileWrapper
from django.conf import settings
import mimetypes
import os
def basic_sendfile(fname,download_name=None):
if not os.path.exists(fname):
raise Http404
wrapper = FileWrapper(open(fname,"r"))
content_type = mimetypes.guess_type(fname)[0]
response = HttpResponse(wrapper, content_type=content_type)
response['Content-Length'] = os.path.getsize(fname)
if download_name:
response['Content-Disposition'] = "attachment; filename=%s"%download_name
return response
def x_sendfile(fname,download_name=None):
if not os.path.exists(fname):
raise Http404
content_type = mimetypes.guess_type(fname)[0]
response = HttpResponse('', content_type=content_type)
response['Content-Length'] = os.path.getsize(fname)
response['X-Sendfile'] = fname
if download_name:
response['Content-Disposition'] = "attachment; filename=%s"%download_name
return response
try:
__sendfile = getattr(settings,'SENDFILE',False) == 'x_sendfile'
except:
__sendfile = False
if __sendfile == 'x_sendfile':
sendfile = x_sendfile
else:
sendfile = basic_sendfile

View File

@ -3,7 +3,7 @@
import unicodedata
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals
from django.db import migrations, models
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
('sortsortname', models.CharField(max_length=200)),
('edited', models.BooleanField(default=False)),
('numberofnames', models.IntegerField(default=0)),
('aliases', ox.django.fields.TupleField(default=[])),
('aliases', oxdjango.fields.TupleField(default=[])),
('imdbId', models.CharField(blank=True, max_length=7)),
('wikipediaId', models.CharField(blank=True, max_length=1000)),
],

View File

@ -6,7 +6,7 @@ import unicodedata
from django.db import models
from ox.django import fields
from oxdjango import fields
import ox
from item import utils

View File

@ -5,10 +5,10 @@ from __future__ import division
import ox
from ox.utils import json
from ox.django.decorators import admin_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.decorators import admin_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
import models

View File

@ -3,7 +3,7 @@
import unicodedata
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -27,7 +27,7 @@ class Migration(migrations.Migration):
('modified', models.DateTimeField(auto_now=True)),
('defined', models.BooleanField(default=True)),
('name', models.CharField(max_length=1024)),
('alternativeNames', ox.django.fields.TupleField(default=[])),
('alternativeNames', oxdjango.fields.TupleField(default=[])),
('name_sort', models.CharField(db_index=True, max_length=200)),
('name_find', models.TextField(default=b'', editable=False)),
('geoname', models.CharField(max_length=1024, null=True)),

View File

@ -5,7 +5,7 @@ from __future__ import division, with_statement
from django.db import models, transaction
from django.contrib.auth.models import User
import ox
from ox.django import fields
from oxdjango import fields
import managers
from annotation.models import Annotation, get_matches, get_super_matches

View File

@ -8,10 +8,10 @@ from django.conf import settings
import ox
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
from changelog.models import add_changelog

View File

@ -2,7 +2,7 @@
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -3,9 +3,9 @@
from __future__ import division
from ox.utils import json
from ox.django.shortcuts import render_to_json_response, json_response
from oxdjango.shortcuts import render_to_json_response, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item.models import Item
from item import utils

View File

@ -97,8 +97,8 @@ MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'ox.django.middleware.ExceptionMiddleware',
'ox.django.middleware.ChromeFrameMiddleware',
'oxdjango.middleware.ExceptionMiddleware',
'oxdjango.middleware.ChromeFrameMiddleware',
'user.middleware.UpdateSession',
)

View File

@ -2,7 +2,7 @@
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
def parseCondition(condition, user):
'''

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import ox.django.fields
import oxdjango.fields
import text.models
@ -39,8 +39,8 @@ class Migration(migrations.Migration):
('rightslevel', models.IntegerField(db_index=True, default=0)),
('icon', models.ImageField(blank=True, default=None, upload_to=text.models.get_icon_path)),
('text', models.TextField(default=b'')),
('embeds', ox.django.fields.TupleField(default=[])),
('poster_frames', ox.django.fields.TupleField(default=[], editable=False)),
('embeds', oxdjango.fields.TupleField(default=[])),
('poster_frames', oxdjango.fields.TupleField(default=[], editable=False)),
('uploading', models.BooleanField(default=False)),
('file', models.FileField(blank=True, default=None, null=True, upload_to=text.models.get_path)),
('subscribed_users', models.ManyToManyField(related_name='subscribed_texts', to=settings.AUTH_USER_MODEL)),

View File

@ -13,7 +13,7 @@ from django.contrib.auth.models import User
from django.conf import settings
from django.db.models.signals import pre_delete
import ox
from ox.django.fields import TupleField
from oxdjango.fields import TupleField
from archive import extract
from archive.chunk import save_chunk

View File

@ -6,10 +6,10 @@ import re
import ox
from ox.utils import json
from ox.django.api import actions
from ox.django.decorators import login_required_json
from ox.django.http import HttpFileResponse
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.api import actions
from oxdjango.decorators import login_required_json
from oxdjango.http import HttpFileResponse
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from django import forms
from django.db.models import Sum, Max
from django.conf import settings

View File

@ -2,7 +2,7 @@
# vi:si:et:sw=4:sts=4:ts=4
import unicodedata
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from item.utils import decode_id

View File

@ -6,10 +6,10 @@ import unicodedata
import ox
from ox.utils import json
from ox.django.decorators import admin_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from oxdjango.decorators import admin_required_json
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
from ox.django.api import actions
from oxdjango.api import actions
from item import utils
from user.decorators import capability_required_json
from changelog.models import add_changelog

View File

@ -4,10 +4,10 @@ from __future__ import division
import models
from ox.utils import json
from ox.django.shortcuts import render_to_json_response, json_response
from oxdjango.shortcuts import render_to_json_response, json_response
from itemlist.views import get_list_or_404_json
from ox.django.api import actions
from oxdjango.api import actions
def tv(request, data):
'''

View File

@ -3,7 +3,7 @@
import os
from django.conf.urls import url, include
from ox.django.http import HttpFileResponse
from oxdjango.http import HttpFileResponse
from django.conf import settings
import django.views
@ -14,7 +14,7 @@ admin.autodiscover()
import app.monkey_patch
import ox.django.api.urls
import oxdjango.api.urls
import app.views
import archive.views
@ -40,7 +40,7 @@ urlpatterns = [
url(r'^api/upload/?$', archive.views.firefogg_upload),
url(r'^url=(?P<url>.*)$', app.views.redirect_url),
url(r'^file/(?P<oshash>.*)$', archive.views.lookup_file),
url(r'^api/?', include(ox.django.api.urls)),
url(r'^api/?', include(oxdjango.api.urls)),
url(r'^resetUI$', user.views.reset_ui),
url(r'^documents/(?P<id>[A-Z0-9]+)/(?P<size>\d*)p(?P<page>[\d,]*).jpg$', document.views.thumbnail),
url(r'^documents/(?P<id>[A-Z0-9]+)/(?P<name>.*?\.[^\d]{3})$', document.views.file),

View File

@ -4,7 +4,7 @@ try:
from django.contrib.auth.decorators import wraps
except:
from django.utils.functional import wraps
from ox.django.shortcuts import render_to_json_response, json_response
from oxdjango.shortcuts import render_to_json_response, json_response
def capability_required_json(capability):
def capability_required(function=None):

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from django.db.models import Q, Manager
from ox.django.query import QuerySet
from oxdjango.query import QuerySet
from django.conf import settings
def parseCondition(condition, user):

View File

@ -6,7 +6,7 @@ import datetime
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import ox.django.fields
import oxdjango.fields
class Migration(migrations.Migration):
@ -31,7 +31,7 @@ class Migration(migrations.Migration):
('useragent', models.CharField(max_length=4096, null=True)),
('windowsize', models.CharField(max_length=255, null=True)),
('screensize', models.CharField(max_length=255, null=True)),
('info', ox.django.fields.DictField(default={})),
('info', oxdjango.fields.DictField(default={})),
('location', models.CharField(max_length=255, null=True)),
('location_sort', models.CharField(max_length=255, null=True)),
('system', models.CharField(max_length=255, null=True)),
@ -49,8 +49,8 @@ class Migration(migrations.Migration):
('level', models.IntegerField(default=1)),
('files_updated', models.DateTimeField(default=datetime.datetime.now)),
('newsletter', models.BooleanField(default=True)),
('ui', ox.django.fields.DictField(default={})),
('preferences', ox.django.fields.DictField(default={})),
('ui', oxdjango.fields.DictField(default={})),
('preferences', oxdjango.fields.DictField(default={})),
('notes', models.TextField(default=b'')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, unique=True)),
],

View File

@ -11,7 +11,7 @@ from django.contrib.gis.geoip import GeoIP
import ox
from ox.django.fields import DictField
from oxdjango.fields import DictField
from ox.utils import json
from itemlist.models import List, Position

View File

@ -15,12 +15,12 @@ from django.db.models import Max
from django.contrib.auth.models import User, Group
from django.contrib.sessions.models import Session
from ox.django.shortcuts import render_to_json_response, json_response, get_object_or_404_json
from ox.django.decorators import login_required_json
from oxdjango.shortcuts import render_to_json_response, json_response, get_object_or_404_json
from oxdjango.decorators import login_required_json
import ox
from ox.django.api import actions
from oxdjango.api import actions
from item.models import Access, Item
from item import utils
from changelog.models import add_changelog