drop python2 support, upgrade to django 3

This commit is contained in:
j 2020-05-29 00:20:18 +02:00
parent 80390a1f9b
commit 844382b1e8
124 changed files with 413 additions and 563 deletions

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model

View File

@ -158,7 +158,7 @@ class AnnotationManager(Manager):
#anonymous can only see public items #anonymous can only see public items
public_layers = self.model.public_layers() public_layers = self.model.public_layers()
if user.is_anonymous(): if user.is_anonymous:
qs = qs.filter(layer__in=public_layers) qs = qs.filter(layer__in=public_layers)
#users can see public and own #users can see public and own
else: else:

View File

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import re import re
import unicodedata import unicodedata
from django.utils.encoding import python_2_unicode_compatible
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Q from django.db.models import Q
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -83,16 +81,15 @@ def get_matches(obj, model, layer_type, qs=None):
matches = [-1] matches = [-1]
return Annotation.objects.filter(id__in=matches) return Annotation.objects.filter(id__in=matches)
@python_2_unicode_compatible
class Annotation(models.Model): class Annotation(models.Model):
objects = managers.AnnotationManager() objects = managers.AnnotationManager()
#FIXME: here having a item,start index would be good #FIXME: here having a item,start index would be good
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, related_name='annotations') user = models.ForeignKey(User, related_name='annotations', on_delete=models.CASCADE)
item = models.ForeignKey('item.Item', related_name='annotations') item = models.ForeignKey('item.Item', related_name='annotations', on_delete=models.CASCADE)
clip = models.ForeignKey('clip.Clip', null=True, related_name='annotations') clip = models.ForeignKey('clip.Clip', null=True, related_name='annotations', on_delete=models.CASCADE)
public_id = models.CharField(max_length=128, unique=True) public_id = models.CharField(max_length=128, unique=True)
#seconds #seconds
@ -107,7 +104,7 @@ class Annotation(models.Model):
languages = models.CharField(max_length=255, null=True, blank=True) languages = models.CharField(max_length=255, null=True, blank=True)
def editable(self, user): def editable(self, user):
if user.is_authenticated(): if user.is_authenticated:
if user.profile.capability('canEditAnnotations') or \ if user.profile.capability('canEditAnnotations') or \
self.user == user or \ self.user == user or \
user.groups.filter(id__in=self.item.groups.all()).count() > 0: user.groups.filter(id__in=self.item.groups.all()).count() > 0:
@ -400,7 +397,7 @@ class Annotation(models.Model):
return j return j
def __str__(self): def __str__(self):
return u"%s %s-%s" % (self.public_id, self.start, self.end) return "%s %s-%s" % (self.public_id, self.start, self.end)
def cleanup_related(sender, **kwargs): def cleanup_related(sender, **kwargs):
kwargs['instance'].cleanup_undefined_relations() kwargs['instance'].cleanup_undefined_relations()

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.conf import settings from django.conf import settings
from django.db.models import Count, Sum, F, Value from django.db.models import Count, Sum, F, Value

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import codecs import codecs
import os import os
@ -38,7 +37,7 @@ def get_version():
version = settings.VERSION_EPOCH + version version = settings.VERSION_EPOCH + version
return version return version
else: else:
return u'unknown' return 'unknown'
def load_config(init=False): def load_config(init=False):
with open(settings.SITE_CONFIG) as f: with open(settings.SITE_CONFIG) as f:

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import re import re
import ox.jsonc import ox.jsonc

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings from django.conf import settings

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection from django.db import connection

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings from django.conf import settings
from ... import documentation from ... import documentation

View File

@ -1,16 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import json import json
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from . import monkey_patch from . import monkey_patch
from . import tasks from . import tasks
@python_2_unicode_compatible
class Page(models.Model): class Page(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
@ -20,7 +17,6 @@ class Page(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
@python_2_unicode_compatible
class Settings(models.Model): class Settings(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group from django.contrib.auth.models import Group

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import datetime import datetime

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import copy import copy
from datetime import datetime from datetime import datetime

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import json import json
import subprocess import subprocess

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
from os.path import exists from os.path import exists

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings from django.conf import settings

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import os import os
import re import re

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings from django.conf import settings

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import json import json
import os.path import os.path
@ -12,7 +11,6 @@ from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db import models from django.db import models
from django.db.models.signals import pre_delete from django.db.models.signals import pre_delete
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
from oxdjango import fields from oxdjango import fields
@ -36,7 +34,6 @@ if not PY2:
def data_path(f, x): def data_path(f, x):
return f.get_path('data.bin') return f.get_path('data.bin')
@python_2_unicode_compatible
class File(models.Model): class File(models.Model):
AV_INFO = ( AV_INFO = (
'duration', 'video', 'audio', 'oshash', 'size', 'duration', 'video', 'audio', 'oshash', 'size',
@ -55,7 +52,7 @@ class File(models.Model):
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
oshash = models.CharField(max_length=16, unique=True) oshash = models.CharField(max_length=16, unique=True)
item = models.ForeignKey("item.Item", related_name='files', null=True) item = models.ForeignKey("item.Item", related_name='files', null=True, on_delete=models.CASCADE)
path = models.CharField(max_length=2048, default="") # canoncial path/file path = models.CharField(max_length=2048, default="") # canoncial path/file
sort_path = models.CharField(max_length=2048, default="") # sort name sort_path = models.CharField(max_length=2048, default="") # sort name
@ -483,7 +480,7 @@ class File(models.Model):
if k not in keys: if k not in keys:
del data[k] del data[k]
can_see_media = False can_see_media = False
if user and not user.is_anonymous(): if user and not user.is_anonymous:
can_see_media = user.profile.capability('canSeeMedia') or \ can_see_media = user.profile.capability('canSeeMedia') or \
user.is_staff or \ user.is_staff or \
self.item.user == user or \ self.item.user == user or \
@ -598,15 +595,15 @@ class File(models.Model):
status = {} status = {}
if self.encoding: if self.encoding:
for s in self.streams.all(): for s in self.streams.all():
status[s.name()] = u'done' if s.available else u'encoding' status[s.name()] = 'done' if s.available else 'encoding'
config = settings.CONFIG['video'] config = settings.CONFIG['video']
max_resolution = self.streams.get(source=None).resolution max_resolution = self.streams.get(source=None).resolution
for resolution in sorted(config['resolutions'], reverse=True): for resolution in sorted(config['resolutions'], reverse=True):
if resolution <= max_resolution: if resolution <= max_resolution:
for f in config['formats']: for f in config['formats']:
name = u'%sp.%s' % (resolution, f) name = '%sp.%s' % (resolution, f)
if name not in status: if name not in status:
status[name] = u'queued' status[name] = 'queued'
return status return status
def delete_frames(self): def delete_frames(self):
@ -627,7 +624,6 @@ def delete_file(sender, **kwargs):
f.delete_files() f.delete_files()
pre_delete.connect(delete_file, sender=File) pre_delete.connect(delete_file, sender=File)
@python_2_unicode_compatible
class Volume(models.Model): class Volume(models.Model):
class Meta: class Meta:
@ -636,11 +632,11 @@ class Volume(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, related_name='volumes') user = models.ForeignKey(User, related_name='volumes', on_delete=models.CASCADE)
name = models.CharField(max_length=1024) name = models.CharField(max_length=1024)
def __str__(self): def __str__(self):
return u"%s's %s" % (self.user, self.name) return "%s's %s" % (self.user, self.name)
def json(self): def json(self):
return { return {
@ -652,7 +648,6 @@ class Volume(models.Model):
def inttime(): def inttime():
return int(time.time()) return int(time.time())
@python_2_unicode_compatible
class Instance(models.Model): class Instance(models.Model):
class Meta: class Meta:
@ -668,11 +663,11 @@ class Instance(models.Model):
path = models.CharField(max_length=2048) path = models.CharField(max_length=2048)
ignore = models.BooleanField(default=False) ignore = models.BooleanField(default=False)
file = models.ForeignKey(File, related_name='instances') file = models.ForeignKey(File, related_name='instances', on_delete=models.CASCADE)
volume = models.ForeignKey(Volume, related_name='files') volume = models.ForeignKey(Volume, related_name='files', on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return u"%s's %s <%s>" % (self.volume.user, self.path, self.file.oshash) return "%s's %s <%s>" % (self.volume.user, self.path, self.file.oshash)
@property @property
def public_id(self): def public_id(self):
@ -691,14 +686,13 @@ def frame_path(frame, name):
name = "%s%s" % (frame.position, ext) name = "%s%s" % (frame.position, ext)
return frame.file.get_path(name) return frame.file.get_path(name)
@python_2_unicode_compatible
class Frame(models.Model): class Frame(models.Model):
class Meta: class Meta:
unique_together = ("file", "position") unique_together = ("file", "position")
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
file = models.ForeignKey(File, related_name="frames") file = models.ForeignKey(File, related_name="frames", on_delete=models.CASCADE)
position = models.FloatField() position = models.FloatField()
frame = models.ImageField(default=None, null=True, upload_to=frame_path) frame = models.ImageField(default=None, null=True, upload_to=frame_path)
width = models.IntegerField(default=0) width = models.IntegerField(default=0)
@ -711,7 +705,7 @@ class Frame(models.Model):
super(Frame, self).save(*args, **kwargs) super(Frame, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
return u'%s/%s' % (self.file, self.position) return '%s/%s' % (self.file, self.position)
def delete_frame(sender, **kwargs): def delete_frame(sender, **kwargs):
f = kwargs['instance'] f = kwargs['instance']
@ -722,18 +716,17 @@ pre_delete.connect(delete_frame, sender=Frame)
def stream_path(f, x): def stream_path(f, x):
return f.path(x) return f.path(x)
@python_2_unicode_compatible
class Stream(models.Model): class Stream(models.Model):
class Meta: class Meta:
unique_together = ("file", "resolution", "format") unique_together = ("file", "resolution", "format")
file = models.ForeignKey(File, related_name='streams') file = models.ForeignKey(File, related_name='streams', on_delete=models.CASCADE)
resolution = models.IntegerField(default=96) resolution = models.IntegerField(default=96)
format = models.CharField(max_length=255, default='webm') format = models.CharField(max_length=255, default='webm')
media = models.FileField(default=None, blank=True, upload_to=stream_path) media = models.FileField(default=None, blank=True, upload_to=stream_path)
source = models.ForeignKey('Stream', related_name='derivatives', default=None, null=True) source = models.ForeignKey('Stream', related_name='derivatives', default=None, null=True, on_delete=models.CASCADE)
available = models.BooleanField(default=False) available = models.BooleanField(default=False)
oshash = models.CharField(max_length=16, null=True, db_index=True) oshash = models.CharField(max_length=16, null=True, db_index=True)
info = JSONField(default=dict, editable=False) info = JSONField(default=dict, editable=False)
@ -753,10 +746,10 @@ class Stream(models.Model):
return os.path.join(settings.MEDIA_ROOT, self.path(), 'timeline') return os.path.join(settings.MEDIA_ROOT, self.path(), 'timeline')
def name(self): def name(self):
return u"%sp.%s" % (self.resolution, self.format) return "%sp.%s" % (self.resolution, self.format)
def __str__(self): def __str__(self):
return u"%s/%s" % (self.file, self.name()) return "%s/%s" % (self.file, self.name())
def get(self, resolution, format): def get(self, resolution, format):
streams = [] streams = []

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function
from datetime import datetime from datetime import datetime
from time import time from time import time

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from glob import glob from glob import glob

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os.path import os.path
from datetime import datetime from datetime import datetime

View File

@ -1,11 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from datetime import datetime from datetime import datetime
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
import ox import ox
@ -19,14 +17,13 @@ User = get_user_model()
''' '''
FIXME: remove this table more migrate to new ChangeLog FIXME: remove this table more migrate to new ChangeLog
''' '''
@python_2_unicode_compatible
class Changelog(models.Model): class Changelog(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
type = models.CharField(max_length=255, db_index=True) type = models.CharField(max_length=255, db_index=True)
value = JSONField(default=dict, editable=False) value = JSONField(default=dict, editable=False)
def __str__(self): def __str__(self):
return u'%s %s' % (self.type, self.created) return '%s %s' % (self.type, self.created)
def json(self): def json(self):
return self.value return self.value
@ -50,19 +47,18 @@ def add_changelog(request, data, id=None):
'user': c.user.username, 'user': c.user.username,
}) })
@python_2_unicode_compatible
class Log(models.Model): class Log(models.Model):
action = models.CharField(max_length=255, db_index=True) action = models.CharField(max_length=255, db_index=True)
data = JSONField(default=dict, editable=False) data = JSONField(default=dict, editable=False)
created = models.DateTimeField(db_index=True) created = models.DateTimeField(db_index=True)
user = models.ForeignKey(User, null=True, related_name='changelog') user = models.ForeignKey(User, null=True, related_name='changelog', on_delete=models.CASCADE)
changeid = models.TextField() changeid = models.TextField()
objects = managers.LogManager() objects = managers.LogManager()
def __str__(self): def __str__(self):
return u'%s %s %s' % (self.created, self.action, self.changeid) return '%s %s %s' % (self.created, self.action, self.changeid)
def get_id(self): def get_id(self):
return ox.toAZ(self.id) return ox.toAZ(self.id)

View File

@ -1,4 +1,3 @@
from __future__ import print_function
import models import models
import item.models import item.models
@ -18,33 +17,33 @@ def recover_item(id):
created = old.value['created'] created = old.value['created']
i.user = user.models.User.objects.get(username=i.data['user']) i.user = user.models.User.objects.get(username=i.data['user'])
for key in [ for key in [
u'rendered', 'rendered',
u'random', 'random',
u'cuts', 'cuts',
u'duration', 'duration',
u'id', 'id',
u'size', 'size',
u'posterFrame', 'posterFrame',
u'parts', 'parts',
u'cutsperminute', 'cutsperminute',
u'hue', 'hue',
u'numberofcuts', 'numberofcuts',
u'durations', 'durations',
u'volume', 'volume',
u'user', 'user',
u'words', 'words',
u'videoRatio', 'videoRatio',
u'aspectratio', 'aspectratio',
u'bitrate', 'bitrate',
u'pixels', 'pixels',
u'created', 'created',
u'numberoffiles', 'numberoffiles',
u'modified', 'modified',
u'timesaccessed', 'timesaccessed',
u'accessed', 'accessed',
u'resolution', 'resolution',
u'wordsperminute', 'wordsperminute',
u'posterRatio' 'posterRatio'
]: ]:
if key in i.data: if key in i.data:
del i.data[key] del i.data[key]

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import ox import ox

View File

@ -215,7 +215,7 @@ class ClipManager(Manager):
for l in list(filter(lambda k: k in layer_ids, data['keys'])): for l in list(filter(lambda k: k in layer_ids, data['keys'])):
qs = qs.filter(**{l: True}) qs = qs.filter(**{l: True})
#anonymous can only see public clips #anonymous can only see public clips
if not user or user.is_anonymous(): if not user or user.is_anonymous:
allowed_level = settings.CONFIG['capabilities']['canSeeItem']['guest'] allowed_level = settings.CONFIG['capabilities']['canSeeItem']['guest']
qs = qs.filter(sort__rightslevel__lte=allowed_level) qs = qs.filter(sort__rightslevel__lte=allowed_level)
#users can see public clips, there own clips and clips of there groups #users can see public clips, there own clips and clips of there groups

View File

@ -1,9 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db import models from django.db import models
from django.conf import settings from django.conf import settings
from django.utils.encoding import python_2_unicode_compatible
import ox import ox
@ -15,7 +13,7 @@ from . import managers
def get_layers(item, interval=None, user=None): def get_layers(item, interval=None, user=None):
from annotation.models import Annotation from annotation.models import Annotation
if user and user.is_anonymous(): if user and user.is_anonymous:
user = None user = None
layers = {} layers = {}
@ -45,7 +43,6 @@ def get_layers(item, interval=None, user=None):
return layers return layers
@python_2_unicode_compatible
class MetaClip(object): class MetaClip(object):
def update_calculated_values(self): def update_calculated_values(self):
start = self.start start = self.start
@ -184,7 +181,7 @@ class MetaClip(object):
@property @property
def public_id(self): def public_id(self):
return u"%s/%0.03f-%0.03f" % (self.item.public_id, float(self.start), float(self.end)) return "%s/%0.03f-%0.03f" % (self.item.public_id, float(self.start), float(self.end))
def __str__(self): def __str__(self):
return self.public_id return self.public_id
@ -200,8 +197,8 @@ attrs = {
'modified': models.DateTimeField(auto_now=True), 'modified': models.DateTimeField(auto_now=True),
'aspect_ratio': models.FloatField(default=0), 'aspect_ratio': models.FloatField(default=0),
'item': models.ForeignKey('item.Item', related_name='clips'), 'item': models.ForeignKey('item.Item', related_name='clips', on_delete=models.CASCADE),
'sort': models.ForeignKey('item.ItemSort', related_name='matching_clips'), 'sort': models.ForeignKey('item.ItemSort', related_name='matching_clips', on_delete=models.CASCADE),
'user': models.IntegerField(db_index=True, null=True), 'user': models.IntegerField(db_index=True, null=True),
#seconds #seconds
@ -226,4 +223,4 @@ Clip = type('Clip', (MetaClip, models.Model), attrs)
class ClipRandom(models.Model): class ClipRandom(models.Model):
id = models.BigIntegerField(primary_key=True) id = models.BigIntegerField(primary_key=True)
clip = models.OneToOneField(Clip) clip = models.OneToOneField(Clip, on_delete=models.CASCADE)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.conf import settings from django.conf import settings
import ox import ox
@ -154,7 +153,7 @@ def findClips(request, data):
add_annotations(layer, aqs) add_annotations(layer, aqs)
elif 'position' in query: elif 'position' in query:
qs = order_query(qs, query['sort']) qs = order_query(qs, query['sort'])
ids = [u'%s/%0.03f-%0.03f' % (c['item__public_id'], c['start'], c['end']) ids = ['%s/%0.03f-%0.03f' % (c['item__public_id'], c['start'], c['end'])
for c in qs.values('item__public_id', 'start', 'end')] for c in qs.values('item__public_id', 'start', 'end')]
data['conditions'] = data['conditions'] + { data['conditions'] = data['conditions'] + {
'value': data['position'], 'value': data['position'],
@ -167,7 +166,7 @@ def findClips(request, data):
response['data']['position'] = utils.get_positions(ids, [qs[0].public_id])[0] response['data']['position'] = utils.get_positions(ids, [qs[0].public_id])[0]
elif 'positions' in data: elif 'positions' in data:
qs = order_query(qs, query['sort']) qs = order_query(qs, query['sort'])
ids = [u'%s/%0.03f-%0.03f' % (c['item__public_id'], c['start'], c['end']) ids = ['%s/%0.03f-%0.03f' % (c['item__public_id'], c['start'], c['end'])
for c in qs.values('item__public_id', 'start', 'end')] for c in qs.values('item__public_id', 'start', 'end')]
response['data']['positions'] = utils.get_positions(ids, data['positions']) response['data']['positions'] = utils.get_positions(ids, data['positions'])
else: else:

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -283,7 +283,7 @@ class DocumentManager(Manager):
qs = qs.distinct() qs = qs.distinct()
#anonymous can only see public items #anonymous can only see public items
if not user or user.is_anonymous(): if not user or user.is_anonymous:
level = 'guest' level = 'guest'
allowed_level = settings.CONFIG['capabilities']['canSeeDocument'][level] allowed_level = settings.CONFIG['capabilities']['canSeeDocument'][level]
qs = qs.filter(rightslevel__lte=allowed_level) qs = qs.filter(rightslevel__lte=allowed_level)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -13,7 +12,6 @@ from django.db.models import Q, Sum, Max
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db.models.signals import pre_delete from django.db.models.signals import pre_delete
from django.conf import settings from django.conf import settings
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
from PIL import Image from PIL import Image
@ -42,13 +40,12 @@ if not PY2:
def get_path(f, x): def get_path(f, x):
return f.path(x) return f.path(x)
@python_2_unicode_compatible
class Document(models.Model, FulltextMixin): class Document(models.Model, FulltextMixin):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, related_name='documents') user = models.ForeignKey(User, related_name='documents', on_delete=models.CASCADE)
groups = models.ManyToManyField(Group, blank=True, related_name='documents') groups = models.ManyToManyField(Group, blank=True, related_name='documents')
extension = models.CharField(max_length=255) extension = models.CharField(max_length=255)
@ -74,7 +71,7 @@ class Document(models.Model, FulltextMixin):
data = JSONField(default=dict, editable=False) data = JSONField(default=dict, editable=False)
def update_access(self, user): def update_access(self, user):
if not user.is_authenticated(): if not user.is_authenticated:
user = None user = None
access, created = Access.objects.get_or_create(document=self, user=user) access, created = Access.objects.get_or_create(document=self, user=user)
if not created: if not created:
@ -161,7 +158,7 @@ class Document(models.Model, FulltextMixin):
elif i not in ('*', 'dimensions') and i not in self.facet_keys: elif i not in ('*', 'dimensions') and i not in self.facet_keys:
value = data.get(i) value = data.get(i)
if isinstance(value, list): if isinstance(value, list):
value = u'\n'.join(value) value = '\n'.join(value)
save(i, value) save(i, value)
base_keys = ('id', 'size', 'dimensions', 'extension', 'matches') base_keys = ('id', 'size', 'dimensions', 'extension', 'matches')
@ -192,11 +189,11 @@ class Document(models.Model, FulltextMixin):
s.dimensions = ox.sort_string('%d' % prefix) + ox.sort_string('%d' % value) s.dimensions = ox.sort_string('%d' % prefix) + ox.sort_string('%d' % value)
def sortNames(values): def sortNames(values):
sort_value = u'' sort_value = ''
if values: if values:
sort_value = u'; '.join([get_name_sort(name) for name in values]) sort_value = '; '.join([get_name_sort(name) for name in values])
if not sort_value: if not sort_value:
sort_value = u'' sort_value = ''
return sort_value.lower() return sort_value.lower()
def set_value(s, name, value): def set_value(s, name, value):
@ -229,7 +226,7 @@ class Document(models.Model, FulltextMixin):
if isinstance(sort_type, list): if isinstance(sort_type, list):
sort_type = sort_type[0] sort_type = sort_type[0]
if sort_type == 'title': if sort_type == 'title':
value = self.get_value(source, u'Untitled') value = self.get_value(source, 'Untitled')
value = utils.sort_title(value)[:955] value = utils.sort_title(value)[:955]
set_value(s, name, value) set_value(s, name, value)
elif sort_type == 'person': elif sort_type == 'person':
@ -237,9 +234,9 @@ class Document(models.Model, FulltextMixin):
value = utils.sort_string(value)[:955] value = utils.sort_string(value)[:955]
set_value(s, name, value) set_value(s, name, value)
elif sort_type == 'string': elif sort_type == 'string':
value = self.get_value(source, u'') value = self.get_value(source, '')
if isinstance(value, list): if isinstance(value, list):
value = u','.join(value) value = ','.join(value)
if not isinstance(value, str): if not isinstance(value, str):
value = str(value) value = str(value)
value = utils.sort_string(value)[:955] value = utils.sort_string(value)[:955]
@ -319,7 +316,7 @@ class Document(models.Model, FulltextMixin):
return ox.toAZ(self.id) return ox.toAZ(self.id)
def access(self, user): def access(self, user):
if user.is_anonymous(): if user.is_anonymous:
level = 'guest' level = 'guest'
else: else:
level = user.profile.get_level() level = user.profile.get_level()
@ -332,7 +329,7 @@ class Document(models.Model, FulltextMixin):
return False return False
def editable(self, user, item=None): def editable(self, user, item=None):
if not user or user.is_anonymous(): if not user or user.is_anonymous:
return False return False
if self.user == user or \ if self.user == user or \
self.groups.filter(id__in=user.groups.all()).count() > 0 or \ self.groups.filter(id__in=user.groups.all()).count() > 0 or \
@ -693,8 +690,8 @@ class ItemProperties(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
item = models.ForeignKey(Item) item = models.ForeignKey(Item, on_delete=models.CASCADE)
document = models.ForeignKey(Document, related_name='descriptions') document = models.ForeignKey(Document, related_name='descriptions', on_delete=models.CASCADE)
description = models.TextField(default="") description = models.TextField(default="")
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
@ -709,14 +706,13 @@ class ItemProperties(models.Model):
super(ItemProperties, self).save(*args, **kwargs) super(ItemProperties, self).save(*args, **kwargs)
@python_2_unicode_compatible
class Access(models.Model): class Access(models.Model):
class Meta: class Meta:
unique_together = ("document", "user") unique_together = ("document", "user")
access = models.DateTimeField(auto_now=True) access = models.DateTimeField(auto_now=True)
document = models.ForeignKey(Document, related_name='accessed') document = models.ForeignKey(Document, related_name='accessed', on_delete=models.CASCADE)
user = models.ForeignKey(User, null=True, related_name='accessed_documents') user = models.ForeignKey(User, null=True, related_name='accessed_documents', on_delete=models.CASCADE)
accessed = models.IntegerField(default=0) accessed = models.IntegerField(default=0)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
@ -729,10 +725,9 @@ class Access(models.Model):
def __str__(self): def __str__(self):
if self.user: if self.user:
return u"%s/%s/%s" % (self.user, self.document, self.access) return "%s/%s/%s" % (self.user, self.document, self.access)
return u"%s/%s" % (self.item, self.access) return "%s/%s" % (self.item, self.access)
@python_2_unicode_compatible
class Facet(models.Model): class Facet(models.Model):
''' '''
used for keys that can have multiple values like people, languages etc. used for keys that can have multiple values like people, languages etc.
@ -743,13 +738,13 @@ class Facet(models.Model):
class Meta: class Meta:
unique_together = ("document", "key", "value") unique_together = ("document", "key", "value")
document = models.ForeignKey('Document', related_name='facets') document = models.ForeignKey('Document', related_name='facets', on_delete=models.CASCADE)
key = models.CharField(max_length=200, db_index=True) key = models.CharField(max_length=200, db_index=True)
value = models.CharField(max_length=1000, db_index=True) value = models.CharField(max_length=1000, db_index=True)
sortvalue = models.CharField(max_length=1000, db_index=True) sortvalue = models.CharField(max_length=1000, db_index=True)
def __str__(self): def __str__(self):
return u"%s=%s" % (self.key, self.value) return "%s=%s" % (self.key, self.value)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.sortvalue: if not self.sortvalue:
@ -768,18 +763,17 @@ for key in settings.CONFIG['itemKeys']:
if key.get('sortType') == 'person': if key.get('sortType') == 'person':
Document.person_keys.append(key['id']) Document.person_keys.append(key['id'])
@python_2_unicode_compatible
class Find(models.Model): class Find(models.Model):
class Meta: class Meta:
unique_together = ('document', 'key') unique_together = ('document', 'key')
document = models.ForeignKey('Document', related_name='find', db_index=True) document = models.ForeignKey('Document', related_name='find', db_index=True, on_delete=models.CASCADE)
key = models.CharField(max_length=200, db_index=True) key = models.CharField(max_length=200, db_index=True)
value = models.TextField(blank=True, db_index=settings.DB_GIN_TRGM) value = models.TextField(blank=True, db_index=settings.DB_GIN_TRGM)
def __str__(self): def __str__(self):
return u'%s=%s' % (self.key, self.value) return '%s=%s' % (self.key, self.value)
''' '''
Sort Sort
@ -787,7 +781,7 @@ table constructed based on info in settings.CONFIG['documentKeys']
''' '''
attrs = { attrs = {
'__module__': 'document.models', '__module__': 'document.models',
'document': models.OneToOneField('Document', related_name='sort', primary_key=True), 'document': models.OneToOneField('Document', related_name='sort', primary_key=True, on_delete=models.CASCADE),
'created': models.DateTimeField(null=True, blank=True, db_index=True), 'created': models.DateTimeField(null=True, blank=True, db_index=True),
} }
for key in list(filter(lambda k: k.get('sort', False) or k['type'] in ('integer', 'time', 'float', 'date', 'enum'), settings.CONFIG['documentKeys'])): for key in list(filter(lambda k: k.get('sort', False) or k['type'] in ('integer', 'time', 'float', 'date', 'enum'), settings.CONFIG['documentKeys'])):

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re

View File

@ -124,7 +124,7 @@ class CollectionManager(Manager):
if conditions: if conditions:
qs = qs.filter(conditions) qs = qs.filter(conditions)
if user.is_anonymous(): if user.is_anonymous:
qs = qs.filter(Q(status='public') | Q(status='featured')) qs = qs.filter(Q(status='public') | Q(status='featured'))
else: else:
qs = qs.filter(Q(status='public') | Q(status='featured') | Q(user=user)) qs = qs.filter(Q(status='public') | Q(status='featured') | Q(user=user))

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -10,7 +9,6 @@ from django.db import models
from django.db.models import Max from django.db.models import Max
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.conf import settings from django.conf import settings
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
import ox import ox
@ -36,7 +34,6 @@ def get_collectionview():
def get_collectionsort(): def get_collectionsort():
return tuple(settings.CONFIG['user']['ui']['collectionSort']) return tuple(settings.CONFIG['user']['ui']['collectionSort'])
@python_2_unicode_compatible
class Collection(models.Model): class Collection(models.Model):
class Meta: class Meta:
@ -44,7 +41,7 @@ class Collection(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, related_name='collections') user = models.ForeignKey(User, related_name='collections', on_delete=models.CASCADE)
groups = models.ManyToManyField(Group, blank=True, related_name='collections') groups = models.ManyToManyField(Group, blank=True, related_name='collections')
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
status = models.CharField(max_length=20, default='private') status = models.CharField(max_length=20, default='private')
@ -58,7 +55,7 @@ class Collection(models.Model):
view = models.TextField(default=get_collectionview) view = models.TextField(default=get_collectionview)
sort = JSONField(default=get_collectionsort, editable=False) sort = JSONField(default=get_collectionsort, editable=False)
poster_frames = JSONField(default=[], editable=False) poster_frames = JSONField(default=list, editable=False)
#is through table still required? #is through table still required?
documents = models.ManyToManyField('document.Document', related_name='collections', documents = models.ManyToManyField('document.Document', related_name='collections',
@ -117,13 +114,13 @@ class Collection(models.Model):
return self.get_id() return self.get_id()
def get_id(self): def get_id(self):
return u'%s:%s' % (self.user.username, self.name) return '%s:%s' % (self.user.username, self.name)
def accessible(self, user): def accessible(self, user):
return self.user == user or self.status in ('public', 'featured') return self.user == user or self.status in ('public', 'featured')
def editable(self, user): def editable(self, user):
if not user or user.is_anonymous(): if not user or user.is_anonymous:
return False return False
if self.user == user or \ if self.user == user or \
self.groups.filter(id__in=user.groups.all()).count() > 0 or \ self.groups.filter(id__in=user.groups.all()).count() > 0 or \
@ -251,7 +248,7 @@ class Collection(models.Model):
elif key == 'subscribers': elif key == 'subscribers':
response[key] = self.subscribed_users.all().count() response[key] = self.subscribed_users.all().count()
elif key == 'subscribed': elif key == 'subscribed':
if user and not user.is_anonymous(): if user and not user.is_anonymous:
response[key] = self.subscribed_users.filter(id=user.id).exists() response[key] = self.subscribed_users.filter(id=user.id).exists()
else: else:
response[key] = getattr(self, { response[key] = getattr(self, {
@ -318,28 +315,26 @@ class Collection(models.Model):
path = source path = source
return path return path
@python_2_unicode_compatible
class CollectionDocument(models.Model): class CollectionDocument(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
collection = models.ForeignKey(Collection) collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
document = models.ForeignKey('document.Document') document = models.ForeignKey('document.Document', on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return u'%s in %s' % (self.document, self.collection) return '%s in %s' % (self.document, self.collection)
@python_2_unicode_compatible
class Position(models.Model): class Position(models.Model):
class Meta: class Meta:
unique_together = ("user", "collection", "section") unique_together = ("user", "collection", "section")
collection = models.ForeignKey(Collection, related_name='position') collection = models.ForeignKey(Collection, related_name='position', on_delete=models.CASCADE)
user = models.ForeignKey(User, related_name='collection_positions') user = models.ForeignKey(User, related_name='collection_positions', on_delete=models.CASCADE)
section = models.CharField(max_length=255) section = models.CharField(max_length=255)
position = models.IntegerField(default=0) position = models.IntegerField(default=0)
def __str__(self): def __str__(self):
return u'%s/%s/%s' % (self.section, self.position, self.collection) return '%s/%s/%s' % (self.section, self.position, self.collection)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -75,7 +74,7 @@ def findCollections(request, data):
query = parse_query(data, request.user) query = parse_query(data, request.user)
#order #order
is_section_request = query['sort'] == [{u'operator': u'+', u'key': u'position'}] is_section_request = query['sort'] == [{'operator': '+', 'key': 'position'}]
def is_featured_condition(x): def is_featured_condition(x):
return x['key'] == 'status' and \ return x['key'] == 'status' and \
@ -89,7 +88,7 @@ def findCollections(request, data):
if is_section_request: if is_section_request:
qs = query['qs'] qs = query['qs']
if not is_featured and not request.user.is_anonymous(): if not is_featured and not request.user.is_anonymous:
qs = qs.filter(position__in=models.Position.objects.filter(user=request.user)) qs = qs.filter(position__in=models.Position.objects.filter(user=request.user))
qs = qs.order_by('position__position') qs = qs.order_by('position__position')
else: else:

View File

@ -124,7 +124,7 @@ class EditManager(Manager):
if conditions: if conditions:
qs = qs.filter(conditions) qs = qs.filter(conditions)
if user.is_anonymous(): if user.is_anonymous:
qs = qs.filter(Q(status='public') | Q(status='featured')) qs = qs.filter(Q(status='public') | Q(status='featured'))
else: else:
qs = qs.filter(Q(status='public') | Q(status='featured') | Q(user=user)) qs = qs.filter(Q(status='public') | Q(status='featured') | Q(user=user))

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import re import re
import os import os
@ -15,7 +14,6 @@ from django.db import models, transaction
from django.db.models import Max from django.db.models import Max
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
from annotation.models import Annotation from annotation.models import Annotation
@ -35,7 +33,6 @@ User = get_user_model()
def get_path(f, x): return f.path(x) def get_path(f, x): return f.path(x)
def get_icon_path(f, x): return get_path(f, 'icon.jpg') def get_icon_path(f, x): return get_path(f, 'icon.jpg')
@python_2_unicode_compatible
class Edit(models.Model): class Edit(models.Model):
class Meta: class Meta:
@ -45,7 +42,7 @@ class Edit(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, related_name='edits') user = models.ForeignKey(User, related_name='edits', on_delete=models.CASCADE)
groups = models.ManyToManyField(Group, blank=True, related_name='edits') groups = models.ManyToManyField(Group, blank=True, related_name='edits')
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
@ -59,11 +56,11 @@ class Edit(models.Model):
icon = models.ImageField(default=None, blank=True, null=True, upload_to=get_icon_path) icon = models.ImageField(default=None, blank=True, null=True, upload_to=get_icon_path)
poster_frames = JSONField(default=[], editable=False) poster_frames = JSONField(default=list, editable=False)
subscribed_users = models.ManyToManyField(User, related_name='subscribed_edits') subscribed_users = models.ManyToManyField(User, related_name='subscribed_edits')
def __str__(self): def __str__(self):
return u'%s (%s)' % (self.name, self.user) return '%s (%s)' % (self.name, self.user)
@classmethod @classmethod
def get(cls, id): def get(cls, id):
@ -73,7 +70,7 @@ class Edit(models.Model):
return cls.objects.get(user__username=username, name=name) return cls.objects.get(user__username=username, name=name)
def get_id(self): def get_id(self):
return u'%s:%s' % (self.user.username, self.name) return '%s:%s' % (self.user.username, self.name)
def get_absolute_url(self): def get_absolute_url(self):
return ('/edits/%s' % quote(self.get_id())).replace('%3A', ':') return ('/edits/%s' % quote(self.get_id())).replace('%3A', ':')
@ -137,7 +134,7 @@ class Edit(models.Model):
return self.user == user or self.status in ('public', 'featured') return self.user == user or self.status in ('public', 'featured')
def editable(self, user): def editable(self, user):
if not user or user.is_anonymous(): if not user or user.is_anonymous:
return False return False
if self.user == user or \ if self.user == user or \
self.groups.filter(id__in=user.groups.all()).count() > 0 or \ self.groups.filter(id__in=user.groups.all()).count() > 0 or \
@ -403,7 +400,7 @@ class Edit(models.Model):
elif key == 'subscribers': elif key == 'subscribers':
response[key] = self.subscribed_users.all().count() response[key] = self.subscribed_users.all().count()
elif key == 'subscribed': elif key == 'subscribed':
if user and not user.is_anonymous(): if user and not user.is_anonymous:
response[key] = self.subscribed_users.filter(id=user.id).exists() response[key] = self.subscribed_users.filter(id=user.id).exists()
elif hasattr(self, _map.get(key, key)): elif hasattr(self, _map.get(key, key)):
response[key] = getattr(self, _map.get(key, key)) response[key] = getattr(self, _map.get(key, key))
@ -430,15 +427,14 @@ class Edit(models.Model):
#p.wait() #p.wait()
shutil.rmtree(tmp) shutil.rmtree(tmp)
@python_2_unicode_compatible
class Clip(models.Model): class Clip(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
edit = models.ForeignKey(Edit, related_name='clips') edit = models.ForeignKey(Edit, related_name='clips', on_delete=models.CASCADE)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
item = models.ForeignKey(Item, null=True, default=None, related_name='editclip') item = models.ForeignKey(Item, null=True, default=None, related_name='editclip', on_delete=models.CASCADE)
annotation = models.ForeignKey(Annotation, null=True, default=None, related_name='editclip') annotation = models.ForeignKey(Annotation, null=True, default=None, related_name='editclip', on_delete=models.CASCADE)
start = models.FloatField(default=0) start = models.FloatField(default=0)
end = models.FloatField(default=0) end = models.FloatField(default=0)
duration = models.FloatField(default=0) duration = models.FloatField(default=0)
@ -454,8 +450,8 @@ class Clip(models.Model):
def __str__(self): def __str__(self):
if self.annotation: if self.annotation:
return u'%s' % self.annotation.public_id return '%s' % self.annotation.public_id
return u'%s/%0.3f-%0.3f' % (self.item.public_id, self.start, self.end) return '%s/%0.3f-%0.3f' % (self.item.public_id, self.start, self.end)
def get_id(self): def get_id(self):
return ox.toAZ(self.id) return ox.toAZ(self.id)
@ -541,17 +537,16 @@ class Clip(models.Model):
return clip.models.get_layers(item=item, interval=(start, end), user=user) return clip.models.get_layers(item=item, interval=(start, end), user=user)
@python_2_unicode_compatible
class Position(models.Model): class Position(models.Model):
class Meta: class Meta:
unique_together = ("user", "edit", "section") unique_together = ("user", "edit", "section")
edit = models.ForeignKey(Edit, related_name='position') edit = models.ForeignKey(Edit, related_name='position', on_delete=models.CASCADE)
user = models.ForeignKey(User, related_name='edit_position') user = models.ForeignKey(User, related_name='edit_position', on_delete=models.CASCADE)
section = models.CharField(max_length=255) section = models.CharField(max_length=255)
position = models.IntegerField(default=0) position = models.IntegerField(default=0)
def __str__(self): def __str__(self):
return u'%s/%s/%s' % (self.section, self.position, self.edit) return '%s/%s/%s' % (self.section, self.position, self.edit)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -404,7 +403,8 @@ def findEdits(request, data):
query = parse_query(data, request.user) query = parse_query(data, request.user)
#order #order
is_section_request = query['sort'] == [{u'operator': u'+', u'key': u'position'}] is_section_request = query['sort'] == [{'operator': '+', 'key': 'position'}]
def is_featured_condition(x): def is_featured_condition(x):
return x['key'] == 'status' and \ return x['key'] == 'status' and \
x['value'] == 'featured' and \ x['value'] == 'featured' and \
@ -414,7 +414,7 @@ def findEdits(request, data):
if is_section_request: if is_section_request:
qs = query['qs'] qs = query['qs']
if not is_featured and not request.user.is_anonymous(): if not is_featured and not request.user.is_anonymous:
qs = qs.filter(position__in=models.Position.objects.filter(user=request.user)) qs = qs.filter(position__in=models.Position.objects.filter(user=request.user))
qs = qs.order_by('position__position') qs = qs.order_by('position__position')
else: else:

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -14,7 +13,6 @@ from django.contrib.auth import get_user_model
from django.db.models.signals import pre_delete, post_init from django.db.models.signals import pre_delete, post_init
from django.conf import settings from django.conf import settings
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
import ox import ox
@ -28,7 +26,6 @@ from . import managers
User = get_user_model() User = get_user_model()
@python_2_unicode_compatible
class Entity(models.Model): class Entity(models.Model):
class ValueError(ValueError): class ValueError(ValueError):
'''Raised if a field name or value is invalid (based on the "entities" '''Raised if a field name or value is invalid (based on the "entities"
@ -38,7 +35,7 @@ class Entity(models.Model):
class Meta: class Meta:
unique_together = ("type", "name") unique_together = ("type", "name")
user = models.ForeignKey(User, related_name='entities', null=True, default=None) user = models.ForeignKey(User, related_name='entities', null=True, default=None, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
@ -64,7 +61,7 @@ class Entity(models.Model):
self.name = self.name.decode('utf-8') self.name = self.name.decode('utf-8')
self.name_sort = get_name_sort(self.name)[:255].lower() self.name_sort = get_name_sort(self.name)[:255].lower()
else: else:
self.name_sort = ox.sort_string(self.name or u'')[:255].lower() or None self.name_sort = ox.sort_string(self.name or '')[:255].lower() or None
self.name_find = '||' + '||'.join((self.name,) + self.alternativeNames) + '||' self.name_find = '||' + '||'.join((self.name,) + self.alternativeNames) + '||'
self.name_find = self.name_find.lower() self.name_find = self.name_find.lower()
super(Entity, self).save(*args, **kwargs) super(Entity, self).save(*args, **kwargs)
@ -88,11 +85,11 @@ class Entity(models.Model):
@classmethod @classmethod
def get_by_name(cls, name, type): def get_by_name(cls, name, type):
return cls.objects.get(name_find__contains=u'|%s|' % name.lower(), type=type) return cls.objects.get(name_find__contains='|%s|' % name.lower(), type=type)
@classmethod @classmethod
def get_or_create(model, name): def get_or_create(model, name):
qs = model.objects.filter(name_find__contains=u'|%s|' % name.lower()) qs = model.objects.filter(name_find__contains='|%s|' % name.lower())
if qs.count() == 0: if qs.count() == 0:
instance = model(name=name) instance = model(name=name)
instance.save() instance.save()
@ -117,7 +114,7 @@ class Entity(models.Model):
DocumentProperties.objects.filter(document=document, entity=self).delete() DocumentProperties.objects.filter(document=document, entity=self).delete()
def editable(self, user, item=None): def editable(self, user, item=None):
if not user or user.is_anonymous(): if not user or user.is_anonymous:
return False return False
if user.is_staff or \ if user.is_staff or \
user.profile.capability('canEditEntities') == True or \ user.profile.capability('canEditEntities') == True or \
@ -140,7 +137,7 @@ class Entity(models.Model):
data['name'] = "Unnamed" data['name'] = "Unnamed"
name = data['name'] name = data['name']
n = 1 n = 1
while Entity.objects.filter(name_find__contains=u'|%s|' % name.lower()).exclude(id=self.id).count() > 0: while Entity.objects.filter(name_find__contains='|%s|' % name.lower()).exclude(id=self.id).count() > 0:
n += 1 n += 1
name = data['name'] + ' [%d]' % n name = data['name'] + ' [%d]' % n
self.name = name self.name = name
@ -155,7 +152,7 @@ class Entity(models.Model):
name_ = name name_ = name
n = 1 n = 1
while name in used_names or \ while name in used_names or \
Entity.objects.filter(name_find__contains=u'|%s|' % name.lower()).exclude(id=self.id).count() > 0: Entity.objects.filter(name_find__contains='|%s|' % name.lower()).exclude(id=self.id).count() > 0:
n += 1 n += 1
name = name_ + ' [%d]' % n name = name_ + ' [%d]' % n
names.append(name) names.append(name)
@ -268,7 +265,7 @@ class Entity(models.Model):
return response return response
def annotation_value(self): def annotation_value(self):
#return u'<a href="/entities/%s">%s</a>' % (self.get_id(), ox.escape_html(self.name)) #return '<a href="/entities/%s">%s</a>' % (self.get_id(), ox.escape_html(self.name))
return ox.escape_html(self.name) return ox.escape_html(self.name)
def update_find(self): def update_find(self):
@ -292,10 +289,10 @@ class Entity(models.Model):
for key in entity['keys']: for key in entity['keys']:
value = self.data.get(key['id']) value = self.data.get(key['id'])
if isinstance(value, list): if isinstance(value, list):
value = u'\n'.join(value) value = '\n'.join(value)
save(key['id'], value) save(key['id'], value)
ids.append(key['id']) ids.append(key['id'])
save('name', u'\n'.join([self.name] + list(self.alternativeNames))) save('name', '\n'.join([self.name] + list(self.alternativeNames)))
self.find.exclude(key__in=ids).delete() self.find.exclude(key__in=ids).delete()
def update_matches(self): def update_matches(self):
@ -344,7 +341,6 @@ post_init.connect(
) )
@python_2_unicode_compatible
class DocumentProperties(models.Model): class DocumentProperties(models.Model):
class Meta: class Meta:
@ -353,42 +349,40 @@ class DocumentProperties(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
document = models.ForeignKey(Document, related_name='documentproperties') document = models.ForeignKey(Document, related_name='documentproperties', on_delete=models.CASCADE)
entity = models.ForeignKey(Entity, related_name='documentproperties') entity = models.ForeignKey(Entity, related_name='documentproperties', on_delete=models.CASCADE)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
data = JSONField(default=dict, editable=False) data = JSONField(default=dict, editable=False)
def __str__(self): def __str__(self):
return u"%r-%r" % (self.document, self.entity) return "%r-%r" % (self.document, self.entity)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(DocumentProperties, self).save(*args, **kwargs) super(DocumentProperties, self).save(*args, **kwargs)
@python_2_unicode_compatible
class Find(models.Model): class Find(models.Model):
class Meta: class Meta:
unique_together = ("entity", "key") unique_together = ("entity", "key")
entity = models.ForeignKey('Entity', related_name='find', db_index=True) entity = models.ForeignKey('Entity', related_name='find', db_index=True, on_delete=models.CASCADE)
key = models.CharField(max_length=200, db_index=True) key = models.CharField(max_length=200, db_index=True)
value = models.TextField(blank=True, db_index=settings.DB_GIN_TRGM) value = models.TextField(blank=True, db_index=settings.DB_GIN_TRGM)
def __str__(self): def __str__(self):
return u"%s=%s" % (self.key, self.value) return "%s=%s" % (self.key, self.value)
@python_2_unicode_compatible
class Link(models.Model): class Link(models.Model):
'''Models entity fields of type "entity".''' '''Models entity fields of type "entity".'''
class Meta: class Meta:
unique_together = ("source", "key", "target") unique_together = ("source", "key", "target")
source = models.ForeignKey(Entity, related_name='links') source = models.ForeignKey(Entity, related_name='links', on_delete=models.CASCADE)
key = models.CharField(max_length=200) key = models.CharField(max_length=200)
target = models.ForeignKey(Entity, related_name='backlinks') target = models.ForeignKey(Entity, related_name='backlinks', on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return u"%s-[%s]->%s" % (self.source, self.key, self.target) return "%s-[%s]->%s" % (self.source, self.key, self.target)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from six import string_types from six import string_types
import ox import ox
@ -60,7 +59,7 @@ def addEntity(request, data):
for name in names: for name in names:
name = ox.decode_html(name) name = ox.decode_html(name)
if models.Entity.objects.filter(type=data['type'], if models.Entity.objects.filter(type=data['type'],
name_find__icontains=u'|%s|'%name).count() != 0: name_find__icontains='|%s|'%name).count() != 0:
exists = True exists = True
existing_names.append(name) existing_names.append(name)
if not exists: if not exists:
@ -87,7 +86,7 @@ def addEntity(request, data):
type = data['type'] type = data['type']
name = 'Unnamed' name = 'Unnamed'
num = 1 num = 1
while models.Entity.objects.filter(name_find__icontains=u'|%s|'%name).count() > 0: while models.Entity.objects.filter(name_find__icontains='|%s|'%name).count() > 0:
num += 1 num += 1
name = 'Unnamed [%d]' % num name = 'Unnamed [%d]' % num
entity = models.Entity(name=name, type=type) entity = models.Entity(name=name, type=type)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db import models, transaction from django.db import models, transaction
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils.encoding import python_2_unicode_compatible
import ox import ox
from oxdjango import fields from oxdjango import fields
@ -19,7 +17,6 @@ from . import managers
User = get_user_model() User = get_user_model()
@python_2_unicode_compatible
class Event(models.Model): class Event(models.Model):
''' '''
Events are events in time that can be once or recurring, Events are events in time that can be once or recurring,
@ -33,7 +30,7 @@ class Event(models.Model):
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
defined = models.BooleanField(default=False) defined = models.BooleanField(default=False)
user = models.ForeignKey(User, null=True, related_name='events') user = models.ForeignKey(User, null=True, related_name='events', on_delete=models.CASCADE)
name = models.CharField(null=True, max_length=255, unique=True) name = models.CharField(null=True, max_length=255, unique=True)
name_sort = models.CharField(null=True, max_length=255, db_index=True) name_sort = models.CharField(null=True, max_length=255, db_index=True)
@ -66,7 +63,7 @@ class Event(models.Model):
@classmethod @classmethod
def get_or_create(model, name): def get_or_create(model, name):
qs = model.objects.filter(name_find__contains=u'|%s|' % name.lower()) qs = model.objects.filter(name_find__contains='|%s|' % name.lower())
if qs.count() == 0: if qs.count() == 0:
instance = model(name=name) instance = model(name=name)
instance.save() instance.save()
@ -75,7 +72,7 @@ class Event(models.Model):
return instance return instance
def editable(self, user): def editable(self, user):
if user and not user.is_anonymous() \ if user and not user.is_anonymous \
and (not self.user or \ and (not self.user or \
self.user == user or \ self.user == user or \
user.profile.capability('canEditEvents')): user.profile.capability('canEditEvents')):

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from celery.task import task from celery.task import task

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db.models import Count from django.db.models import Count
from django.conf import settings from django.conf import settings
@ -37,7 +36,7 @@ def addEvent(request, data):
for name in names: for name in names:
name = ox.decode_html(name) name = ox.decode_html(name)
if models.Event.objects.filter(defined=True, if models.Event.objects.filter(defined=True,
name_find__icontains=u'|%s|'%name).count() != 0: name_find__icontains='|%s|'%name).count() != 0:
exists = True exists = True
existing_names.append(name) existing_names.append(name)
if not exists: if not exists:
@ -93,7 +92,7 @@ def editEvent(request, data):
names = [data.get('name', event.name)] + data.get('alternativeNames', []) names = [data.get('name', event.name)] + data.get('alternativeNames', [])
for name in names: for name in names:
if models.Event.objects.filter(defined=True, if models.Event.objects.filter(defined=True,
name_find__icontains=u'|%s|'%name).exclude(id=event.id).count() != 0: name_find__icontains='|%s|'%name).exclude(id=event.id).count() != 0:
conflict = True conflict = True
conflict_names.append(name) conflict_names.append(name)
if not conflict: if not conflict:

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from six import string_types from six import string_types
from six.moves.urllib.parse import quote from six.moves.urllib.parse import quote
@ -7,7 +6,6 @@ from six.moves.urllib.parse import quote
from django.db import models from django.db import models
from django.db.models import Max from django.db.models import Max
from django.db.models.signals import pre_delete from django.db.models.signals import pre_delete
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
import ox import ox
@ -17,7 +15,6 @@ from edit.models import Edit
from documentcollection.models import Collection from documentcollection.models import Collection
@python_2_unicode_compatible
class Item(models.Model): class Item(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
@ -27,7 +24,7 @@ class Item(models.Model):
data = JSONField(default=dict, editable=False) data = JSONField(default=dict, editable=False)
def editable(self, user): def editable(self, user):
return user.is_authenticated() and user.profile.capability("canManageHome") return user.is_authenticated and user.profile.capability("canManageHome")
def edit(self, data): def edit(self, data):
changed = False changed = False
@ -153,7 +150,7 @@ class Item(models.Model):
return j return j
def __str__(self): def __str__(self):
return u"%s" % (self.get_id()) return "%s" % (self.get_id())
def delete_item(type, contentid): def delete_item(type, contentid):
for home in Item.objects.all(): for home in Item.objects.all():

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings from django.conf import settings

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import os import os
from glob import glob from glob import glob

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import time import time

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
@ -44,7 +43,13 @@ class Command(BaseCommand):
(document.models.Find._meta.db_table, 'value'), # Document Find (document.models.Find._meta.db_table, 'value'), # Document Find
): ):
cursor = connection.cursor() cursor = connection.cursor()
indexes = connection.introspection.get_indexes(cursor, table) contraints = connection.introspection.get_constraints(cursor, table)
indexes = {
','.join(c['columns']): {'primary_key': c['primary_key'], 'unique': c['unique']}
for k, c in contraints.items()
if c['index'] or c['primary_key'] or c['unique']
}
#indexes = connection.introspection.get_indexes(cursor, table)
drop = [] drop = []
if column in indexes: if column in indexes:
for sql in ( for sql in (

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import os import os
@ -38,10 +37,10 @@ class Command(BaseCommand):
versions = os.path.join(prefix, os.path.dirname(path), 'Versions') versions = os.path.join(prefix, os.path.dirname(path), 'Versions')
s = f.streams.filter(source=None)[0] s = f.streams.filter(source=None)[0]
basename = os.path.basename(path).rsplit('.', 1)[0] basename = os.path.basename(path).rsplit('.', 1)[0]
target = os.path.join(versions, u'%s.%s' % (basename, s.format)) target = os.path.join(versions, '%s.%s' % (basename, s.format))
link(s.media.path, target) link(s.media.path, target)
else: else:
s = f.streams.filter(source=None)[0] s = f.streams.filter(source=None)[0]
basename = path.rsplit('.', 1)[0] basename = path.rsplit('.', 1)[0]
target = os.path.join(prefix, u'%s.%s' % (basename, s.format)) target = os.path.join(prefix, '%s.%s' % (basename, s.format))
link(s.media.path, target) link(s.media.path, target)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from datetime import datetime from datetime import datetime
import unicodedata import unicodedata
@ -81,7 +80,7 @@ def parseCondition(condition, user, owner=None):
if (not exclude and op == '=' or op in ('$', '^')) and v == '': if (not exclude and op == '=' or op in ('$', '^')) and v == '':
return Q() return Q()
elif k == 'filename' and (user.is_anonymous() or not user.profile.capability('canSeeMedia')): elif k == 'filename' and (user.is_anonymous or not user.profile.capability('canSeeMedia')):
return Q(id=0) return Q(id=0)
elif k == 'oshash': elif k == 'oshash':
return Q(files__oshash=v) return Q(files__oshash=v)
@ -100,7 +99,7 @@ def parseCondition(condition, user, owner=None):
q = ~q q = ~q
return q return q
elif k in ('canplayvideo', 'canplayclips'): elif k in ('canplayvideo', 'canplayclips'):
level = user.is_anonymous() and 'guest' or user.profile.get_level() level = user.is_anonymous and 'guest' or user.profile.get_level()
allowed_level = settings.CONFIG['capabilities'][{ allowed_level = settings.CONFIG['capabilities'][{
'canplayvideo': 'canPlayVideo', 'canplayvideo': 'canPlayVideo',
'canplayclips': 'canPlayClips' 'canplayclips': 'canPlayClips'
@ -249,7 +248,7 @@ class ItemManager(Manager):
if l != "*": if l != "*":
l = l.split(":") l = l.split(":")
only_public = True only_public = True
if not user.is_anonymous(): if not user.is_anonymous:
if len(l) == 1: if len(l) == 1:
l = [user.username] + l l = [user.username] + l
if user.username == l[0]: if user.username == l[0]:
@ -305,7 +304,7 @@ class ItemManager(Manager):
qs = qs.distinct() qs = qs.distinct()
#anonymous can only see public items #anonymous can only see public items
if not user or user.is_anonymous(): if not user or user.is_anonymous:
level = 'guest' level = 'guest'
allowed_level = settings.CONFIG['capabilities']['canSeeItem'][level] allowed_level = settings.CONFIG['capabilities']['canSeeItem'][level]
qs = qs.filter(level__lte=allowed_level) qs = qs.filter(level__lte=allowed_level)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import json import json
import os import os
@ -21,7 +20,6 @@ from django.core.files.temp import NamedTemporaryFile
from django.db import models, transaction, connection from django.db import models, transaction, connection
from django.db.models import Q, Sum, Max from django.db.models import Q, Sum, Max
from django.db.models.signals import pre_delete from django.db.models.signals import pre_delete
from django.utils.encoding import python_2_unicode_compatible
from django.utils import datetime_safe from django.utils import datetime_safe
import ox import ox
@ -164,12 +162,11 @@ def get_poster_path(f, x):
def get_torrent_path(f, x): def get_torrent_path(f, x):
return get_path(f, 'torrent.torrent') return get_path(f, 'torrent.torrent')
@python_2_unicode_compatible
class Item(models.Model): class Item(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, null=True, related_name='items') user = models.ForeignKey(User, null=True, related_name='items', on_delete=models.CASCADE)
groups = models.ManyToManyField(Group, blank=True, related_name='items') groups = models.ManyToManyField(Group, blank=True, related_name='items')
# while metadata is updated, files are set to rendered=False # while metadata is updated, files are set to rendered=False
@ -221,7 +218,7 @@ class Item(models.Model):
return default return default
def access(self, user): def access(self, user):
if user.is_anonymous(): if user.is_anonymous:
level = 'guest' level = 'guest'
else: else:
level = user.profile.get_level() level = user.profile.get_level()
@ -236,7 +233,7 @@ class Item(models.Model):
return False return False
def editable(self, user): def editable(self, user):
if user.is_anonymous(): if user.is_anonymous:
return False return False
if user.profile.capability('canEditMetadata') or \ if user.profile.capability('canEditMetadata') or \
user.is_staff or \ user.is_staff or \
@ -350,10 +347,10 @@ class Item(models.Model):
def __str__(self): def __str__(self):
year = self.get('year') year = self.get('year')
if year: if year:
string = u'%s (%s)' % (ox.decode_html(self.get('title', 'Untitled')), self.get('year')) string = '%s (%s)' % (ox.decode_html(self.get('title', 'Untitled')), self.get('year'))
else: else:
string = self.get('title', u'Untitled') string = self.get('title', 'Untitled')
return u'[%s] %s' % (self.public_id, string) return '[%s] %s' % (self.public_id, string)
def get_absolute_url(self): def get_absolute_url(self):
return '/%s' % self.public_id return '/%s' % self.public_id
@ -400,7 +397,7 @@ class Item(models.Model):
title = self.get(key, 'Untitled') title = self.get(key, 'Untitled')
while q.count() != 0: while q.count() != 0:
n += 1 n += 1
self.data[key] = u'%s [%d]' % (title, n) self.data[key] = '%s [%d]' % (title, n)
oxdbId = self.oxdb_id() oxdbId = self.oxdb_id()
q = Item.objects.filter(oxdbId=oxdbId).exclude(id=self.id) q = Item.objects.filter(oxdbId=oxdbId).exclude(id=self.id)
self.oxdbId = oxdbId self.oxdbId = oxdbId
@ -821,7 +818,7 @@ class Item(models.Model):
for key in settings.CONFIG['itemKeys']: for key in settings.CONFIG['itemKeys']:
i = key['id'] i = key['id']
if i == 'title': if i == 'title':
save(i, u'\n'.join(get_titles())) save(i, '\n'.join(get_titles()))
elif i == 'rightslevel': elif i == 'rightslevel':
save(i, self.level) save(i, self.level)
elif i == 'filename': elif i == 'filename':
@ -830,17 +827,17 @@ class Item(models.Model):
qs = Annotation.objects.filter(item=self) qs = Annotation.objects.filter(item=self)
qs = qs.filter(layer__in=Annotation.public_layers()).exclude(findvalue=None) qs = qs.filter(layer__in=Annotation.public_layers()).exclude(findvalue=None)
qs = qs.order_by('start') qs = qs.order_by('start')
save(i, u'\n'.join([l.findvalue for l in qs])) save(i, '\n'.join([l.findvalue for l in qs]))
elif key['type'] == 'layer': elif key['type'] == 'layer':
qs = Annotation.objects.filter(item=self).exclude(findvalue=None) qs = Annotation.objects.filter(item=self).exclude(findvalue=None)
qs = qs.filter(layer=i) qs = qs.filter(layer=i)
qs = qs.order_by('start') qs = qs.order_by('start')
save(i, u'\n'.join(list(filter(None, [l.findvalue for l in qs])))) save(i, '\n'.join(list(filter(None, [l.findvalue for l in qs]))))
layer_keys.append(i) layer_keys.append(i)
elif i != '*' and i not in self.facet_keys: elif i != '*' and i not in self.facet_keys:
value = self.get(i) value = self.get(i)
if isinstance(value, list): if isinstance(value, list):
value = u'\n'.join(value) value = '\n'.join(value)
save(i, value) save(i, value)
for key in self.facet_keys: for key in self.facet_keys:
@ -911,11 +908,11 @@ class Item(models.Model):
s = ItemSort(item=self) s = ItemSort(item=self)
def sortNames(values): def sortNames(values):
sort_value = u'' sort_value = ''
if values: if values:
sort_value = u'; '.join([get_name_sort(name) for name in values]) sort_value = '; '.join([get_name_sort(name) for name in values])
if not sort_value: if not sort_value:
sort_value = u'' sort_value = ''
return sort_value.lower() return sort_value.lower()
def set_value(s, name, value): def set_value(s, name, value):
@ -1019,7 +1016,7 @@ class Item(models.Model):
sort_type = sort_type[0] sort_type = sort_type[0]
if name not in self.base_keys: if name not in self.base_keys:
if sort_type == 'title': if sort_type == 'title':
value = get_title_sort(self.get(source, u'Untitled')) value = get_title_sort(self.get(source, 'Untitled'))
value = utils.sort_title(value)[:955] value = utils.sort_title(value)[:955]
set_value(s, name, value) set_value(s, name, value)
elif sort_type == 'person': elif sort_type == 'person':
@ -1027,9 +1024,9 @@ class Item(models.Model):
value = utils.sort_string(value)[:955] value = utils.sort_string(value)[:955]
set_value(s, name, value) set_value(s, name, value)
elif sort_type == 'string': elif sort_type == 'string':
value = self.get(source, u'') value = self.get(source, '')
if isinstance(value, list): if isinstance(value, list):
value = u','.join(value) value = ','.join(value)
value = utils.sort_string(value)[:955] value = utils.sort_string(value)[:955]
set_value(s, name, value) set_value(s, name, value)
elif sort_type == 'words': elif sort_type == 'words':
@ -1784,7 +1781,6 @@ for key in settings.CONFIG['itemKeys']:
if key.get('sortType') == 'person': if key.get('sortType') == 'person':
Item.person_keys.append(key['id']) Item.person_keys.append(key['id'])
@python_2_unicode_compatible
class ItemFind(models.Model): class ItemFind(models.Model):
""" """
used to find items, used to find items,
@ -1795,19 +1791,19 @@ class ItemFind(models.Model):
class Meta: class Meta:
unique_together = ("item", "key") unique_together = ("item", "key")
item = models.ForeignKey('Item', related_name='find', db_index=True) item = models.ForeignKey('Item', related_name='find', db_index=True, on_delete=models.CASCADE)
key = models.CharField(max_length=200, db_index=True) key = models.CharField(max_length=200, db_index=True)
value = models.TextField(blank=True, db_index=settings.DB_GIN_TRGM) value = models.TextField(blank=True, db_index=settings.DB_GIN_TRGM)
def __str__(self): def __str__(self):
return u"%s=%s" % (self.key, self.value) return "%s=%s" % (self.key, self.value)
''' '''
ItemSort ItemSort
table constructed based on info in settings.CONFIG['itemKeys'] table constructed based on info in settings.CONFIG['itemKeys']
''' '''
attrs = { attrs = {
'__module__': 'item.models', '__module__': 'item.models',
'item': models.OneToOneField('Item', related_name='sort', primary_key=True), 'item': models.OneToOneField('Item', related_name='sort', primary_key=True, on_delete=models.CASCADE),
'duration': models.FloatField(null=True, blank=True, db_index=True), 'duration': models.FloatField(null=True, blank=True, db_index=True),
'width': models.BigIntegerField(null=True, blank=True, db_index=True), 'width': models.BigIntegerField(null=True, blank=True, db_index=True),
'height': models.BigIntegerField(null=True, blank=True, db_index=True), 'height': models.BigIntegerField(null=True, blank=True, db_index=True),
@ -1826,14 +1822,13 @@ for key in list(filter(lambda k: k.get('sort', False) or k['type'] in ('integer'
ItemSort = type('ItemSort', (models.Model,), attrs) ItemSort = type('ItemSort', (models.Model,), attrs)
ItemSort.fields = [f.name for f in ItemSort._meta.fields] ItemSort.fields = [f.name for f in ItemSort._meta.fields]
@python_2_unicode_compatible
class Access(models.Model): class Access(models.Model):
class Meta: class Meta:
unique_together = ("item", "user") unique_together = ("item", "user")
access = models.DateTimeField(auto_now=True) access = models.DateTimeField(auto_now=True)
item = models.ForeignKey(Item, related_name='accessed') item = models.ForeignKey(Item, related_name='accessed', on_delete=models.CASCADE)
user = models.ForeignKey(User, null=True, related_name='accessed_items') user = models.ForeignKey(User, null=True, related_name='accessed_items', on_delete=models.CASCADE)
accessed = models.IntegerField(default=0) accessed = models.IntegerField(default=0)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
@ -1846,10 +1841,9 @@ class Access(models.Model):
def __str__(self): def __str__(self):
if self.user: if self.user:
return u"%s/%s/%s" % (self.user, self.item, self.access) return "%s/%s/%s" % (self.user, self.item, self.access)
return u"%s/%s" % (self.item, self.access) return "%s/%s" % (self.item, self.access)
@python_2_unicode_compatible
class Facet(models.Model): class Facet(models.Model):
''' '''
used for keys that can have multiple values like people, languages etc. used for keys that can have multiple values like people, languages etc.
@ -1860,13 +1854,13 @@ class Facet(models.Model):
class Meta: class Meta:
unique_together = ("item", "key", "value") unique_together = ("item", "key", "value")
item = models.ForeignKey('Item', related_name='facets') item = models.ForeignKey('Item', related_name='facets', on_delete=models.CASCADE)
key = models.CharField(max_length=200, db_index=True) key = models.CharField(max_length=200, db_index=True)
value = models.CharField(max_length=1000, db_index=True) value = models.CharField(max_length=1000, db_index=True)
sortvalue = models.CharField(max_length=1000, db_index=True) sortvalue = models.CharField(max_length=1000, db_index=True)
def __str__(self): def __str__(self):
return u"%s=%s" % (self.key, self.value) return "%s=%s" % (self.key, self.value)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.sortvalue: if not self.sortvalue:
@ -1886,7 +1880,7 @@ class Description(models.Model):
class AnnotationSequence(models.Model): class AnnotationSequence(models.Model):
item = models.OneToOneField('Item', related_name='_annotation_sequence') item = models.OneToOneField('Item', related_name='_annotation_sequence', on_delete=models.CASCADE)
value = models.BigIntegerField(default=1) value = models.BigIntegerField(default=1)
@classmethod @classmethod

51
pandora/item/site.py Normal file
View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
from django.urls import path, re_path
from . import views
urls = [
[
#frames
re_path(r'^(?P<id>[A-Z0-9].*)/(?P<size>\d+)p(?P<position>[\d\.]*)\.jpg$', views.frame),
#timelines
re_path(r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p(?P<position>\d+)\.(?P<format>png|jpg)$', views.timeline),
re_path(r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p\.(?P<format>png|jpg)$', views.timeline),
#download
re_path(r'^(?P<id>[A-Z0-9].*)/download$', views.download),
re_path(r'^(?P<id>[A-Z0-9].*)/download/$', views.download),
re_path(r'^(?P<id>[A-Z0-9].*)/download/source/(?P<part>\d+)?$', views.download_source),
re_path(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p(?P<part>\d+)\.(?P<format>webm|ogv|mp4)$', views.download),
re_path(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p\.(?P<format>webm|ogv|mp4)$', views.download),
#video
re_path(r'^(?P<id>[A-Z0-9].*)/(?P<resolution>\d+)p(?P<index>\d*)\.(?P<format>webm|ogv|mp4)$', views.video),
re_path(r'^(?P<id>[A-Z0-9].*)/(?P<resolution>\d+)p(?P<index>\d*)\.(?P<track>.+)\.(?P<format>webm|ogv|mp4)$', views.video),
#torrent
re_path(r'^(?P<id>[A-Z0-9].*)/torrent$', views.torrent),
re_path(r'^(?P<id>[A-Z0-9].*)/torrent/(?P<filename>.*?)$', views.torrent),
#export
re_path(r'^(?P<id>[A-Z0-9].*)/json$', views.item_json),
re_path(r'^(?P<id>[A-Z0-9].*)/xml$', views.item_xml),
#srt export
re_path(r'^(?P<id>[A-Z0-9].*)/(?P<layer>.+)\.(?:(?P<language>.{2})\.)?(?P<ext>srt|vtt)$', views.srt),
#icon
re_path(r'^(?P<id>[A-Z0-9].*)/icon(?P<size>\d*)\.jpg$', views.icon),
#poster
re_path(r'^(?P<id>[A-Z0-9].*)/posterframe(?P<position>\d+).jpg$', views.poster_frame),
re_path(r'^(?P<id>[A-Z0-9].*)/poster(?P<size>\d+)\.jpg$', views.poster),
re_path(r'^(?P<id>[A-Z0-9].*)/siteposter(?P<size>\d*)\.jpg$', views.siteposter),
re_path(r'^(?P<id>[A-Z0-9].*)/poster\.jpg$', views.siteposter),
re_path(r'^random$', views.random_annotation),
],
'item',
'item',
]

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
from datetime import timedelta, datetime from datetime import timedelta, datetime

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, with_statement, print_function
import math import math
import os import os

View File

@ -1,47 +0,0 @@
# -*- coding: utf-8 -*-
from django.conf.urls import url
from . import views
urlpatterns = [
#frames
url(r'^(?P<id>[A-Z0-9].*)/(?P<size>\d+)p(?P<position>[\d\.]*)\.jpg$', views.frame),
#timelines
url(r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p(?P<position>\d+)\.(?P<format>png|jpg)$', views.timeline),
url(r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p\.(?P<format>png|jpg)$', views.timeline),
#download
url(r'^(?P<id>[A-Z0-9].*)/download$', views.download),
url(r'^(?P<id>[A-Z0-9].*)/download/$', views.download),
url(r'^(?P<id>[A-Z0-9].*)/download/source/(?P<part>\d+)?$', views.download_source),
url(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p(?P<part>\d+)\.(?P<format>webm|ogv|mp4)$', views.download),
url(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p\.(?P<format>webm|ogv|mp4)$', views.download),
#video
url(r'^(?P<id>[A-Z0-9].*)/(?P<resolution>\d+)p(?P<index>\d*)\.(?P<format>webm|ogv|mp4)$', views.video),
url(r'^(?P<id>[A-Z0-9].*)/(?P<resolution>\d+)p(?P<index>\d*)\.(?P<track>.+)\.(?P<format>webm|ogv|mp4)$', views.video),
#torrent
url(r'^(?P<id>[A-Z0-9].*)/torrent$', views.torrent),
url(r'^(?P<id>[A-Z0-9].*)/torrent/(?P<filename>.*?)$', views.torrent),
#export
url(r'^(?P<id>[A-Z0-9].*)/json$', views.item_json),
url(r'^(?P<id>[A-Z0-9].*)/xml$', views.item_xml),
#srt export
url(r'^(?P<id>[A-Z0-9].*)/(?P<layer>.+)\.(?:(?P<language>.{2})\.)?(?P<ext>srt|vtt)$', views.srt),
#icon
url(r'^(?P<id>[A-Z0-9].*)/icon(?P<size>\d*)\.jpg$', views.icon),
#poster
url(r'^(?P<id>[A-Z0-9].*)/posterframe(?P<position>\d+).jpg$', views.poster_frame),
url(r'^(?P<id>[A-Z0-9].*)/poster(?P<size>\d+)\.jpg$', views.poster),
url(r'^(?P<id>[A-Z0-9].*)/siteposter(?P<size>\d*)\.jpg$', views.siteposter),
url(r'^(?P<id>[A-Z0-9].*)/poster\.jpg$', views.siteposter),
url(r'^random$', views.random_annotation),
]

View File

@ -55,14 +55,14 @@ def plural_key(term):
def sort_title(title): def sort_title(title):
title = title.replace(u'Æ', 'Ae') title = title.replace('Æ', 'Ae')
if isinstance(title, bytes): if isinstance(title, bytes):
title = title.decode('utf-8') title = title.decode('utf-8')
title = ox.decode_html(title) title = ox.decode_html(title)
title = sort_string(title) title = sort_string(title)
#title #title
title = re.sub(u'[\'!¿¡,\.;\-"\:\*\[\]]', '', title) title = re.sub('[\'!¿¡,\.;\-"\:\*\[\]]', '', title)
return title.strip() return title.strip()
def get_positions(ids, pos, decode_id=False): def get_positions(ids, pos, decode_id=False):

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os.path import os.path
import mimetypes import mimetypes
@ -144,7 +143,7 @@ def get_positions(request, query):
return utils.get_positions(ids, query['positions']) return utils.get_positions(ids, query['positions'])
def is_editable(request, item): def is_editable(request, item):
if request.user.is_anonymous(): if request.user.is_anonymous:
return False return False
if not hasattr(request, 'user_group_names'): if not hasattr(request, 'user_group_names'):
request.user_group_names = {g.name for g in request.user.groups.all()} request.user_group_names = {g.name for g in request.user.groups.all()}
@ -1097,7 +1096,7 @@ def video(request, id, resolution, format, index=None, track=None):
ext = '.%s' % format ext = '.%s' % format
duration = stream.info['duration'] duration = stream.info['duration']
filename = u"Clip of %s - %s-%s - %s %s%s" % ( filename = "Clip of %s - %s-%s - %s %s%s" % (
item.get('title'), item.get('title'),
ox.format_duration(t[0] * 1000).replace(':', '.')[:-4], ox.format_duration(t[0] * 1000).replace(':', '.')[:-4],
ox.format_duration(t[1] * 1000).replace(':', '.')[:-4], ox.format_duration(t[1] * 1000).replace(':', '.')[:-4],
@ -1166,9 +1165,9 @@ def srt(request, id, layer, language=None, index=None, ext='srt'):
content_type, encoder = _subtitle_formats[ext] content_type, encoder = _subtitle_formats[ext]
response = HttpResponse() response = HttpResponse()
if language: if language:
filename = u"%s.%s.%s" % (item.get('title'), language, ext) filename = "%s.%s.%s" % (item.get('title'), language, ext)
else: else:
filename = u"%s.%s" % (item.get('title'), ext) filename = "%s.%s" % (item.get('title'), ext)
response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8')) response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8'))
response['Content-Type'] = content_type response['Content-Type'] = content_type
response.write(item.srt(layer, language, encoder=encoder)) response.write(item.srt(layer, language, encoder=encoder))
@ -1206,7 +1205,7 @@ def atom_xml(request):
el.text = atom_link el.text = atom_link
level = settings.CONFIG['capabilities']['canSeeItem']['guest'] level = settings.CONFIG['capabilities']['canSeeItem']['guest']
if not request.user.is_anonymous(): if not request.user.is_anonymous:
level = request.user.profile.level level = request.user.profile.level
for item in models.Item.objects.filter(level__lte=level, rendered=True).order_by('-created')[:7]: for item in models.Item.objects.filter(level__lte=level, rendered=True).order_by('-created')[:7]:
if add_updated: if add_updated:
@ -1232,7 +1231,7 @@ def atom_xml(request):
if item.get('director'): if item.get('director'):
el = ET.SubElement(entry, "author") el = ET.SubElement(entry, "author")
name = ET.SubElement(el, "name") name = ET.SubElement(el, "name")
name.text = ox.decode_html(u', '.join(item.get('director'))) name.text = ox.decode_html(', '.join(item.get('director')))
elif item.user: elif item.user:
el = ET.SubElement(entry, "author") el = ET.SubElement(entry, "author")
name = ET.SubElement(el, "name") name = ET.SubElement(el, "name")
@ -1283,7 +1282,7 @@ def atom_xml(request):
el = ET.SubElement(format, key) el = ET.SubElement(format, key)
el.text = unicode(value) el.text = unicode(value)
el = ET.SubElement(format, 'pixel_aspect_ratio') el = ET.SubElement(format, 'pixel_aspect_ratio')
el.text = u"1:1" el.text = "1:1"
if has_capability(request.user, 'canDownloadVideo'): if has_capability(request.user, 'canDownloadVideo'):
if item.torrent: if item.torrent:
@ -1386,7 +1385,7 @@ def sitemap_part_xml(request, part):
def item_json(request, id): def item_json(request, id):
level = settings.CONFIG['capabilities']['canSeeItem']['guest'] level = settings.CONFIG['capabilities']['canSeeItem']['guest']
if not request.user.is_anonymous(): if not request.user.is_anonymous:
level = request.user.profile.level level = request.user.profile.level
qs = models.Item.objects.filter(public_id=id, level__lte=level) qs = models.Item.objects.filter(public_id=id, level__lte=level)
if qs.count() == 0: if qs.count() == 0:
@ -1399,7 +1398,7 @@ def item_json(request, id):
def item_xml(request, id): def item_xml(request, id):
level = settings.CONFIG['capabilities']['canSeeItem']['guest'] level = settings.CONFIG['capabilities']['canSeeItem']['guest']
if not request.user.is_anonymous(): if not request.user.is_anonymous:
level = request.user.profile.level level = request.user.profile.level
qs = models.Item.objects.filter(public_id=id, level__lte=level) qs = models.Item.objects.filter(public_id=id, level__lte=level)
if qs.count() == 0: if qs.count() == 0:
@ -1439,7 +1438,7 @@ def item(request, id):
view = None view = None
template = 'index.html' template = 'index.html'
level = settings.CONFIG['capabilities']['canSeeItem']['guest'] level = settings.CONFIG['capabilities']['canSeeItem']['guest']
if not request.user.is_anonymous(): if not request.user.is_anonymous:
level = request.user.profile.level level = request.user.profile.level
qs = models.Item.objects.filter(public_id=id, level__lte=level) qs = models.Item.objects.filter(public_id=id, level__lte=level)
if qs.count() == 0: if qs.count() == 0:
@ -1484,7 +1483,7 @@ def item(request, id):
else: else:
title = key['title'] if key else k.capitalize() title = key['title'] if key else k.capitalize()
if isinstance(value, list): if isinstance(value, list):
value = value = u', '.join([unicode(v) for v in value]) value = value = ', '.join([unicode(v) for v in value])
elif key and key.get('type') == 'float': elif key and key.get('type') == 'float':
value = '%0.3f' % value value = '%0.3f' % value
elif key and key.get('type') == 'time': elif key and key.get('type') == 'time':
@ -1493,7 +1492,7 @@ def item(request, id):
clips = [] clips = []
clip = {'in': 0, 'annotations': []} clip = {'in': 0, 'annotations': []}
# logged in users should have javascript. not adding annotations makes load faster # logged in users should have javascript. not adding annotations makes load faster
if not settings.USE_IMDB and request.user.is_anonymous(): if not settings.USE_IMDB and request.user.is_anonymous:
for a in item.annotations.exclude( for a in item.annotations.exclude(
layer='subtitles' layer='subtitles'
).exclude( ).exclude(
@ -1513,13 +1512,13 @@ def item(request, id):
head_title = item.get('title', '') head_title = item.get('title', '')
title = item.get('title', '') title = item.get('title', '')
if item.get('director'): if item.get('director'):
head_title += u' (%s)' % u', '.join(item.get('director', [])) head_title += ' (%s)' % ', '.join(item.get('director', []))
if item.get('year'): if item.get('year'):
head_title += u' %s' % item.get('year') head_title += ' %s' % item.get('year')
title += u' (%s)' % item.get('year') title += ' (%s)' % item.get('year')
if view: if view:
head_title += u' %s' % view head_title += ' %s' % view
head_title += u' %s' % settings.SITENAME head_title += ' %s' % settings.SITENAME
head_title = ox.decode_html(head_title) head_title = ox.decode_html(head_title)
title = ox.decode_html(title) title = ox.decode_html(title)
ctx = { ctx = {

View File

@ -124,7 +124,7 @@ class ListManager(Manager):
if conditions: if conditions:
qs = qs.filter(conditions) qs = qs.filter(conditions)
if user.is_anonymous(): if user.is_anonymous:
qs = qs.filter(Q(status='public') | Q(status='featured')) qs = qs.filter(Q(status='public') | Q(status='featured'))
else: else:
qs = qs.filter(Q(status='public') | Q(status='featured') | Q(user=user)) qs = qs.filter(Q(status='public') | Q(status='featured') | Q(user=user))

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -10,7 +9,6 @@ from django.db import models
from django.db.models import Max from django.db.models import Max
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.conf import settings from django.conf import settings
from django.utils.encoding import python_2_unicode_compatible
from oxdjango.fields import JSONField from oxdjango.fields import JSONField
import ox import ox
@ -28,7 +26,6 @@ def get_icon_path(f, x): return get_path(f, 'icon.jpg')
def get_listview(): return settings.CONFIG['user']['ui']['listView'] def get_listview(): return settings.CONFIG['user']['ui']['listView']
def get_listsort(): return tuple(settings.CONFIG['user']['ui']['listSort']) def get_listsort(): return tuple(settings.CONFIG['user']['ui']['listSort'])
@python_2_unicode_compatible
class List(models.Model): class List(models.Model):
class Meta: class Meta:
@ -36,7 +33,7 @@ class List(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, related_name='lists') user = models.ForeignKey(User, related_name='lists', on_delete=models.CASCADE)
groups = models.ManyToManyField(Group, blank=True, related_name='lists') groups = models.ManyToManyField(Group, blank=True, related_name='lists')
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
status = models.CharField(max_length=20, default='private') status = models.CharField(max_length=20, default='private')
@ -50,7 +47,7 @@ class List(models.Model):
view = models.TextField(default=get_listview) view = models.TextField(default=get_listview)
sort = JSONField(default=get_listsort, editable=False) sort = JSONField(default=get_listsort, editable=False)
poster_frames = JSONField(default=[], editable=False) poster_frames = JSONField(default=list, editable=False)
#is through table still required? #is through table still required?
items = models.ManyToManyField('item.Item', related_name='lists', items = models.ManyToManyField('item.Item', related_name='lists',
@ -110,13 +107,13 @@ class List(models.Model):
return self.get_id() return self.get_id()
def get_id(self): def get_id(self):
return u'%s:%s' % (self.user.username, self.name) return '%s:%s' % (self.user.username, self.name)
def accessible(self, user): def accessible(self, user):
return self.user == user or self.status in ('public', 'featured') return self.user == user or self.status in ('public', 'featured')
def editable(self, user): def editable(self, user):
if not user or user.is_anonymous(): if not user or user.is_anonymous:
return False return False
if self.user == user or \ if self.user == user or \
self.groups.filter(id__in=user.groups.all()).count() > 0 or \ self.groups.filter(id__in=user.groups.all()).count() > 0 or \
@ -244,7 +241,7 @@ class List(models.Model):
elif key == 'subscribers': elif key == 'subscribers':
response[key] = self.subscribed_users.all().count() response[key] = self.subscribed_users.all().count()
elif key == 'subscribed': elif key == 'subscribed':
if user and not user.is_anonymous(): if user and not user.is_anonymous:
response[key] = self.subscribed_users.filter(id=user.id).exists() response[key] = self.subscribed_users.filter(id=user.id).exists()
else: else:
response[key] = getattr(self, { response[key] = getattr(self, {
@ -314,29 +311,27 @@ class List(models.Model):
path = source path = source
return path return path
@python_2_unicode_compatible
class ListItem(models.Model): class ListItem(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
list = models.ForeignKey(List) list = models.ForeignKey(List, on_delete=models.CASCADE)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
item = models.ForeignKey('item.Item') item = models.ForeignKey('item.Item', on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return u'%s in %s' % (self.item, self.list) return '%s in %s' % (self.item, self.list)
@python_2_unicode_compatible
class Position(models.Model): class Position(models.Model):
class Meta: class Meta:
unique_together = ("user", "list", "section") unique_together = ("user", "list", "section")
list = models.ForeignKey(List, related_name='position') list = models.ForeignKey(List, related_name='position', on_delete=models.CASCADE)
user = models.ForeignKey(User) user = models.ForeignKey(User, on_delete=models.CASCADE)
section = models.CharField(max_length=255) section = models.CharField(max_length=255)
position = models.IntegerField(default=0) position = models.IntegerField(default=0)
def __str__(self): def __str__(self):
return u'%s/%s/%s' % (self.section, self.position, self.list) return '%s/%s/%s' % (self.section, self.position, self.list)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os import os
import re import re
@ -75,7 +74,7 @@ def findLists(request, data):
query = parse_query(data, request.user) query = parse_query(data, request.user)
#order #order
is_section_request = query['sort'] == [{u'operator': u'+', u'key': u'position'}] is_section_request = query['sort'] == [{'operator': '+', 'key': 'position'}]
def is_featured_condition(x): def is_featured_condition(x):
return x['key'] == 'status' and \ return x['key'] == 'status' and \
x['value'] == 'featured' and \ x['value'] == 'featured' and \
@ -87,7 +86,7 @@ def findLists(request, data):
if is_section_request: if is_section_request:
qs = query['qs'] qs = query['qs']
if not is_featured and not request.user.is_anonymous(): if not is_featured and not request.user.is_anonymous:
qs = qs.filter(position__in=models.Position.objects.filter(user=request.user)) qs = qs.filter(position__in=models.Position.objects.filter(user=request.user))
qs = qs.order_by('position__position') qs = qs.order_by('position__position')
else: else:

View File

@ -1,9 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db import models from django.db import models
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils.encoding import python_2_unicode_compatible
import ox import ox
@ -12,11 +10,10 @@ from . import managers
User = get_user_model() User = get_user_model()
@python_2_unicode_compatible
class Log(models.Model): class Log(models.Model):
created = models.DateTimeField(auto_now_add=True, db_index=True) created = models.DateTimeField(auto_now_add=True, db_index=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, default=None, blank=True, null=True) user = models.ForeignKey(User, default=None, blank=True, null=True, on_delete=models.CASCADE)
url = models.CharField(max_length=1000, default='') url = models.CharField(max_length=1000, default='')
line = models.IntegerField(default=0) line = models.IntegerField(default=0)
text = models.TextField(blank=True) text = models.TextField(blank=True)
@ -24,7 +21,7 @@ class Log(models.Model):
objects = managers.LogManager() objects = managers.LogManager()
def __str__(self): def __str__(self):
return u"%s" % self.id return "%s" % self.id
def json(self, keys=None): def json(self, keys=None):
j = { j = {

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from datetime import timedelta, datetime from datetime import timedelta, datetime

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import logging import logging
import sys import sys
@ -34,7 +33,7 @@ class ErrorHandler(logging.Handler):
request = record.request request = record.request
request_repr = repr(request) request_repr = repr(request)
if request.user.is_authenticated(): if request.user.is_authenticated:
user = request.user user = request.user
url = request.META.get('PATH_INFO', '') url = request.META.get('PATH_INFO', '')
except: except:

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import ox import ox
from ox.utils import json from ox.utils import json
@ -25,7 +24,7 @@ def logError(request, data):
returns {} returns {}
see: findErrorLogs, removeErrorLogs see: findErrorLogs, removeErrorLogs
''' '''
if request.user.is_authenticated(): if request.user.is_authenticated:
user = request.user user = request.user
else: else:
user = None user = None

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,14 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible
import ox import ox
from . import managers from . import managers
@python_2_unicode_compatible
class News(models.Model): class News(models.Model):
objects = managers.NewsManager() objects = managers.NewsManager()
@ -20,7 +17,7 @@ class News(models.Model):
text = models.TextField() text = models.TextField()
def editable(self, user): def editable(self, user):
return user.is_authenticated() and user.profile.capability("canEditSitePages") return user.is_authenticated and user.profile.capability("canEditSitePages")
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(News, self).save(*args, **kwargs) super(News, self).save(*args, **kwargs)
@ -42,5 +39,5 @@ class News(models.Model):
return j return j
def __str__(self): def __str__(self):
return u"%s/%s" % (self.date, self.title) return "%s/%s" % (self.date, self.title)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import ox import ox
from ox.utils import json from ox.utils import json

View File

@ -111,10 +111,10 @@ class ApiActions(dict):
f = fc[len(fc)-1].cell_contents f = fc[len(fc)-1].cell_contents
if PY2: if PY2:
info = f.func_code.co_filename[len(settings.PROJECT_ROOT)+1:] info = f.func_code.co_filename[len(settings.PROJECT_ROOT)+1:]
info = u'%s:%s' % (info, f.func_code.co_firstlineno) info = '%s:%s' % (info, f.func_code.co_firstlineno)
else: else:
info = f.__code__.co_filename[len(settings.PROJECT_ROOT)+1:] info = f.__code__.co_filename[len(settings.PROJECT_ROOT)+1:]
info = u'%s:%s' % (info, f.__code__.co_firstlineno) info = '%s:%s' % (info, f.__code__.co_firstlineno)
return info, trim(inspect.getsource(f)) return info, trim(inspect.getsource(f))
def register(self, method, action=None, cache=True, version=None): def register(self, method, action=None, cache=True, version=None):

View File

@ -1,13 +1,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import from __future__ import absolute_import
from django.conf.urls import url from django.urls import path
from . import views from . import views
from . import actions from . import actions
actions.autodiscover() actions.autodiscover()
urlpatterns = [ urls = [
url(r'^$', views.api), [
path(r'', views.api),
],
'api',
'api'
] ]

View File

@ -3,7 +3,7 @@ from __future__ import division, absolute_import
import json import json
from django.shortcuts import render_to_response from django.shortcuts import render
from django.conf import settings from django.conf import settings
from ..shortcuts import render_to_json_response, json_response, HttpErrorJson from ..shortcuts import render_to_json_response, json_response, HttpErrorJson
@ -31,7 +31,7 @@ def api(request):
'settings': settings, 'settings': settings,
'sitename': settings.SITENAME 'sitename': settings.SITENAME
} }
response = render_to_response('api.html', context) response = render(request, 'api.html', context)
response['Access-Control-Allow-Origin'] = '*' response['Access-Control-Allow-Origin'] = '*'
return response return response
if request.META.get('CONTENT_TYPE') == 'application/json': if request.META.get('CONTENT_TYPE') == 'application/json':

View File

@ -12,7 +12,7 @@ def login_required_json(function=None):
""" """
def _wrapped_view(request, *args, **kwargs): def _wrapped_view(request, *args, **kwargs):
if request.user.is_authenticated(): if request.user.is_authenticated:
return function(request, *args, **kwargs) return function(request, *args, **kwargs)
return render_to_json_response({'status': {'code': 401, 'text': 'login required'}}) return render_to_json_response({'status': {'code': 401, 'text': 'login required'}})
return wraps(function)(_wrapped_view) return wraps(function)(_wrapped_view)
@ -24,7 +24,7 @@ def admin_required_json(function=None):
""" """
def _wrapped_view(request, *args, **kwargs): def _wrapped_view(request, *args, **kwargs):
if request.user.is_authenticated() and request.user.profile.get_level() == 'admin': if request.user.is_authenticated and request.user.profile.get_level() == 'admin':
return function(request, *args, **kwargs) return function(request, *args, **kwargs)
return render_to_json_response({'status': {'code': 403, 'text': 'permission denied'}}) return render_to_json_response({'status': {'code': 403, 'text': 'permission denied'}})
return wraps(function)(_wrapped_view) return wraps(function)(_wrapped_view)

View File

@ -64,7 +64,7 @@ class DictField(models.TextField):
def dumps(cls, obj): def dumps(cls, obj):
return json.dumps(obj, default=to_json, ensure_ascii=False) return json.dumps(obj, default=to_json, ensure_ascii=False)
def from_db_value(self, value, expression, connection, context): def from_db_value(self, value, expression, connection, context=None):
if value is None: if value is None:
return value return value
if isinstance(value, self._type): if isinstance(value, self._type):

View File

@ -1,14 +1,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.utils.deprecation import MiddlewareMixin
from .shortcuts import HttpErrorJson, render_to_json_response from .shortcuts import HttpErrorJson, render_to_json_response
class ExceptionMiddleware(object): class ExceptionMiddleware(MiddlewareMixin):
def process_exception(self, request, exception): def process_exception(self, request, exception):
if isinstance(exception, HttpErrorJson): if isinstance(exception, HttpErrorJson):
return render_to_json_response(exception.response) return render_to_json_response(exception.response)
return None return None
class ChromeFrameMiddleware(object): class ChromeFrameMiddleware(MiddlewareMixin):
def process_response(self, request, response): def process_response(self, request, response):
response['X-UA-Compatible'] = 'chrome=1' response['X-UA-Compatible'] = 'chrome=1'
return response return response

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import datetime import datetime
from django.utils import datetime_safe from django.utils import datetime_safe
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
@ -23,7 +22,7 @@ def _to_json(python_object):
return python_object.strftime('%Y-%m-%dT%H:%M:%SZ') return python_object.strftime('%Y-%m-%dT%H:%M:%SZ')
if isinstance(python_object, datetime_safe.datetime): if isinstance(python_object, datetime_safe.datetime):
return python_object.strftime('%Y-%m-%dT%H:%M:%SZ') 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))) raise TypeError('%s %s is not JSON serializable' % (repr(python_object), type(python_object)))
def json_dump(data, fp, indent=4): def json_dump(data, fp, indent=4):
return json.dump(data, fp, indent=indent, default=_to_json, ensure_ascii=False) return json.dump(data, fp, indent=indent, default=_to_json, ensure_ascii=False)

View File

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import unicodedata import unicodedata
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from oxdjango import fields from oxdjango import fields
import ox import ox
@ -24,10 +22,9 @@ def get_name_sort(name, sortname=None):
person.save() person.save()
sortname = unicodedata.normalize('NFKD', person.sortname) sortname = unicodedata.normalize('NFKD', person.sortname)
else: else:
sortname = u'' sortname = ''
return sortname return sortname
@python_2_unicode_compatible
class Person(models.Model): class Person(models.Model):
name = models.CharField(max_length=200, unique=True) name = models.CharField(max_length=200, unique=True)
sortname = models.CharField(max_length=200) sortname = models.CharField(max_length=200)

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from celery.task import task from celery.task import task

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import ox import ox
from ox.utils import json from ox.utils import json

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.contrib import admin from django.contrib import admin

View File

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db import models, transaction from django.db import models, transaction
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils.encoding import python_2_unicode_compatible
import ox import ox
from oxdjango import fields from oxdjango import fields
@ -15,7 +13,6 @@ from . import managers
User = get_user_model() User = get_user_model()
@python_2_unicode_compatible
class Place(models.Model): class Place(models.Model):
''' '''
Places are named locations, they should have geographical information attached to them. Places are named locations, they should have geographical information attached to them.
@ -24,7 +21,7 @@ class Place(models.Model):
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
defined = models.BooleanField(default=True) defined = models.BooleanField(default=True)
user = models.ForeignKey(User, null=True, related_name='places') user = models.ForeignKey(User, null=True, related_name='places', on_delete=models.CASCADE)
name = models.CharField(max_length=1024) name = models.CharField(max_length=1024)
alternativeNames = fields.TupleField(default=()) alternativeNames = fields.TupleField(default=())
@ -60,7 +57,7 @@ class Place(models.Model):
@classmethod @classmethod
def get_or_create(model, name): def get_or_create(model, name):
qs = model.objects.filter(name_find__contains=u'|%s|' % name.lower()) qs = model.objects.filter(name_find__contains='|%s|' % name.lower())
if qs.count() == 0: if qs.count() == 0:
instance = model(name=name) instance = model(name=name)
instance.save() instance.save()
@ -69,7 +66,7 @@ class Place(models.Model):
return instance return instance
def editable(self, user): def editable(self, user):
if user and not user.is_anonymous() \ if user and not user.is_anonymous \
and (not self.user or \ and (not self.user or \
self.user == user or \ self.user == user or \
user.profile.capability('canEditPlaces')): user.profile.capability('canEditPlaces')):

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from celery.task import task from celery.task import task

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db.models import Max, Min, Count from django.db.models import Max, Min, Count
from django.conf import settings from django.conf import settings
@ -50,7 +49,7 @@ def addPlace(request, data):
n = 0 n = 0
while _exists: while _exists:
_exists = models.Place.objects.filter(defined=True, _exists = models.Place.objects.filter(defined=True,
name_find__contains=u'|%s|' % name.lower()).count() > 0 name_find__contains='|%s|' % name.lower()).count() > 0
if _exists: if _exists:
name = 'Untitled [%s]' %n name = 'Untitled [%s]' %n
n += 1 n += 1
@ -61,7 +60,7 @@ def addPlace(request, data):
for n in names: for n in names:
n = ox.decode_html(name) n = ox.decode_html(name)
if models.Place.objects.filter(defined=True, if models.Place.objects.filter(defined=True,
name_find__contains=u'|%s|' % n.lower()).count() != 0: name_find__contains='|%s|' % n.lower()).count() != 0:
exists = True exists = True
existing_names.append(n) existing_names.append(n)
''' '''
@ -130,7 +129,7 @@ def editPlace(request, data):
for name in names + alternative_names: for name in names + alternative_names:
name = ox.decode_html(name) name = ox.decode_html(name)
if models.Place.objects.filter(defined=True, if models.Place.objects.filter(defined=True,
name_find__contains=u'|%s|' % name.lower()).exclude(id=place.id).count() != 0: name_find__contains='|%s|' % name.lower()).exclude(id=place.id).count() != 0:
conflict = True conflict = True
conflict_names.append(name) conflict_names.append(name)
''' '''

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db.models import Q, Manager from django.db.models import Q, Manager

View File

@ -1,8 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from item.models import ItemSort from item.models import ItemSort
@ -15,7 +13,6 @@ def parse_hash(value):
def format_hash(value): def format_hash(value):
return hex(value + 9223372036854775808)[2:-1].upper() return hex(value + 9223372036854775808)[2:-1].upper()
@python_2_unicode_compatible
class Sequence(models.Model): class Sequence(models.Model):
class Meta: class Meta:
unique_together = ("sort", "start", "end", "mode") unique_together = ("sort", "start", "end", "mode")
@ -25,7 +22,7 @@ class Sequence(models.Model):
'color': 1 'color': 1
} }
mode = models.IntegerField(choices=sorted(zip(MODE.values(), list(MODE)), key=lambda k: k[0]), default=0) mode = models.IntegerField(choices=sorted(zip(MODE.values(), list(MODE)), key=lambda k: k[0]), default=0)
sort = models.ForeignKey(ItemSort, null=True, related_name='sequences') sort = models.ForeignKey(ItemSort, null=True, related_name='sequences', on_delete=models.CASCADE)
hash = models.BigIntegerField(db_index=True, default=-9223372036854775808) hash = models.BigIntegerField(db_index=True, default=-9223372036854775808)
start = models.FloatField(default=-1) start = models.FloatField(default=-1)
@ -40,7 +37,7 @@ class Sequence(models.Model):
@property @property
def public_id(self): def public_id(self):
return u"%s/%0.03f-%0.03f" % (self.sort.item.public_id, float(self.start), float(self.end)) return "%s/%0.03f-%0.03f" % (self.sort.item.public_id, float(self.start), float(self.end))
def __str__(self): def __str__(self):
return self.public_id return self.public_id

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from six import string_types from six import string_types
from django.db import connection, transaction from django.db import connection, transaction

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from ox.utils import json from ox.utils import json
from oxdjango.shortcuts import render_to_json_response, json_response from oxdjango.shortcuts import render_to_json_response, json_response

View File

@ -96,7 +96,7 @@ TEMPLATES = [
}, },
] ]
MIDDLEWARE_CLASSES = ( MIDDLEWARE = (
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',

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