- simplify metadata db structure
- better sort values if field is empty - switch to python-ox, faster imdb import - move files backend into own app
This commit is contained in:
parent
d6a95727a6
commit
9defcd3c9f
16 changed files with 1493 additions and 914 deletions
0
pandora/archive/__init__.py
Normal file
0
pandora/archive/__init__.py
Normal file
25
pandora/archive/admin.py
Normal file
25
pandora/archive/admin.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
#from forms import FileAdminForm, MovieAdminForm, ArchiveFileAdminForm
|
||||
import models
|
||||
|
||||
class FileAdmin(admin.ModelAdmin):
|
||||
search_fields = ['path', 'video_codec']
|
||||
|
||||
#form = FileAdminForm
|
||||
|
||||
admin.site.register(models.File, FileAdmin)
|
||||
|
||||
class FileInstanceAdmin(admin.ModelAdmin):
|
||||
search_fields = ['path', 'archive__name']
|
||||
#form = ArchiveFileAdminForm
|
||||
|
||||
admin.site.register(models.FileInstance, FileInstanceAdmin)
|
||||
|
||||
class ArchiveAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name']
|
||||
admin.site.register(models.Archive, ArchiveAdmin)
|
||||
|
||||
240
pandora/archive/migrations/0001_initial.py
Normal file
240
pandora/archive/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from south.db import db
|
||||
from django.db import models
|
||||
from archive.models import *
|
||||
|
||||
class Migration:
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'Volume'
|
||||
db.create_table('archive_volume', (
|
||||
('id', orm['archive.Volume:id']),
|
||||
('start', orm['archive.Volume:start']),
|
||||
('end', orm['archive.Volume:end']),
|
||||
('name', orm['archive.Volume:name']),
|
||||
))
|
||||
db.send_create_signal('archive', ['Volume'])
|
||||
|
||||
# Adding model 'Frame'
|
||||
db.create_table('archive_frame', (
|
||||
('id', orm['archive.Frame:id']),
|
||||
('created', orm['archive.Frame:created']),
|
||||
('modified', orm['archive.Frame:modified']),
|
||||
('file', orm['archive.Frame:file']),
|
||||
('position', orm['archive.Frame:position']),
|
||||
('frame', orm['archive.Frame:frame']),
|
||||
))
|
||||
db.send_create_signal('archive', ['Frame'])
|
||||
|
||||
# Adding model 'Archive'
|
||||
db.create_table('archive_archive', (
|
||||
('id', orm['archive.Archive:id']),
|
||||
('created', orm['archive.Archive:created']),
|
||||
('modified', orm['archive.Archive:modified']),
|
||||
('published', orm['archive.Archive:published']),
|
||||
('name', orm['archive.Archive:name']),
|
||||
('user', orm['archive.Archive:user']),
|
||||
))
|
||||
db.send_create_signal('archive', ['Archive'])
|
||||
|
||||
# Adding model 'File'
|
||||
db.create_table('archive_file', (
|
||||
('id', orm['archive.File:id']),
|
||||
('created', orm['archive.File:created']),
|
||||
('modified', orm['archive.File:modified']),
|
||||
('verified', orm['archive.File:verified']),
|
||||
('oshash', orm['archive.File:oshash']),
|
||||
('movie', orm['archive.File:movie']),
|
||||
('name', orm['archive.File:name']),
|
||||
('sort_name', orm['archive.File:sort_name']),
|
||||
('part', orm['archive.File:part']),
|
||||
('version', orm['archive.File:version']),
|
||||
('language', orm['archive.File:language']),
|
||||
('season', orm['archive.File:season']),
|
||||
('episode', orm['archive.File:episode']),
|
||||
('size', orm['archive.File:size']),
|
||||
('duration', orm['archive.File:duration']),
|
||||
('info', orm['archive.File:info']),
|
||||
('video_codec', orm['archive.File:video_codec']),
|
||||
('pixel_format', orm['archive.File:pixel_format']),
|
||||
('display_aspect_ratio', orm['archive.File:display_aspect_ratio']),
|
||||
('width', orm['archive.File:width']),
|
||||
('height', orm['archive.File:height']),
|
||||
('framerate', orm['archive.File:framerate']),
|
||||
('audio_codec', orm['archive.File:audio_codec']),
|
||||
('channels', orm['archive.File:channels']),
|
||||
('samplerate', orm['archive.File:samplerate']),
|
||||
('bits_per_pixel', orm['archive.File:bits_per_pixel']),
|
||||
('pixels', orm['archive.File:pixels']),
|
||||
('is_audio', orm['archive.File:is_audio']),
|
||||
('is_video', orm['archive.File:is_video']),
|
||||
('is_extra', orm['archive.File:is_extra']),
|
||||
('is_main', orm['archive.File:is_main']),
|
||||
('is_subtitle', orm['archive.File:is_subtitle']),
|
||||
('is_version', orm['archive.File:is_version']),
|
||||
))
|
||||
db.send_create_signal('archive', ['File'])
|
||||
|
||||
# Adding model 'FileInstance'
|
||||
db.create_table('archive_fileinstance', (
|
||||
('id', orm['archive.FileInstance:id']),
|
||||
('created', orm['archive.FileInstance:created']),
|
||||
('modified', orm['archive.FileInstance:modified']),
|
||||
('published', orm['archive.FileInstance:published']),
|
||||
('accessed', orm['archive.FileInstance:accessed']),
|
||||
('path', orm['archive.FileInstance:path']),
|
||||
('folder', orm['archive.FileInstance:folder']),
|
||||
('file', orm['archive.FileInstance:file']),
|
||||
('archive', orm['archive.FileInstance:archive']),
|
||||
))
|
||||
db.send_create_signal('archive', ['FileInstance'])
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'Volume'
|
||||
db.delete_table('archive_volume')
|
||||
|
||||
# Deleting model 'Frame'
|
||||
db.delete_table('archive_frame')
|
||||
|
||||
# Deleting model 'Archive'
|
||||
db.delete_table('archive_archive')
|
||||
|
||||
# Deleting model 'File'
|
||||
db.delete_table('archive_file')
|
||||
|
||||
# Deleting model 'FileInstance'
|
||||
db.delete_table('archive_fileinstance')
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'archive.archive': {
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'owned_archives'", 'to': "orm['auth.User']"}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'symmetrical': 'False'}),
|
||||
'volumes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['archive.Volume']", 'symmetrical': 'False'})
|
||||
},
|
||||
'archive.file': {
|
||||
'audio_codec': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'bits_per_pixel': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'channels': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'display_aspect_ratio': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'duration': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'episode': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'framerate': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'info': ('fields.DictField', [], {'default': '{}'}),
|
||||
'is_audio': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_extra': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_subtitle': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_version': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_video': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'language': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
|
||||
'oshash': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
|
||||
'part': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
|
||||
'pixel_format': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'pixels': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'samplerate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'season': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||
'sort_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
|
||||
'verified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
|
||||
'video_codec': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'width': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'archive.fileinstance': {
|
||||
'accessed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'archive': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['archive.Archive']"}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'instances'", 'to': "orm['archive.File']"}),
|
||||
'folder': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'path': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
|
||||
'published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
'archive.frame': {
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'frames'", 'to': "orm['archive.File']"}),
|
||||
'frame': ('django.db.models.fields.files.ImageField', [], {'default': 'None', 'max_length': '100', 'null': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'position': ('django.db.models.fields.FloatField', [], {})
|
||||
},
|
||||
'archive.volume': {
|
||||
'end': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'start': ('django.db.models.fields.CharField', [], {'max_length': '1'})
|
||||
},
|
||||
'auth.group': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'unique_together': "(('content_type', 'codename'),)"},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'backend.movie': {
|
||||
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'imdb': ('fields.DictField', [], {'default': '{}', 'editable': 'False'}),
|
||||
'json': ('fields.DictField', [], {'default': '{}', 'editable': 'False'}),
|
||||
'metadata': ('fields.DictField', [], {'default': '{}', 'editable': 'False'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movieId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
|
||||
'oxdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '42', 'blank': 'True'}),
|
||||
'poster_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'poster_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'scene_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'stream_high': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'}),
|
||||
'stream_low': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'}),
|
||||
'stream_mid': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['archive']
|
||||
0
pandora/archive/migrations/__init__.py
Normal file
0
pandora/archive/migrations/__init__.py
Normal file
182
pandora/archive/models.py
Normal file
182
pandora/archive/models.py
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from datetime import datetime
|
||||
import os.path
|
||||
import random
|
||||
import re
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files.base import ContentFile
|
||||
from django.utils import simplejson as json
|
||||
from django.conf import settings
|
||||
|
||||
from oxdjango import fields
|
||||
import ox
|
||||
from ox import stripTags
|
||||
from ox.normalize import canonicalTitle, canonicalName
|
||||
from firefogg import Firefogg
|
||||
|
||||
from backend import utils
|
||||
from backend import extract
|
||||
from pandora.backend.models import Movie
|
||||
|
||||
def parse_decimal(string):
|
||||
string = string.replace(':', '/')
|
||||
if '/' not in string:
|
||||
string = '%s/1' % string
|
||||
d = string.split('/')
|
||||
return Decimal(d[0]) / Decimal(d[1])
|
||||
|
||||
#ARCHIVE stuff
|
||||
class Volume(models.Model):
|
||||
start = models.CharField(max_length=1)
|
||||
end = models.CharField(max_length=1)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
class Archive(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
published = models.DateTimeField(default=datetime.now, editable=False)
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
user = models.ForeignKey(User, related_name='owned_archives')
|
||||
|
||||
users = models.ManyToManyField(User, related_name='archives')
|
||||
volumes = models.ManyToManyField(Volume, related_name='archives')
|
||||
|
||||
def editable(self, user):
|
||||
return self.users.filter(username=user.username).count() > 0
|
||||
|
||||
class File(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
verified = models.BooleanField(default = False)
|
||||
|
||||
oshash = models.CharField(max_length=16)
|
||||
movie = models.ForeignKey(Movie, related_name='files')
|
||||
|
||||
name = models.CharField(max_length=2048, default="") # canoncial path/file
|
||||
sort_name = models.CharField(max_length=2048, default="") # sort path/file name
|
||||
|
||||
part = models.CharField(default="", max_length=255)
|
||||
version = models.CharField(default="", max_length=255) # sort path/file name
|
||||
language = models.CharField(default="", max_length=8)
|
||||
|
||||
season = models.IntegerField(default = -1)
|
||||
episode = models.IntegerField(default = -1)
|
||||
|
||||
size = models.BigIntegerField(default = 0)
|
||||
duration = models.IntegerField(default = 0)
|
||||
|
||||
info = fields.DictField(default={})
|
||||
|
||||
video_codec = models.CharField(max_length=255)
|
||||
pixel_format = models.CharField(max_length=255)
|
||||
display_aspect_ratio = models.CharField(max_length=255)
|
||||
width = models.IntegerField(default = 0)
|
||||
height = models.IntegerField(default = 0)
|
||||
framerate = models.CharField(max_length=255)
|
||||
|
||||
audio_codec = models.CharField(max_length=255)
|
||||
channels = models.IntegerField(default = 0)
|
||||
samplerate = models.IntegerField(default = 0)
|
||||
|
||||
bits_per_pixel = models.FloatField(default=-1)
|
||||
pixels = models.BigIntegerField(default=0)
|
||||
|
||||
is_audio = models.BooleanField(default = False)
|
||||
is_video = models.BooleanField(default = False)
|
||||
is_extra = models.BooleanField(default = False)
|
||||
is_main = models.BooleanField(default = False)
|
||||
is_subtitle = models.BooleanField(default = False)
|
||||
is_version = models.BooleanField(default = False)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.name and not self.sort_name:
|
||||
self.sort_name = canonicalTitle(self.name)
|
||||
if self.info:
|
||||
for key in ('duration', 'size'):
|
||||
setattr(self, key, self.info.get(key, 0))
|
||||
|
||||
if 'video' in self.info and self.info['video']:
|
||||
self.video_codec = self.info['video'][0]['codec']
|
||||
self.width = self.info['video'][0]['width']
|
||||
self.height = self.info['video'][0]['height']
|
||||
self.framerate = self.info['video'][0]['framerate']
|
||||
if 'display_aspect_ratio' in self.info['video'][0]:
|
||||
self.display_aspect_ratio = self.info['video'][0]['display_aspect_ratio']
|
||||
else:
|
||||
self.display_aspect_ratio = "%s:%s" % (self.width, self.height)
|
||||
self.is_video = True
|
||||
self.is_audio = False
|
||||
else:
|
||||
self.is_video = False
|
||||
if 'audio' in self.info and self.info['audio']:
|
||||
self.audio_codec = self.info['audio'][0]['codec']
|
||||
self.samplerate = self.info['audio'][0]['samplerate']
|
||||
self.channels = self.info['audio'][0]['channels']
|
||||
|
||||
if not self.is_video:
|
||||
self.is_audio = True
|
||||
else:
|
||||
self.is_audio = False
|
||||
|
||||
if self.framerate:
|
||||
self.pixels = int(self.width * self.height * float(parse_decimal(self.framerate)) * self.duration)
|
||||
|
||||
if not self.is_audio and not self.is_video and self.name.endswith('.srt'):
|
||||
self.is_subtitle = True
|
||||
|
||||
if self.name and self.name.startswith('Extra/'):
|
||||
self.is_extra = True
|
||||
self.is_main = False
|
||||
else:
|
||||
self.is_extra = False
|
||||
self.is_main = True
|
||||
|
||||
super(File, self).save(*args, **kwargs)
|
||||
|
||||
def json(self):
|
||||
r = {}
|
||||
for k in self:
|
||||
r[k] = unicode(self[k])
|
||||
return r
|
||||
|
||||
class FileInstance(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
published = models.DateTimeField(default=datetime.now, editable=False)
|
||||
accessed = models.DateTimeField(default=datetime.now, editable=False)
|
||||
|
||||
path = models.CharField(max_length=2048)
|
||||
folder = models.CharField(max_length=255)
|
||||
|
||||
file = models.ForeignKey(File, related_name='instances')
|
||||
archive = models.ForeignKey(Archive, related_name='files')
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s <%s> in %s'% (self.path, self.oshash, self.archive.name)
|
||||
|
||||
@property
|
||||
def movieId(self):
|
||||
return File.objects.get(oshash=self.oshash).movieId
|
||||
|
||||
class Frame(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
file = models.ForeignKey(File, related_name="frames")
|
||||
position = models.FloatField()
|
||||
frame = models.ImageField(default=None, null=True, upload_to=lambda f, x: frame_path(f))
|
||||
|
||||
#FIXME: frame path should be renamed on save to match current position
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s at %s' % (self.file, self.position)
|
||||
|
||||
23
pandora/archive/tests.py
Normal file
23
pandora/archive/tests.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
This file demonstrates two different styles of tests (one doctest and one
|
||||
unittest). These will both pass when you run "manage.py test".
|
||||
|
||||
Replace these with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.failUnlessEqual(1 + 1, 2)
|
||||
|
||||
__test__ = {"doctest": """
|
||||
Another way to test that 1 + 1 is equal to 2.
|
||||
|
||||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
|
||||
164
pandora/archive/views.py
Normal file
164
pandora/archive/views.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from __future__ import division
|
||||
import os.path
|
||||
import re
|
||||
from datetime import datetime
|
||||
from urllib2 import unquote
|
||||
import mimetypes
|
||||
|
||||
from django import forms
|
||||
from django.core.paginator import Paginator
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Q, Avg, Count, Sum
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
|
||||
from django.template import RequestContext
|
||||
from django.conf import settings
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
from django.utils import simplejson as json
|
||||
|
||||
from oxdjango.decorators import login_required_json
|
||||
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
|
||||
from oxdjango.http import HttpFileResponse
|
||||
import ox
|
||||
|
||||
import models
|
||||
|
||||
from backend.utils import oxid, parsePath
|
||||
import backend.models
|
||||
|
||||
|
||||
|
||||
#@login_required_json
|
||||
def api_update(request):
|
||||
'''
|
||||
param data
|
||||
{archive: string, files: json}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
'data': {info: object, rename: object}}
|
||||
'''
|
||||
data = json.loads(request.POST['data'])
|
||||
archive = data['archive']
|
||||
folder = data['folder']
|
||||
files = data['files']
|
||||
needs_data = []
|
||||
rename = []
|
||||
archive, created = models.Archive.objects.get_or_create(name=archive, user=request.user)
|
||||
if archive.editable(request.user):
|
||||
print 'editing'
|
||||
same_folder = models.FileInstance.objects.filter(folder=folder)
|
||||
if same_folder.count() > 0:
|
||||
movie = same_folder[0].file.movie
|
||||
else:
|
||||
movie = None
|
||||
for filename in files:
|
||||
data = files[filename]
|
||||
oshash = data['oshash']
|
||||
path = os.path.join(folder, filename)
|
||||
|
||||
instance = models.FileInstance.objects.filter(file__oshash=oshash)
|
||||
if instance.count()>0:
|
||||
instance = instance[0]
|
||||
if path != instance.path: #file was movied
|
||||
instance.path = path
|
||||
instance.folder = folder
|
||||
f.save()
|
||||
print "file movied, so other shit"
|
||||
else:
|
||||
#look if oshash is known
|
||||
f = models.File.objects.filter(oshash=oshash)
|
||||
if f.count() > 0:
|
||||
f = f[0]
|
||||
instance = models.FileInstance()
|
||||
instance.file = f
|
||||
instance.path=data['path']
|
||||
instance.folder=folder
|
||||
instance.save()
|
||||
movie = f.movie
|
||||
#new oshash, add to database
|
||||
else:
|
||||
if not movie:
|
||||
movie_info = parsePath(folder)
|
||||
movie = backend.models.getMovie(movie_info)
|
||||
f = models.File()
|
||||
f.oshash = oshash
|
||||
f.info = data
|
||||
del f.info['oshash']
|
||||
f.name = filename
|
||||
f.movie = movie
|
||||
f.save()
|
||||
instance = models.FileInstance()
|
||||
instance.archive = archive
|
||||
instance.file = f
|
||||
instance.path = path
|
||||
instance.folder = folder
|
||||
instance.save()
|
||||
|
||||
response = json_response({'info': needs_data, 'rename': rename})
|
||||
else:
|
||||
response = json_response(status=403, text='permission denied')
|
||||
return render_to_json_response(response)
|
||||
|
||||
@login_required_json
|
||||
def api_addArchive(request):
|
||||
'''
|
||||
ARCHIVE API NEEDS CLEANUP
|
||||
param data
|
||||
{name: string}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
'data': {}}
|
||||
'''
|
||||
data = json.loads(request.POST['data'])
|
||||
try:
|
||||
archive = models.Archive.objects.get(name=data['name'])
|
||||
response = {'status': {'code': 401, 'text': 'archive with this name exists'}}
|
||||
except models.Archive.DoesNotExist:
|
||||
archive = models.Archive(name=data['name'])
|
||||
archive.user = request.user
|
||||
archive.save()
|
||||
archive.users.add(request.user)
|
||||
response = json_response({})
|
||||
response['status']['text'] = 'archive created'
|
||||
return render_to_json_response(response)
|
||||
|
||||
@login_required_json
|
||||
def api_editArchive(request):
|
||||
'''
|
||||
ARCHIVE API NEEDS CLEANUP
|
||||
param data
|
||||
{id: string, key: value,..}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
'data': {}}
|
||||
'''
|
||||
data = json.loads(request.POST['data'])
|
||||
item = get_object_or_404_json(models.Archive, name=data['name'])
|
||||
if item.editable(request.user):
|
||||
response = json_response(status=501, text='not implemented')
|
||||
item.edit(data)
|
||||
else:
|
||||
response = json_response(status=403, text='permission denied')
|
||||
return render_to_json_response(response)
|
||||
|
||||
@login_required_json
|
||||
def api_removeArchive(request):
|
||||
'''
|
||||
ARCHIVE API NEEDS CLEANUP
|
||||
param data
|
||||
string id
|
||||
|
||||
return {'status': {'code': int, 'text': string}}
|
||||
'''
|
||||
response = json_response({})
|
||||
itemId = json.loads(request.POST['data'])
|
||||
item = get_object_or_404_json(models.Archive, movieId=itemId)
|
||||
if item.editable(request.user):
|
||||
response = json_response(status=501, text='not implemented')
|
||||
else:
|
||||
response = json_response(status=403, text='permission denied')
|
||||
return render_to_json_response(response)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue