move in preparation for virtualenv setup
This commit is contained in:
parent
ac65635b69
commit
973b3600af
33 changed files with 0 additions and 0 deletions
0
oxdb/__init__.py
Normal file
0
oxdb/__init__.py
Normal file
0
oxdb/app/__init__.py
Normal file
0
oxdb/app/__init__.py
Normal file
3
oxdb/app/models.py
Normal file
3
oxdb/app/models.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
23
oxdb/app/tests.py
Normal file
23
oxdb/app/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
|
||||
"""}
|
||||
|
||||
11
oxdb/app/views.py
Normal file
11
oxdb/app/views.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
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
|
||||
|
||||
|
||||
def index(request):
|
||||
context = RequestContext(request, {})
|
||||
return render_to_response('index.html', context)
|
||||
|
||||
0
oxdb/backend/__init__.py
Normal file
0
oxdb/backend/__init__.py
Normal file
173
oxdb/backend/load.py
Normal file
173
oxdb/backend/load.py
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
import random
|
||||
import os.path
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
import oxweb.imdb
|
||||
from oxlib import stripTags, findRe
|
||||
|
||||
import models
|
||||
|
||||
def debug(*msgs):
|
||||
for m in msgs:
|
||||
print m,
|
||||
print
|
||||
|
||||
'''Import data from imdb into database,
|
||||
param: impdb id
|
||||
return: Movie Object, None if failed
|
||||
'''
|
||||
|
||||
def loadIMDb(imdbId):
|
||||
if len(imdbId) != 7:
|
||||
debug("IMDb ID not valid")
|
||||
return None
|
||||
try:
|
||||
movie = models.Movie.byImdbId(imdbId)
|
||||
except models.Movie.DoesNotExist:
|
||||
#this shound not happen, just in case previous imports failed
|
||||
try:
|
||||
imdb = models.MovieImdb.objects.get(imdbId=imdbId)
|
||||
except models.MovieImdb.DoesNotExist:
|
||||
imdb = models.MovieImdb()
|
||||
imdb.imdbId = imdbId
|
||||
imdb.save()
|
||||
movie = models.Movie()
|
||||
movie.imdb = imdb
|
||||
|
||||
info = oxweb.imdb.getMovieInfo(imdbId)
|
||||
for key in ('title',
|
||||
'tagline',
|
||||
'year',
|
||||
'release_date',
|
||||
'rating',
|
||||
'votes',
|
||||
'series_imdb'
|
||||
'season',
|
||||
'episode'):
|
||||
if key in info:
|
||||
setattr(movie.imdb, key, info[key])
|
||||
debug(key, info[key])
|
||||
_info_map = {
|
||||
'episode title': 'episode_title',
|
||||
'series title': 'series_title',
|
||||
}
|
||||
for key in _info_map.keys():
|
||||
if key in info:
|
||||
setattr(movie.imdb, _info_map.get(key, key), info[key])
|
||||
|
||||
movie.imdb.plot = oxweb.imdb.getMoviePlot(imdbId)
|
||||
debug("plot", movie.imdb.plot)
|
||||
|
||||
movie.imdb.runtime = oxweb.imdb.getMovieRuntimeSeconds(imdbId)
|
||||
business = oxweb.imdb.getMovieBusinessSum(imdbId)
|
||||
for key in ('gross', 'profit', 'budget'):
|
||||
setattr(movie.imdb, key, business[key])
|
||||
|
||||
movie.imdb.save()
|
||||
movie.oxdbId = "__init__%s" % random.randint(0, 100000)
|
||||
movie.save()
|
||||
models.AlternativeTitle.objects.filter(movie=movie, manual=False).delete()
|
||||
for i in oxweb.imdb.getMovieAKATitles(imdbId):
|
||||
t = models.AlternativeTitle()
|
||||
t.movie = movie
|
||||
t.title = i[0]
|
||||
t.type = i[1]
|
||||
t.save()
|
||||
|
||||
#FIXME: related tables should be cleaned to not accumulate cruft
|
||||
#Country
|
||||
models.MovieCountry.objects.filter(movie=movie, manual=False).delete()
|
||||
position = 0
|
||||
if 'country' in info:
|
||||
for i in info['country']:
|
||||
debug("add country", i)
|
||||
country = models.Country.get_or_create(i)
|
||||
models.MovieCountry.link(movie, country, position)
|
||||
position += 1
|
||||
|
||||
#Language
|
||||
models.MovieLanguage.objects.filter(movie=movie, manual=False).delete()
|
||||
position = 0
|
||||
if 'language' in info:
|
||||
for i in info['language']:
|
||||
debug("add language", i)
|
||||
language = models.Language.get_or_create(i)
|
||||
models.MovieLanguage.link(movie, language, position)
|
||||
position += 1
|
||||
|
||||
#Location
|
||||
movie.locations_all.filter(manual=False).delete()
|
||||
locations = oxweb.imdb.getMovieLocations(imdbId)
|
||||
for i in locations:
|
||||
debug("add location", i)
|
||||
location = models.Location.get_or_create(i)
|
||||
location.movies.add(movie)
|
||||
|
||||
#Genre
|
||||
movie.genres_all.filter(manual=False).delete()
|
||||
if 'genre' in info:
|
||||
for i in info['genre']:
|
||||
debug("add genre", i)
|
||||
genre = models.Genre.get_or_create(i)
|
||||
genre.movies.add(movie)
|
||||
|
||||
#Keyword
|
||||
movie.keywords_all.filter(manual=False).delete()
|
||||
keywords = oxweb.imdb.getMovieKeywords(imdbId)
|
||||
for g in keywords:
|
||||
debug("add keyword", g)
|
||||
keyword = models.Keyword.get_or_create(g)
|
||||
keyword.movies.add(movie)
|
||||
|
||||
movie.trivia_all.filter(manual=False).delete()
|
||||
position = 0
|
||||
trivia = oxweb.imdb.getMovieTrivia(imdbId)
|
||||
for i in trivia:
|
||||
debug("add trivia", i)
|
||||
t = models.Trivia()
|
||||
t.movie = movie
|
||||
t.trivia = i
|
||||
t.position = position
|
||||
t.save()
|
||||
position += 1
|
||||
|
||||
position = 0
|
||||
models.Cast.objects.filter(movie=movie).filter(manual=False).delete()
|
||||
credits = oxweb.imdb.getMovieCredits(imdbId)
|
||||
for role in credits:
|
||||
for p in credits[role]:
|
||||
name = stripTags(p[0])
|
||||
imdb_id = findRe(p[0], 'nm(\d{7})')
|
||||
debug("add cast", name)
|
||||
#FIXME: we could save character information here
|
||||
character = stripTags(p[1])
|
||||
person = models.Person.get_or_create(name, imdb_id)
|
||||
models.Cast.link(movie, person, role, character, position)
|
||||
position += 1
|
||||
|
||||
movie.connections_all.filter(manual=False).delete()
|
||||
connections = oxweb.imdb.getMovieConnections(imdbId)
|
||||
for relation in connections:
|
||||
for otherId in connections[relation]:
|
||||
try:
|
||||
object = models.Movie.objects.get(imdb__imdbId=otherId)
|
||||
debug("add connection", relation, object)
|
||||
models.Connection.get_or_create(movie, relation, object)
|
||||
except models.Movie.DoesNotExist:
|
||||
pass
|
||||
|
||||
reviews = oxweb.imdb.getMovieExternalReviews(imdbId)
|
||||
movie.reviews_all.filter(manual=False).delete()
|
||||
for r in reviews:
|
||||
debug("add review", r)
|
||||
review = models.Review.get_or_create(movie, r)
|
||||
review.title = reviews[r]
|
||||
review.save()
|
||||
|
||||
movie.oxdbId = movie.oxid()
|
||||
movie.save()
|
||||
return movie
|
||||
|
||||
152
oxdb/backend/managers.py
Normal file
152
oxdb/backend/managers.py
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
import re
|
||||
from datetime import datetime
|
||||
from urllib2 import unquote
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Q, Manager
|
||||
|
||||
import models
|
||||
|
||||
|
||||
def keyType(key):
|
||||
if key in ('released'):
|
||||
return "date"
|
||||
if key in ('year', 'cast.length'):
|
||||
return "int"
|
||||
if key in ('rating', 'votes'):
|
||||
return "float"
|
||||
return "string"
|
||||
|
||||
class MovieManager(Manager):
|
||||
def get_query_set(self):
|
||||
return super(MovieManager, self).get_query_set()
|
||||
|
||||
def find(self, request):
|
||||
'''
|
||||
construct query set from q value in request,
|
||||
also checks for lists.
|
||||
range and order must be applied later
|
||||
'''
|
||||
q = ''
|
||||
for i in request.META['QUERY_STRING'].split('&'):
|
||||
if i.startswith('q='):
|
||||
q = i[2:]
|
||||
op = ','
|
||||
if '|' in q:
|
||||
op = '|'
|
||||
conditions = []
|
||||
for e in q.split(op):
|
||||
e = e.split(':')
|
||||
if len(e) == 1: e = ['all'] + e
|
||||
k, v = e
|
||||
exclude = False
|
||||
if v.startswith('!'):
|
||||
v = v[1:]
|
||||
exclude = True
|
||||
if keyType(k) == "string":
|
||||
startswith = v.startswith('^')
|
||||
endswith = v.endswith('$')
|
||||
if startswith and endswith:
|
||||
v = v[1:-1]
|
||||
k = '%s__iexact' % k
|
||||
elif startswith:
|
||||
v = v[1:]
|
||||
k = '%s__istartswith' % k
|
||||
elif v.endswith('$'):
|
||||
v = v[:-1]
|
||||
k = '%s__iendswith' % k
|
||||
else:
|
||||
k = '%s__icontains' % k
|
||||
k = 'find__%s' % k
|
||||
v = unquote(v)
|
||||
if exclude:
|
||||
conditions.append(~Q(**{k:v}))
|
||||
else:
|
||||
conditions.append(Q(**{k:v}))
|
||||
else:
|
||||
def parseDate(d):
|
||||
while len(d) < 3:
|
||||
d.append(1)
|
||||
return datetime(*[int(i) for i in d])
|
||||
#1960-1970
|
||||
match = re.compile("(-?[\d\.]+?)-(-?[\d\.]+$)").findall(v)
|
||||
if match:
|
||||
v1 = match[0][0]
|
||||
v2 = match[0][1]
|
||||
if keyType(k) == "date":
|
||||
v1 = parseDate(v1.split('.'))
|
||||
v2 = parseDate(v2.split('.'))
|
||||
if exclude: #!1960-1970
|
||||
k1 = str('%s__lt' % k)
|
||||
k2 = str('%s__gte' % k)
|
||||
conditions.append(Q(**{k1:v1})|Q(**{k2:v2}))
|
||||
else: #1960-1970
|
||||
k1 = str('%s__gte' % k)
|
||||
k2 = str('%s__lt' % k)
|
||||
conditions.append(Q(**{k1:v1})&Q(**{k2:v2}))
|
||||
else:
|
||||
if keyType(k) == "date":
|
||||
v = parseDate(v.split('.'))
|
||||
k = str('%s' % k)
|
||||
if exclude: #!1960
|
||||
conditions.append(~Q(**{k:v}))
|
||||
else: #1960
|
||||
conditions.append(Q(**{k:v}))
|
||||
|
||||
#join query with operator
|
||||
qs = self.get_query_set()
|
||||
#only include movies that have hard metadata
|
||||
qs = qs.filter(available=True)
|
||||
if conditions:
|
||||
q = conditions[0]
|
||||
for c in conditions[1:]:
|
||||
if op == '|':
|
||||
q = q | c
|
||||
else:
|
||||
q = q & c
|
||||
qs = qs.filter(q)
|
||||
|
||||
# filter list, works for own or public lists
|
||||
l = request.GET.get('l', 'all')
|
||||
if l != "all":
|
||||
l = l.split(":")
|
||||
only_public = True
|
||||
if not request.user.is_anonymous():
|
||||
if len(l) == 1: l = [request.user.username] + l
|
||||
if request.user.username == l[0]:
|
||||
only_public = False
|
||||
if len(l) == 2:
|
||||
lqs = models.List.objects.filter(name=l[1], user__username=l[0])
|
||||
if only_public:
|
||||
lqs = qls.filter(public=True)
|
||||
if lqs.count() == 1:
|
||||
qs = qs.filter(listitem__list__id=lqs[0].id)
|
||||
return qs
|
||||
|
||||
class FileManager(Manager):
|
||||
def get_query_set(self):
|
||||
return super(FileManager, self).get_query_set()
|
||||
|
||||
def movie_files(self, movie):
|
||||
q = self.get_query_set()
|
||||
return q.filter(is_video=True, movie=movie)
|
||||
|
||||
class ArchiveFileManager(Manager):
|
||||
def get_query_set(self):
|
||||
return super(ArchiveFileManager, self).get_query_set()
|
||||
|
||||
def movie_files(self, movie):
|
||||
q = self.get_query_set()
|
||||
return q.filter(file__is_video=True, file__movie=movie)
|
||||
|
||||
def by_oshash(self, oshash):
|
||||
q = self.get_query_set()
|
||||
q.filter(movie_file__oshash=oshash)
|
||||
if q.count() == 0:
|
||||
raise models.ArchiveFile.DoesNotExist("%s matching oshash %s does not exist." %
|
||||
(models.ArchiveFile._meta.object_name, oshash))
|
||||
return q[0]
|
||||
|
||||
722
oxdb/backend/migrations/0001_initial.py
Normal file
722
oxdb/backend/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,722 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from south.db import db
|
||||
from django.db import models
|
||||
from oxdb.backend.models import *
|
||||
|
||||
class Migration:
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'Trivia'
|
||||
db.create_table('backend_trivia', (
|
||||
('id', orm['backend.Trivia:id']),
|
||||
('trivia', orm['backend.Trivia:trivia']),
|
||||
('movie', orm['backend.Trivia:movie']),
|
||||
('position', orm['backend.Trivia:position']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Trivia'])
|
||||
|
||||
# Adding model 'AlternativeTitle'
|
||||
db.create_table('backend_alternativetitle', (
|
||||
('id', orm['backend.AlternativeTitle:id']),
|
||||
('movie', orm['backend.AlternativeTitle:movie']),
|
||||
('title', orm['backend.AlternativeTitle:title']),
|
||||
('type', orm['backend.AlternativeTitle:type']),
|
||||
))
|
||||
db.send_create_signal('backend', ['AlternativeTitle'])
|
||||
|
||||
# Adding model 'MovieLanguage'
|
||||
db.create_table('backend_movielanguage', (
|
||||
('id', orm['backend.MovieLanguage:id']),
|
||||
('movie', orm['backend.MovieLanguage:movie']),
|
||||
('language', orm['backend.MovieLanguage:language']),
|
||||
('position', orm['backend.MovieLanguage:position']),
|
||||
))
|
||||
db.send_create_signal('backend', ['MovieLanguage'])
|
||||
|
||||
# Adding model 'Movie'
|
||||
db.create_table('backend_movie', (
|
||||
('id', orm['backend.Movie:id']),
|
||||
('created', orm['backend.Movie:created']),
|
||||
('modified', orm['backend.Movie:modified']),
|
||||
('accessed', orm['backend.Movie:accessed']),
|
||||
('movieId', orm['backend.Movie:movieId']),
|
||||
('imdbId', orm['backend.Movie:imdbId']),
|
||||
('oxdbId', orm['backend.Movie:oxdbId']),
|
||||
('title', orm['backend.Movie:title']),
|
||||
('year', orm['backend.Movie:year']),
|
||||
('runtime', orm['backend.Movie:runtime']),
|
||||
('release_date', orm['backend.Movie:release_date']),
|
||||
('tagline', orm['backend.Movie:tagline']),
|
||||
('plot', orm['backend.Movie:plot']),
|
||||
('plot_outline', orm['backend.Movie:plot_outline']),
|
||||
('rating', orm['backend.Movie:rating']),
|
||||
('votes', orm['backend.Movie:votes']),
|
||||
('budget', orm['backend.Movie:budget']),
|
||||
('gross', orm['backend.Movie:gross']),
|
||||
('profit', orm['backend.Movie:profit']),
|
||||
('files_modified', orm['backend.Movie:files_modified']),
|
||||
('filename', orm['backend.Movie:filename']),
|
||||
('extracted', orm['backend.Movie:extracted']),
|
||||
('duration', orm['backend.Movie:duration']),
|
||||
('rights_level', orm['backend.Movie:rights_level']),
|
||||
('tpb_id', orm['backend.Movie:tpb_id']),
|
||||
('kg_id', orm['backend.Movie:kg_id']),
|
||||
('open_subtitle_id', orm['backend.Movie:open_subtitle_id']),
|
||||
('wikipedia_url', orm['backend.Movie:wikipedia_url']),
|
||||
('series_imdb', orm['backend.Movie:series_imdb']),
|
||||
('series_title', orm['backend.Movie:series_title']),
|
||||
('episode_title', orm['backend.Movie:episode_title']),
|
||||
('season', orm['backend.Movie:season']),
|
||||
('episode', orm['backend.Movie:episode']),
|
||||
('still_pos', orm['backend.Movie:still_pos']),
|
||||
('poster', orm['backend.Movie:poster']),
|
||||
('posters_disabled', orm['backend.Movie:posters_disabled']),
|
||||
('posters_available', orm['backend.Movie:posters_available']),
|
||||
('poster_height', orm['backend.Movie:poster_height']),
|
||||
('poster_width', orm['backend.Movie:poster_width']),
|
||||
('scene_height', orm['backend.Movie:scene_height']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Movie'])
|
||||
|
||||
# Adding model 'Archive'
|
||||
db.create_table('backend_archive', (
|
||||
('id', orm['backend.Archive:id']),
|
||||
('created', orm['backend.Archive:created']),
|
||||
('modified', orm['backend.Archive:modified']),
|
||||
('name', orm['backend.Archive:name']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Archive'])
|
||||
|
||||
# Adding model 'ArchiveFile'
|
||||
db.create_table('backend_archivefile', (
|
||||
('id', orm['backend.ArchiveFile:id']),
|
||||
('created', orm['backend.ArchiveFile:created']),
|
||||
('modified', orm['backend.ArchiveFile:modified']),
|
||||
('archive', orm['backend.ArchiveFile:archive']),
|
||||
('movie_file', orm['backend.ArchiveFile:movie_file']),
|
||||
('path', orm['backend.ArchiveFile:path']),
|
||||
))
|
||||
db.send_create_signal('backend', ['ArchiveFile'])
|
||||
|
||||
# Adding model 'Language'
|
||||
db.create_table('backend_language', (
|
||||
('id', orm['backend.Language:id']),
|
||||
('name', orm['backend.Language:name']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Language'])
|
||||
|
||||
# Adding model 'ReviewWhitelist'
|
||||
db.create_table('backend_reviewwhitelist', (
|
||||
('id', orm['backend.ReviewWhitelist:id']),
|
||||
('name', orm['backend.ReviewWhitelist:name']),
|
||||
('url', orm['backend.ReviewWhitelist:url']),
|
||||
))
|
||||
db.send_create_signal('backend', ['ReviewWhitelist'])
|
||||
|
||||
# Adding model 'MovieSort'
|
||||
db.create_table('backend_moviesort', (
|
||||
('id', orm['backend.MovieSort:id']),
|
||||
('movie', orm['backend.MovieSort:movie']),
|
||||
('title', orm['backend.MovieSort:title']),
|
||||
('director', orm['backend.MovieSort:director']),
|
||||
('country', orm['backend.MovieSort:country']),
|
||||
('year', orm['backend.MovieSort:year']),
|
||||
('producer', orm['backend.MovieSort:producer']),
|
||||
('writer', orm['backend.MovieSort:writer']),
|
||||
('editor', orm['backend.MovieSort:editor']),
|
||||
('cinematographer', orm['backend.MovieSort:cinematographer']),
|
||||
('language', orm['backend.MovieSort:language']),
|
||||
('runtime', orm['backend.MovieSort:runtime']),
|
||||
('keywords', orm['backend.MovieSort:keywords']),
|
||||
('genre', orm['backend.MovieSort:genre']),
|
||||
('cast', orm['backend.MovieSort:cast']),
|
||||
('summary', orm['backend.MovieSort:summary']),
|
||||
('trivia', orm['backend.MovieSort:trivia']),
|
||||
('connections', orm['backend.MovieSort:connections']),
|
||||
('scenes', orm['backend.MovieSort:scenes']),
|
||||
('words', orm['backend.MovieSort:words']),
|
||||
('wpm', orm['backend.MovieSort:wpm']),
|
||||
('risk', orm['backend.MovieSort:risk']),
|
||||
('movieId', orm['backend.MovieSort:movieId']),
|
||||
('duration', orm['backend.MovieSort:duration']),
|
||||
('resolution', orm['backend.MovieSort:resolution']),
|
||||
('aspectratio', orm['backend.MovieSort:aspectratio']),
|
||||
('bitrate', orm['backend.MovieSort:bitrate']),
|
||||
('pixels', orm['backend.MovieSort:pixels']),
|
||||
('filename', orm['backend.MovieSort:filename']),
|
||||
('files', orm['backend.MovieSort:files']),
|
||||
('size', orm['backend.MovieSort:size']),
|
||||
))
|
||||
db.send_create_signal('backend', ['MovieSort'])
|
||||
|
||||
# Adding model 'File'
|
||||
db.create_table('backend_file', (
|
||||
('id', orm['backend.File:id']),
|
||||
('created', orm['backend.File:created']),
|
||||
('modified', orm['backend.File:modified']),
|
||||
('oshash', orm['backend.File:oshash']),
|
||||
('sha1', orm['backend.File:sha1']),
|
||||
('md5', orm['backend.File:md5']),
|
||||
('movie', orm['backend.File:movie']),
|
||||
('computed_path', orm['backend.File:computed_path']),
|
||||
('size', orm['backend.File:size']),
|
||||
('duration', orm['backend.File:duration']),
|
||||
('video_codec', orm['backend.File:video_codec']),
|
||||
('pixel_format', orm['backend.File:pixel_format']),
|
||||
('width', orm['backend.File:width']),
|
||||
('height', orm['backend.File:height']),
|
||||
('pixel_aspect_ratio', orm['backend.File:pixel_aspect_ratio']),
|
||||
('display_aspect_ratio', orm['backend.File:display_aspect_ratio']),
|
||||
('framerate', orm['backend.File:framerate']),
|
||||
('audio_codec', orm['backend.File:audio_codec']),
|
||||
('samplerate', orm['backend.File:samplerate']),
|
||||
('channels', orm['backend.File:channels']),
|
||||
('bpp', orm['backend.File:bpp']),
|
||||
('pixels', orm['backend.File:pixels']),
|
||||
('part', orm['backend.File:part']),
|
||||
))
|
||||
db.send_create_signal('backend', ['File'])
|
||||
|
||||
# Adding model 'Country'
|
||||
db.create_table('backend_country', (
|
||||
('id', orm['backend.Country:id']),
|
||||
('name', orm['backend.Country:name']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Country'])
|
||||
|
||||
# Adding model 'Genre'
|
||||
db.create_table('backend_genre', (
|
||||
('id', orm['backend.Genre:id']),
|
||||
('name', orm['backend.Genre:name']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Genre'])
|
||||
|
||||
# Adding model 'MovieCountry'
|
||||
db.create_table('backend_moviecountry', (
|
||||
('id', orm['backend.MovieCountry:id']),
|
||||
('movie', orm['backend.MovieCountry:movie']),
|
||||
('country', orm['backend.MovieCountry:country']),
|
||||
('position', orm['backend.MovieCountry:position']),
|
||||
))
|
||||
db.send_create_signal('backend', ['MovieCountry'])
|
||||
|
||||
# Adding model 'Review'
|
||||
db.create_table('backend_review', (
|
||||
('id', orm['backend.Review:id']),
|
||||
('movie', orm['backend.Review:movie']),
|
||||
('title', orm['backend.Review:title']),
|
||||
('url', orm['backend.Review:url']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Review'])
|
||||
|
||||
# Adding model 'Subtitle'
|
||||
db.create_table('backend_subtitle', (
|
||||
('id', orm['backend.Subtitle:id']),
|
||||
('created', orm['backend.Subtitle:created']),
|
||||
('modified', orm['backend.Subtitle:modified']),
|
||||
('user', orm['backend.Subtitle:user']),
|
||||
('movie_file', orm['backend.Subtitle:movie_file']),
|
||||
('language', orm['backend.Subtitle:language']),
|
||||
('srt', orm['backend.Subtitle:srt']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Subtitle'])
|
||||
|
||||
# Adding model 'Cast'
|
||||
db.create_table('backend_cast', (
|
||||
('id', orm['backend.Cast:id']),
|
||||
('movie', orm['backend.Cast:movie']),
|
||||
('person', orm['backend.Cast:person']),
|
||||
('role', orm['backend.Cast:role']),
|
||||
('character', orm['backend.Cast:character']),
|
||||
('position', orm['backend.Cast:position']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Cast'])
|
||||
|
||||
# Adding model 'Person'
|
||||
db.create_table('backend_person', (
|
||||
('id', orm['backend.Person:id']),
|
||||
('name', orm['backend.Person:name']),
|
||||
('imdbId', orm['backend.Person:imdbId']),
|
||||
('name_sort', orm['backend.Person:name_sort']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Person'])
|
||||
|
||||
# Adding model 'Keyword'
|
||||
db.create_table('backend_keyword', (
|
||||
('id', orm['backend.Keyword:id']),
|
||||
('name', orm['backend.Keyword:name']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Keyword'])
|
||||
|
||||
# Adding model 'List'
|
||||
db.create_table('backend_list', (
|
||||
('id', orm['backend.List:id']),
|
||||
('created', orm['backend.List:created']),
|
||||
('modified', orm['backend.List:modified']),
|
||||
('user', orm['backend.List:user']),
|
||||
('name', orm['backend.List:name']),
|
||||
('public', orm['backend.List:public']),
|
||||
))
|
||||
db.send_create_signal('backend', ['List'])
|
||||
|
||||
# Adding model 'Connection'
|
||||
db.create_table('backend_connection', (
|
||||
('id', orm['backend.Connection:id']),
|
||||
('subject', orm['backend.Connection:subject']),
|
||||
('relation', orm['backend.Connection:relation']),
|
||||
('object', orm['backend.Connection:object']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Connection'])
|
||||
|
||||
# Adding model 'Location'
|
||||
db.create_table('backend_location', (
|
||||
('id', orm['backend.Location:id']),
|
||||
('name', orm['backend.Location:name']),
|
||||
('lat_sw', orm['backend.Location:lat_sw']),
|
||||
('lng_sw', orm['backend.Location:lng_sw']),
|
||||
('lat_ne', orm['backend.Location:lat_ne']),
|
||||
('lng_ne', orm['backend.Location:lng_ne']),
|
||||
('lat_center', orm['backend.Location:lat_center']),
|
||||
('lng_center', orm['backend.Location:lng_center']),
|
||||
('area', orm['backend.Location:area']),
|
||||
))
|
||||
db.send_create_signal('backend', ['Location'])
|
||||
|
||||
# Adding model 'MovieFind'
|
||||
db.create_table('backend_moviefind', (
|
||||
('id', orm['backend.MovieFind:id']),
|
||||
('movie', orm['backend.MovieFind:movie']),
|
||||
('all', orm['backend.MovieFind:all']),
|
||||
('title', orm['backend.MovieFind:title']),
|
||||
('director', orm['backend.MovieFind:director']),
|
||||
('country', orm['backend.MovieFind:country']),
|
||||
('year', orm['backend.MovieFind:year']),
|
||||
('language', orm['backend.MovieFind:language']),
|
||||
('writer', orm['backend.MovieFind:writer']),
|
||||
('producer', orm['backend.MovieFind:producer']),
|
||||
('editor', orm['backend.MovieFind:editor']),
|
||||
('cinematographer', orm['backend.MovieFind:cinematographer']),
|
||||
('cast', orm['backend.MovieFind:cast']),
|
||||
('genre', orm['backend.MovieFind:genre']),
|
||||
('keywords', orm['backend.MovieFind:keywords']),
|
||||
('summary', orm['backend.MovieFind:summary']),
|
||||
('trivia', orm['backend.MovieFind:trivia']),
|
||||
('locations', orm['backend.MovieFind:locations']),
|
||||
('filename', orm['backend.MovieFind:filename']),
|
||||
))
|
||||
db.send_create_signal('backend', ['MovieFind'])
|
||||
|
||||
# Adding model 'ListItem'
|
||||
db.create_table('backend_listitem', (
|
||||
('id', orm['backend.ListItem:id']),
|
||||
('created', orm['backend.ListItem:created']),
|
||||
('modified', orm['backend.ListItem:modified']),
|
||||
('list', orm['backend.ListItem:list']),
|
||||
('movie', orm['backend.ListItem:movie']),
|
||||
))
|
||||
db.send_create_signal('backend', ['ListItem'])
|
||||
|
||||
# Adding ManyToManyField 'Location.movies'
|
||||
db.create_table('backend_location_movies', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('location', models.ForeignKey(orm.Location, null=False)),
|
||||
('movie', models.ForeignKey(orm.Movie, null=False))
|
||||
))
|
||||
|
||||
# Adding ManyToManyField 'Archive.users'
|
||||
db.create_table('backend_archive_users', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('archive', models.ForeignKey(orm.Archive, null=False)),
|
||||
('user', models.ForeignKey(orm['auth.User'], null=False))
|
||||
))
|
||||
|
||||
# Adding ManyToManyField 'Keyword.movies'
|
||||
db.create_table('backend_keyword_movies', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('keyword', models.ForeignKey(orm.Keyword, null=False)),
|
||||
('movie', models.ForeignKey(orm.Movie, null=False))
|
||||
))
|
||||
|
||||
# Adding ManyToManyField 'Genre.movies'
|
||||
db.create_table('backend_genre_movies', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('genre', models.ForeignKey(orm.Genre, null=False)),
|
||||
('movie', models.ForeignKey(orm.Movie, null=False))
|
||||
))
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'Trivia'
|
||||
db.delete_table('backend_trivia')
|
||||
|
||||
# Deleting model 'AlternativeTitle'
|
||||
db.delete_table('backend_alternativetitle')
|
||||
|
||||
# Deleting model 'MovieLanguage'
|
||||
db.delete_table('backend_movielanguage')
|
||||
|
||||
# Deleting model 'Movie'
|
||||
db.delete_table('backend_movie')
|
||||
|
||||
# Deleting model 'Archive'
|
||||
db.delete_table('backend_archive')
|
||||
|
||||
# Deleting model 'ArchiveFile'
|
||||
db.delete_table('backend_archivefile')
|
||||
|
||||
# Deleting model 'Language'
|
||||
db.delete_table('backend_language')
|
||||
|
||||
# Deleting model 'ReviewWhitelist'
|
||||
db.delete_table('backend_reviewwhitelist')
|
||||
|
||||
# Deleting model 'MovieSort'
|
||||
db.delete_table('backend_moviesort')
|
||||
|
||||
# Deleting model 'File'
|
||||
db.delete_table('backend_file')
|
||||
|
||||
# Deleting model 'Country'
|
||||
db.delete_table('backend_country')
|
||||
|
||||
# Deleting model 'Genre'
|
||||
db.delete_table('backend_genre')
|
||||
|
||||
# Deleting model 'MovieCountry'
|
||||
db.delete_table('backend_moviecountry')
|
||||
|
||||
# Deleting model 'Review'
|
||||
db.delete_table('backend_review')
|
||||
|
||||
# Deleting model 'Subtitle'
|
||||
db.delete_table('backend_subtitle')
|
||||
|
||||
# Deleting model 'Cast'
|
||||
db.delete_table('backend_cast')
|
||||
|
||||
# Deleting model 'Person'
|
||||
db.delete_table('backend_person')
|
||||
|
||||
# Deleting model 'Keyword'
|
||||
db.delete_table('backend_keyword')
|
||||
|
||||
# Deleting model 'List'
|
||||
db.delete_table('backend_list')
|
||||
|
||||
# Deleting model 'Connection'
|
||||
db.delete_table('backend_connection')
|
||||
|
||||
# Deleting model 'Location'
|
||||
db.delete_table('backend_location')
|
||||
|
||||
# Deleting model 'MovieFind'
|
||||
db.delete_table('backend_moviefind')
|
||||
|
||||
# Deleting model 'ListItem'
|
||||
db.delete_table('backend_listitem')
|
||||
|
||||
# Dropping ManyToManyField 'Location.movies'
|
||||
db.delete_table('backend_location_movies')
|
||||
|
||||
# Dropping ManyToManyField 'Archive.users'
|
||||
db.delete_table('backend_archive_users')
|
||||
|
||||
# Dropping ManyToManyField 'Keyword.movies'
|
||||
db.delete_table('backend_keyword_movies')
|
||||
|
||||
# Dropping ManyToManyField 'Genre.movies'
|
||||
db.delete_table('backend_genre_movies')
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'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']", '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']", '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']", 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'backend.alternativetitle': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alternative_titles'", 'to': "orm['backend.Movie']"}),
|
||||
'title': ('django.db.models.fields.TextField', [], {}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
|
||||
},
|
||||
'backend.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', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'backend.archivefile': {
|
||||
'archive': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.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'}),
|
||||
'movie_file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.File']"}),
|
||||
'path': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'})
|
||||
},
|
||||
'backend.cast': {
|
||||
'character': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Person']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'role': ('django.db.models.fields.CharField', [], {'max_length': '200'})
|
||||
},
|
||||
'backend.connection': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'relation': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'subject': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'connections'", 'to': "orm['backend.Movie']"})
|
||||
},
|
||||
'backend.country': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.file': {
|
||||
'audio_codec': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||
'bpp': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'channels': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'computed_path': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'display_aspect_ratio': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||
'duration': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'framerate': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||
'height': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'md5': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'blank': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'files'", 'to': "orm['backend.Movie']"}),
|
||||
'oshash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '16', 'blank': 'True'}),
|
||||
'part': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'pixel_aspect_ratio': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||
'pixel_format': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||
'pixels': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'samplerate': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'sha1': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'blank': 'True'}),
|
||||
'size': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'video_codec': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||
'width': ('django.db.models.fields.IntegerField', [], {'default': '-1'})
|
||||
},
|
||||
'backend.genre': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.keyword': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.language': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.list': {
|
||||
'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'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'backend.listitem': {
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.List']"}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"})
|
||||
},
|
||||
'backend.location': {
|
||||
'area': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'lat_center': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lat_ne': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lat_sw': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lng_center': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lng_ne': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lng_sw': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.movie': {
|
||||
'accessed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'budget': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'duration': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'episode': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'episode_title': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'extracted': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'filename': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'files_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'gross': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'imdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '7', 'blank': 'True'}),
|
||||
'kg_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movieId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
|
||||
'open_subtitle_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'oxdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '42', 'blank': 'True'}),
|
||||
'plot': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'plot_outline': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'poster': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'poster_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'poster_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'posters_available': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'posters_disabled': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'profit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rating': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'release_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rights_level': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'runtime': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'scene_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'season': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'series_imdb': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '7'}),
|
||||
'series_title': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'still_pos': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'tagline': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'tpb_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'votes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'wikipedia_url': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'year': ('django.db.models.fields.CharField', [], {'max_length': '4'})
|
||||
},
|
||||
'backend.moviecountry': {
|
||||
'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Country']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'backend.moviefind': {
|
||||
'all': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'cast': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'cinematographer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'director': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'editor': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'filename': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'genre': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'language': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'locations': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'find'", 'unique': 'True', 'to': "orm['backend.Movie']"}),
|
||||
'producer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'trivia': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'writer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'year': ('django.db.models.fields.CharField', [], {'max_length': '4'})
|
||||
},
|
||||
'backend.movielanguage': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'language': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Language']"}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'backend.moviesort': {
|
||||
'aspectratio': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'bitrate': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'cast': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'cinematographer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'connections': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'director': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'duration': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'editor': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'filename': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'files': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'genre': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'keywords': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'language': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sort'", 'unique': 'True', 'to': "orm['backend.Movie']"}),
|
||||
'movieId': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'pixels': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'producer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'resolution': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'risk': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'runtime': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'scenes': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'summary': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'trivia': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'words': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'wpm': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'writer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'year': ('django.db.models.fields.CharField', [], {'max_length': '4'})
|
||||
},
|
||||
'backend.person': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'imdbId': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'name_sort': ('django.db.models.fields.CharField', [], {'max_length': '200'})
|
||||
},
|
||||
'backend.review': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reviews'", 'to': "orm['backend.Movie']"}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'})
|
||||
},
|
||||
'backend.reviewwhitelist': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
|
||||
},
|
||||
'backend.subtitle': {
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'language': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movie_file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.File']"}),
|
||||
'srt': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'backend.trivia': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'trivia'", 'to': "orm['backend.Movie']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'trivia': ('django.db.models.fields.TextField', [], {})
|
||||
},
|
||||
'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 = ['backend']
|
||||
349
oxdb/backend/migrations/0002_extend_movies.py
Normal file
349
oxdb/backend/migrations/0002_extend_movies.py
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from south.db import db
|
||||
from django.db import models
|
||||
from oxdb.backend.models import *
|
||||
|
||||
class Migration:
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding field 'Movie.available'
|
||||
db.add_column('backend_movie', 'available', orm['backend.movie:available'])
|
||||
|
||||
# Deleting field 'Movie.filename'
|
||||
db.delete_column('backend_movie', 'filename')
|
||||
|
||||
# Deleting field 'Movie.extracted'
|
||||
db.delete_column('backend_movie', 'extracted')
|
||||
|
||||
# Deleting field 'Movie.files_modified'
|
||||
db.delete_column('backend_movie', 'files_modified')
|
||||
|
||||
# Deleting model 'file'
|
||||
db.delete_table('backend_file')
|
||||
|
||||
# Deleting model 'archivefile'
|
||||
db.delete_table('backend_archivefile')
|
||||
|
||||
# Deleting model 'subtitle'
|
||||
db.delete_table('backend_subtitle')
|
||||
|
||||
# Deleting model 'archive'
|
||||
db.delete_table('backend_archive')
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting field 'Movie.available'
|
||||
db.delete_column('backend_movie', 'available')
|
||||
|
||||
# Adding field 'Movie.filename'
|
||||
db.add_column('backend_movie', 'filename', orm['backend.movie:filename'])
|
||||
|
||||
# Adding field 'Movie.extracted'
|
||||
db.add_column('backend_movie', 'extracted', orm['backend.movie:extracted'])
|
||||
|
||||
# Adding field 'Movie.files_modified'
|
||||
db.add_column('backend_movie', 'files_modified', orm['backend.movie:files_modified'])
|
||||
|
||||
# Adding model 'file'
|
||||
db.create_table('backend_file', (
|
||||
('computed_path', orm['backend.movie:computed_path']),
|
||||
('pixel_format', orm['backend.movie:pixel_format']),
|
||||
('height', orm['backend.movie:height']),
|
||||
('channels', orm['backend.movie:channels']),
|
||||
('audio_codec', orm['backend.movie:audio_codec']),
|
||||
('duration', orm['backend.movie:duration']),
|
||||
('samplerate', orm['backend.movie:samplerate']),
|
||||
('id', orm['backend.movie:id']),
|
||||
('size', orm['backend.movie:size']),
|
||||
('width', orm['backend.movie:width']),
|
||||
('movie', orm['backend.movie:movie']),
|
||||
('pixel_aspect_ratio', orm['backend.movie:pixel_aspect_ratio']),
|
||||
('oshash', orm['backend.movie:oshash']),
|
||||
('part', orm['backend.movie:part']),
|
||||
('display_aspect_ratio', orm['backend.movie:display_aspect_ratio']),
|
||||
('pixels', orm['backend.movie:pixels']),
|
||||
('md5', orm['backend.movie:md5']),
|
||||
('sha1', orm['backend.movie:sha1']),
|
||||
('created', orm['backend.movie:created']),
|
||||
('framerate', orm['backend.movie:framerate']),
|
||||
('modified', orm['backend.movie:modified']),
|
||||
('bpp', orm['backend.movie:bpp']),
|
||||
('video_codec', orm['backend.movie:video_codec']),
|
||||
))
|
||||
db.send_create_signal('backend', ['file'])
|
||||
|
||||
# Adding model 'archivefile'
|
||||
db.create_table('backend_archivefile', (
|
||||
('created', orm['backend.movie:created']),
|
||||
('modified', orm['backend.movie:modified']),
|
||||
('archive', orm['backend.movie:archive']),
|
||||
('movie_file', orm['backend.movie:movie_file']),
|
||||
('path', orm['backend.movie:path']),
|
||||
('id', orm['backend.movie:id']),
|
||||
))
|
||||
db.send_create_signal('backend', ['archivefile'])
|
||||
|
||||
# Adding model 'subtitle'
|
||||
db.create_table('backend_subtitle', (
|
||||
('language', orm['backend.movie:language']),
|
||||
('created', orm['backend.movie:created']),
|
||||
('modified', orm['backend.movie:modified']),
|
||||
('user', orm['backend.movie:user']),
|
||||
('srt', orm['backend.movie:srt']),
|
||||
('movie_file', orm['backend.movie:movie_file']),
|
||||
('id', orm['backend.movie:id']),
|
||||
))
|
||||
db.send_create_signal('backend', ['subtitle'])
|
||||
|
||||
# Adding model 'archive'
|
||||
db.create_table('backend_archive', (
|
||||
('name', orm['backend.movie:name']),
|
||||
('created', orm['backend.movie:created']),
|
||||
('modified', orm['backend.movie:modified']),
|
||||
('id', orm['backend.movie:id']),
|
||||
('users', orm['backend.movie:users']),
|
||||
))
|
||||
db.send_create_signal('backend', ['archive'])
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'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']", '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']", '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']", 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'backend.alternativetitle': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alternative_titles'", 'to': "orm['backend.Movie']"}),
|
||||
'title': ('django.db.models.fields.TextField', [], {}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
|
||||
},
|
||||
'backend.cast': {
|
||||
'character': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Person']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'role': ('django.db.models.fields.CharField', [], {'max_length': '200'})
|
||||
},
|
||||
'backend.connection': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'object': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'relation': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'subject': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'connections'", 'to': "orm['backend.Movie']"})
|
||||
},
|
||||
'backend.country': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.genre': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.keyword': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.language': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.list': {
|
||||
'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'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'backend.listitem': {
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.List']"}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"})
|
||||
},
|
||||
'backend.location': {
|
||||
'area': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'lat_center': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lat_ne': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lat_sw': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lng_center': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lng_ne': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'lng_sw': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
|
||||
},
|
||||
'backend.movie': {
|
||||
'accessed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'budget': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'duration': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'episode': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'episode_title': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'gross': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'imdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '7', 'blank': 'True'}),
|
||||
'kg_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'movieId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
|
||||
'open_subtitle_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'oxdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '42', 'blank': 'True'}),
|
||||
'plot': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'plot_outline': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'poster': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'poster_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'poster_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'posters_available': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'posters_disabled': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'profit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rating': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'release_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rights_level': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'runtime': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'scene_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'season': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'series_imdb': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '7'}),
|
||||
'series_title': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'still_pos': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'tagline': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'tpb_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'votes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'wikipedia_url': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'year': ('django.db.models.fields.CharField', [], {'max_length': '4'})
|
||||
},
|
||||
'backend.moviecountry': {
|
||||
'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Country']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'backend.moviefind': {
|
||||
'all': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'cast': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'cinematographer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'director': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'editor': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'filename': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'genre': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'language': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'locations': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'find'", 'unique': 'True', 'to': "orm['backend.Movie']"}),
|
||||
'producer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'trivia': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'writer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'year': ('django.db.models.fields.CharField', [], {'max_length': '4'})
|
||||
},
|
||||
'backend.movielanguage': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'language': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Language']"}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'backend.moviesort': {
|
||||
'aspectratio': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'bitrate': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'cast': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'cinematographer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'connections': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'director': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'duration': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||
'editor': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'filename': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'files': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'genre': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'keywords': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'language': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sort'", 'unique': 'True', 'to': "orm['backend.Movie']"}),
|
||||
'movieId': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
|
||||
'pixels': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'producer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'resolution': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'risk': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'runtime': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'scenes': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'summary': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'trivia': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
|
||||
'words': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'wpm': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'writer': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'year': ('django.db.models.fields.CharField', [], {'max_length': '4'})
|
||||
},
|
||||
'backend.person': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'imdbId': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}),
|
||||
'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'name_sort': ('django.db.models.fields.CharField', [], {'max_length': '200'})
|
||||
},
|
||||
'backend.review': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reviews'", 'to': "orm['backend.Movie']"}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'})
|
||||
},
|
||||
'backend.reviewwhitelist': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
|
||||
},
|
||||
'backend.trivia': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'trivia'", 'to': "orm['backend.Movie']"}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'trivia': ('django.db.models.fields.TextField', [], {})
|
||||
},
|
||||
'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 = ['backend']
|
||||
0
oxdb/backend/migrations/__init__.py
Normal file
0
oxdb/backend/migrations/__init__.py
Normal file
998
oxdb/backend/models.py
Normal file
998
oxdb/backend/models.py
Normal file
|
|
@ -0,0 +1,998 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
import re
|
||||
import os.path
|
||||
import random
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.models import User
|
||||
import oxlib
|
||||
from oxlib import stripTags
|
||||
from oxlib.normalize import canonicalTitle, canonicalName
|
||||
|
||||
import utils
|
||||
import managers
|
||||
|
||||
|
||||
class MovieImdb(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
imdbId = models.CharField(max_length=7, unique=True)
|
||||
title = models.CharField(max_length=1000)
|
||||
year = models.CharField(max_length=4)
|
||||
runtime = models.IntegerField(null=True, blank=True)
|
||||
release_date = models.DateField(null=True, blank=True)
|
||||
tagline = models.TextField(blank=True)
|
||||
plot = models.TextField(blank=True)
|
||||
plot_outline = models.TextField(blank=True)
|
||||
|
||||
rating = models.FloatField(null=True, blank=True)
|
||||
votes = models.IntegerField(null=True, blank=True)
|
||||
|
||||
budget = models.IntegerField(null=True, blank=True)
|
||||
gross = models.IntegerField(null=True, blank=True)
|
||||
profit = models.IntegerField(null=True, blank=True)
|
||||
|
||||
series_imdb = models.CharField(max_length=7, default='')
|
||||
series_title = models.TextField(blank=True, default='')
|
||||
episode_title = models.TextField(blank=True, default='')
|
||||
season = models.IntegerField(default=-1)
|
||||
episode = models.IntegerField(default=-1)
|
||||
|
||||
class MovieOxdb(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
title = models.CharField(max_length=1000)
|
||||
year = models.CharField(max_length=4)
|
||||
runtime = models.IntegerField(null=True, blank=True)
|
||||
release_date = models.DateField(null=True, blank=True)
|
||||
tagline = models.TextField(blank=True)
|
||||
plot = models.TextField(blank=True)
|
||||
plot_outline = models.TextField(blank=True)
|
||||
|
||||
rating = models.FloatField(null=True, blank=True)
|
||||
votes = models.IntegerField(null=True, blank=True)
|
||||
|
||||
budget = models.IntegerField(null=True, blank=True)
|
||||
gross = models.IntegerField(null=True, blank=True)
|
||||
profit = models.IntegerField(null=True, blank=True)
|
||||
|
||||
series_imdb = models.CharField(max_length=7, default='')
|
||||
series_title = models.TextField(blank=True, default='')
|
||||
episode_title = models.TextField(blank=True, default='')
|
||||
season = models.IntegerField(default=-1)
|
||||
episode = models.IntegerField(default=-1)
|
||||
|
||||
def newMovie(title, director, year):
|
||||
movie = Movie()
|
||||
oxdb = MovieOxdb()
|
||||
oxdb.save()
|
||||
movie.oxdb = oxdb
|
||||
movie.oxdb.title = title
|
||||
movie.oxdb.year = str(year)
|
||||
movie.oxdb.save()
|
||||
movie.oxdbId = "__init__%s" % random.randint(0, 100000)
|
||||
movie.save()
|
||||
movie.oxdbId = movie.oxid()
|
||||
movie.save()
|
||||
return movie
|
||||
|
||||
class Movie(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
#only movies that have metadata from files are available,
|
||||
#this is indicated by setting available to True
|
||||
available = models.BooleanField(default=False)
|
||||
|
||||
movieId = models.CharField(max_length=128, unique=True, blank=True)
|
||||
oxdbId = models.CharField(max_length=42, unique=True, blank=True)
|
||||
|
||||
imdb = models.OneToOneField('MovieImdb', null=True, related_name='movie')
|
||||
oxdb = models.OneToOneField('MovieOxdb', null=True, related_name='movie')
|
||||
|
||||
objects = managers.MovieManager()
|
||||
|
||||
def get(self, key, default=None):
|
||||
if self.oxdb and getattr(self.oxdb, key):
|
||||
return getattr(self.oxdb, key)
|
||||
if self.imdb:
|
||||
return getattr(self.imdb, key)
|
||||
return default
|
||||
|
||||
def _manual(self, qs, f='manual'):
|
||||
if qs.filter(**{f:True}).count() > 0:
|
||||
return qs.exclude(**{f:False})
|
||||
return qs.exclude(**{f:True})
|
||||
|
||||
def directors(self):
|
||||
qs = self.people.filter(cast__role='directors').order_by('cast__position')
|
||||
return self._manual(qs, 'cast__manual')
|
||||
def writers(self):
|
||||
qs = self.people.filter(cast__role='writers').order_by('cast__position')
|
||||
return self._manual(qs, 'cast__manual')
|
||||
def editors(self):
|
||||
qs = self.people.filter(cast__role='editors').order_by('cast__position')
|
||||
return self._manual(qs, 'cast__manual')
|
||||
def producers(self):
|
||||
qs = self.people.filter(cast__role='producers').order_by('cast__position')
|
||||
return self._manual(qs, 'cast__manual')
|
||||
def cinematographers(self):
|
||||
qs = self.people.filter(cast__role='cinematographers').order_by('cast__position')
|
||||
return self._manual(qs, 'cast__manual')
|
||||
|
||||
def cast(self):
|
||||
cast = []
|
||||
qs = Cast.objects.filter(movie=self, role='cast').order_by('position')
|
||||
qs = self._manual(qs)
|
||||
for c in qs:
|
||||
cast.append((c.person.name, c.character))
|
||||
return tuple(cast)
|
||||
|
||||
def alternative_titles(self):
|
||||
return self._manual(self.alternative_titles_all)
|
||||
def genres(self):
|
||||
return self._manual(self.genres_all)
|
||||
def keywords(self):
|
||||
return self._manual(self.keywords_all)
|
||||
def countries(self):
|
||||
return self._manual(self.countries_all, 'moviecountry__manual')
|
||||
def languages(self):
|
||||
return self._manual(self.languages_all, 'movielanguage__manual')
|
||||
def trivia(self):
|
||||
return self._manual(self.trivia_all)
|
||||
def locations(self):
|
||||
return self._manual(self.locations_all)
|
||||
def connections(self):
|
||||
return self._manual(self.connections_all)
|
||||
|
||||
def connections_json(self):
|
||||
connections = {}
|
||||
for connection in self.connections():
|
||||
if connection.relation not in connections:
|
||||
connections[connection.relation] = []
|
||||
connections[connection.relation].append(connection.object.movieId)
|
||||
return connections
|
||||
|
||||
def reviews(self):
|
||||
q = self.reviews_all.filter(manual=True)
|
||||
if q.count() > 0:
|
||||
return q
|
||||
whitelist = ReviewWhitelist.objects.all()
|
||||
q = Q(id=-1)
|
||||
for w in whitelist:
|
||||
q = q | Q(url__contains=w.url)
|
||||
return self.reviews_all.filter(q).filter(manual=False)
|
||||
|
||||
rights_level = models.IntegerField(default=-1)
|
||||
|
||||
#FIXME: use data.0xdb.org
|
||||
tpb_id = models.CharField(max_length=128, blank=True)
|
||||
kg_id = models.CharField(max_length=128, blank=True)
|
||||
open_subtitle_id = models.IntegerField(null=True, blank=True)
|
||||
wikipedia_url = models.TextField(blank=True)
|
||||
|
||||
#what of this is still required?
|
||||
still_pos = models.IntegerField(null=True, blank=True)
|
||||
poster = models.TextField(blank=True)
|
||||
posters_disabled = models.TextField(blank=True)
|
||||
posters_available = models.TextField(blank=True)
|
||||
poster_height = models.IntegerField(null=True, blank=True)
|
||||
poster_width = models.IntegerField(null=True, blank=True)
|
||||
|
||||
scene_height = models.IntegerField(null=True, blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s (%s)' % (self.get('title'), self.get('year'))
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.oxdb:
|
||||
oxdb = MovieOxdb()
|
||||
oxdb.save()
|
||||
self.oxdb = oxdb
|
||||
if self.imdb:
|
||||
mid = self.imdb.imdbId
|
||||
else:
|
||||
mid = self.oxdbId
|
||||
self.movieId = mid
|
||||
|
||||
super(Movie, self).save(*args, **kwargs)
|
||||
self.updateFind()
|
||||
self.updateSort()
|
||||
|
||||
_public_fields = {
|
||||
'movieId': 'id',
|
||||
'title': 'title',
|
||||
'year': 'year',
|
||||
|
||||
'runtime': 'runtime',
|
||||
'release_date': 'release_date',
|
||||
|
||||
'countries': 'country',
|
||||
'directors': 'director',
|
||||
'languages': 'language',
|
||||
'genres': 'genre',
|
||||
'keywords': 'keyword',
|
||||
'cast': 'cast',
|
||||
'series_title': 'series_title',
|
||||
'episode_title': 'episode_title',
|
||||
'season': 'season',
|
||||
'episode': 'episode',
|
||||
'reviews': 'reviews',
|
||||
'trivia': 'trivia',
|
||||
'rating': 'rating',
|
||||
'votes': 'votes',
|
||||
'alternative_titles': 'alternative_titles',
|
||||
'connections_json': 'connections'
|
||||
}
|
||||
def json(self, fields=None):
|
||||
movie = {}
|
||||
for key in self._public_fields:
|
||||
pub_key = self._public_fields.get(key, key)
|
||||
if not fields or pub_key in fields:
|
||||
if hasattr(self, key):
|
||||
value = getattr(self, key)
|
||||
else:
|
||||
value = self.get(key)
|
||||
if key in ('directors', 'writers', 'reviews',
|
||||
'countries', 'languages', 'keywords', 'genres', 'trivia', 'alternative_titles'):
|
||||
movie[pub_key] = tuple([v.json() for v in value()])
|
||||
elif callable(value):
|
||||
movie[pub_key] = value()
|
||||
else:
|
||||
movie[pub_key] = value
|
||||
if fields:
|
||||
for f in fields:
|
||||
if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'):
|
||||
movie[f] = getattr(self.sort.all()[0], f[:-7])
|
||||
return movie
|
||||
|
||||
def fields(self):
|
||||
fields = {}
|
||||
for f in self._meta.fields:
|
||||
if f.name in self._public_fields:
|
||||
fields[f.name] = {}
|
||||
fields[f.name]['order'] = 'desc'
|
||||
fields[f.name]['type'] = type(f)
|
||||
return fields
|
||||
fields = classmethod(fields)
|
||||
|
||||
#Class functions to get Movies by ID, right now movieId, imdbId and oxdbId
|
||||
#FIXME: this should go into a manager
|
||||
def byMovieId(self, movieId):
|
||||
if len(movieId) == 7:
|
||||
return self.byImdbId(movieId)
|
||||
return self.byOxdbId(movieId)
|
||||
byMovieId = classmethod(byMovieId)
|
||||
|
||||
def byImdbId(self, imdbId):
|
||||
return self.objects.get(imdb__imdbId=imdbId)
|
||||
byImdbId = classmethod(byImdbId)
|
||||
|
||||
def byOxdbId(self, oxdbId):
|
||||
return self.objects.get(oxdbId=oxdbId)
|
||||
byOxdbId = classmethod(byOxdbId)
|
||||
|
||||
def oxid(self):
|
||||
directors = ','.join([d.name for d in self.directors()])
|
||||
return utils.oxid(self.get('title', ''), directors, self.get('year', ''),
|
||||
self.get('series_title', ''), self.get('episode_title', ''),
|
||||
self.get('season', ''), self.get('episode', ''))
|
||||
|
||||
def updateFind(self):
|
||||
try:
|
||||
f = self.find
|
||||
except MovieFind.DoesNotExist:
|
||||
f = MovieFind(movie=self)
|
||||
|
||||
f.title = self.get('title') + ' '.join([t.title for t in self.alternative_titles()])
|
||||
f.director = ' '.join([i.name for i in self.directors()])
|
||||
f.country = ' '.join([i.name for i in self.countries()])
|
||||
f.year = self.get('year', '')
|
||||
f.language = ' '.join([i.name for i in self.languages()])
|
||||
f.writer = ' '.join([i.name for i in self.writers()])
|
||||
f.producer = ' '.join([i.name for i in self.producers()])
|
||||
f.editor = ' '.join([i.name for i in self.editors()])
|
||||
f.cinematographer = ' '.join([i.name for i in self.cinematographers()])
|
||||
f.cast = ' '.join(['%s %s' % i for i in self.cast()])
|
||||
f.genre = ' '.join([i.name for i in self.genres()])
|
||||
f.keywords = ' '.join([i.name for i in self.keywords()])
|
||||
f.summary = self.get('plot', '') + self.get('plot_outline', '')
|
||||
f.trivia = ' '.join([i.trivia for i in self.trivia()])
|
||||
f.location = ' '.join([i.name for i in self.locations()])
|
||||
#FIXME: collate filenames
|
||||
#f.filename = self.filename
|
||||
f.all = ' '.join(filter(None, [f.title, f.director, f.country, f.year, f.language,
|
||||
f.writer, f.producer, f.editor, f.cinematographer,
|
||||
f.cast, f.genre, f.keywords, f.summary, f.trivia,
|
||||
f.location, f.filename]))
|
||||
f.save()
|
||||
|
||||
def updateSort(self):
|
||||
try:
|
||||
s = self.sort
|
||||
except MovieSort.DoesNotExist:
|
||||
s = MovieSort(movie=self)
|
||||
|
||||
def sortName(value):
|
||||
sort_value = '~'
|
||||
if value:
|
||||
sort_value = stripTags(value).split(',')
|
||||
sort_value = '; '.join([canonicalName(name.strip()) for name in sort_value])
|
||||
sort_value = sort_value.replace(u'\xc5k', 'A')
|
||||
if not sort_value:
|
||||
sort_value = '~'
|
||||
return sort_value
|
||||
|
||||
#title
|
||||
title = canonicalTitle(self.get('title'))
|
||||
title = re.sub(u'[\'!¿¡,\.;\-"\:\*\[\]]', '', title)
|
||||
title = title.replace(u'Æ', 'Ae')
|
||||
#pad numbered titles
|
||||
numbers = re.compile('^(\d+)').findall(title)
|
||||
if numbers:
|
||||
padded = '%010d' % int(numbers[0])
|
||||
title = re.sub('^(\d+)', padded, title)
|
||||
|
||||
s.title = title.strip()
|
||||
|
||||
directors = ','.join([i.name for i in self.directors()])
|
||||
s.director = sortName(directors)
|
||||
|
||||
s.country = ','.join([i.name for i in self.countries()])
|
||||
s.year = self.get('year', '')
|
||||
|
||||
names = ','.join([i.name for i in self.producers()])
|
||||
s.producer = sortName(names)
|
||||
names = ','.join([i.name for i in self.writers()])
|
||||
s.writer = sortName(names)
|
||||
names = ','.join([i.name for i in self.editors()])
|
||||
s.editor = sortName(names)
|
||||
names = ','.join([i.name for i in self.cinematographers()])
|
||||
s.cinematographer = sortName(names)
|
||||
|
||||
s.language = ','.join([i.name for i in self.languages()])
|
||||
s.country = ','.join([i.name for i in self.countries()])
|
||||
s.runtime = self.get('runtime', 0)
|
||||
|
||||
s.keywords = self.keywords().count()
|
||||
s.genre = self.genres().count()
|
||||
s.cast = len(self.cast())
|
||||
s.summary = len(self.get('plot', '').split())
|
||||
s.trivia = self.trivia().count()
|
||||
s.connections = self.connections().count()
|
||||
s.movieId = self.movieId
|
||||
s.rating = self.get('rating', -1)
|
||||
s.votes = self.get('votes', -1)
|
||||
|
||||
# data from related subtitles
|
||||
s.scenes = 0 #FIXME
|
||||
s.words = 0 #FIXME
|
||||
s.wpm = 0 #FIXME
|
||||
s.risk = 0 #FIXME
|
||||
# data from related files
|
||||
s.duration = 0 #FIXME
|
||||
s.resolution = 0 #FIXME
|
||||
s.aspectratio = 0 #FIXME
|
||||
s.bitrate = 0 #FIXME
|
||||
s.pixels = 0 #FIXME
|
||||
s.filename = 0 #FIXME
|
||||
s.files = 0 #FIXME
|
||||
s.size = 0 #FIXME
|
||||
s.save()
|
||||
|
||||
class MovieFind(models.Model):
|
||||
"""
|
||||
used to search movies, all search values are in here
|
||||
"""
|
||||
movie = models.OneToOneField('Movie', related_name='find', primary_key=True)
|
||||
|
||||
all = models.TextField(blank=True)
|
||||
title = models.CharField(max_length=1000)
|
||||
director = models.TextField(blank=True, default='')
|
||||
country = models.TextField(blank=True, default='')
|
||||
year = models.CharField(max_length=4)
|
||||
language = models.TextField(blank=True, default='')
|
||||
writer = models.TextField(blank=True, default='')
|
||||
producer = models.TextField(blank=True, default='')
|
||||
editor = models.TextField(blank=True, default='')
|
||||
cinematographer = models.TextField(blank=True, default='')
|
||||
cast = models.TextField(blank=True, default='')
|
||||
#person
|
||||
|
||||
genre = models.TextField(blank=True)
|
||||
keywords = models.TextField(blank=True)
|
||||
summary = models.TextField(blank=True)
|
||||
trivia = models.TextField(blank=True)
|
||||
locations = models.TextField(blank=True, default='')
|
||||
|
||||
#only for own files or as admin?
|
||||
filename = models.TextField(blank=True, default='')
|
||||
|
||||
_private_fields = ('id', 'movie')
|
||||
_public_names = {
|
||||
'movieId': 'id'
|
||||
}
|
||||
def options(self):
|
||||
options = []
|
||||
for f in self._meta.fields:
|
||||
if f.name not in self._private_fields:
|
||||
name = f.name
|
||||
name = self._public_names.get(name, name)
|
||||
options.append((name, 'Find: %s' % name.capitalize()))
|
||||
return tuple(options)
|
||||
options = classmethod(options)
|
||||
|
||||
class MovieSort(models.Model):
|
||||
"""
|
||||
used to sort movies, all sort values are in here
|
||||
"""
|
||||
movie = models.OneToOneField('Movie', related_name='sort', primary_key=True)
|
||||
|
||||
title = models.CharField(max_length=1000)
|
||||
director = models.TextField(blank=True)
|
||||
country = models.TextField(blank=True)
|
||||
year = models.CharField(max_length=4)
|
||||
|
||||
producer = models.TextField(blank=True)
|
||||
writer = models.TextField(blank=True)
|
||||
editor = models.TextField(blank=True)
|
||||
cinematographer = models.TextField(blank=True)
|
||||
|
||||
language = models.TextField(blank=True)
|
||||
runtime = models.IntegerField(blank=True, null=True)
|
||||
|
||||
keywords = models.IntegerField(blank=True)
|
||||
genre = models.TextField(blank=True)
|
||||
cast = models.IntegerField(blank=True)
|
||||
summary = models.IntegerField(blank=True)
|
||||
trivia = models.IntegerField(blank=True)
|
||||
connections = models.IntegerField(blank=True)
|
||||
|
||||
rating = models.FloatField(blank=True)
|
||||
votes = models.IntegerField(blank=True)
|
||||
scenes = models.IntegerField(blank=True)
|
||||
words = models.IntegerField(null=True, blank=True)
|
||||
wpm = models.IntegerField(null=True, blank=True)
|
||||
risk = models.IntegerField(null=True, blank=True)
|
||||
|
||||
movieId = models.CharField(max_length=128, blank=True)
|
||||
|
||||
duration = models.FloatField(default=-1)
|
||||
resolution = models.IntegerField(blank=True)
|
||||
aspectratio = models.IntegerField(blank=True)
|
||||
bitrate = models.IntegerField(blank=True)
|
||||
pixels = models.IntegerField(blank=True)
|
||||
filename = models.IntegerField(blank=True)
|
||||
files = models.IntegerField(blank=True)
|
||||
size = models.IntegerField(blank=True)
|
||||
|
||||
_private_fields = ('id', 'movie')
|
||||
_public_names = {
|
||||
'movieId': 'id'
|
||||
}
|
||||
def options(self):
|
||||
options = []
|
||||
for f in self._meta.fields:
|
||||
if f.name not in self._private_fields:
|
||||
name = f.name
|
||||
name = self._public_names.get(name, name)
|
||||
options.append((name, 'Sort: %s' % name.capitalize()))
|
||||
return tuple(options)
|
||||
options = classmethod(options)
|
||||
|
||||
class AlternativeTitle(models.Model):
|
||||
movie = models.ForeignKey(Movie, related_name='alternative_titles_all')
|
||||
title = models.TextField()
|
||||
type = models.CharField(max_length=1000)
|
||||
manual = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ('title', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def json(self):
|
||||
return (self.title, self.type)
|
||||
|
||||
def get_or_create(model, name):
|
||||
try:
|
||||
o = model.objects.get(name=name)
|
||||
except model.DoesNotExist:
|
||||
o = model.objects.create(name=name)
|
||||
o.save()
|
||||
return o
|
||||
|
||||
class Person(models.Model):
|
||||
name = models.CharField(max_length=200)
|
||||
imdbId = models.CharField(max_length=7, blank=True)
|
||||
name_sort = models.CharField(max_length=200)
|
||||
movies = models.ManyToManyField(Movie, related_name='people', through='Cast')
|
||||
|
||||
class Meta:
|
||||
ordering = ('name_sort', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.name_sort:
|
||||
self.name_sort = oxlib.normalize.canonicalName(self.name)
|
||||
super(Person, self).save(*args, **kwargs)
|
||||
|
||||
def get_or_create(model, name, imdbId=None):
|
||||
if imdbId:
|
||||
q = model.objects.filter(name=name, imdbId=imdbId)
|
||||
else:
|
||||
q = model.objects.all().filter(name=name)
|
||||
if q.count() > 0:
|
||||
o = q[0]
|
||||
else:
|
||||
o = model.objects.create(name=name)
|
||||
if imdbId:
|
||||
o.imdbId = imdbId
|
||||
o.save()
|
||||
return o
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def json(self):
|
||||
return self.name
|
||||
|
||||
class Cast(models.Model):
|
||||
movie = models.ForeignKey(Movie)
|
||||
person = models.ForeignKey(Person)
|
||||
role = models.CharField(max_length=200)
|
||||
character = models.CharField(max_length=200, blank=True)
|
||||
position = models.IntegerField()
|
||||
manual = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ('position', 'person__name_sort')
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s <> %s" % (self.person, self.movie)
|
||||
|
||||
def link(self, movie, person, role, character, position, manual=False):
|
||||
q = self.objects.filter(movie=movie, person=person, role=role, character=character)
|
||||
if q.count() > 0:
|
||||
link = q[0]
|
||||
link.position = position
|
||||
link.manual = manual
|
||||
link.save()
|
||||
else:
|
||||
link = self()
|
||||
link.movie=movie
|
||||
link.person=person
|
||||
link.role=role
|
||||
link.character=character
|
||||
link.position = position
|
||||
link.manual = manual
|
||||
link.save()
|
||||
return link
|
||||
link = classmethod(link)
|
||||
|
||||
def json(self):
|
||||
return (self.person.json(), self.character)
|
||||
|
||||
class Country(models.Model):
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
movies = models.ManyToManyField(Movie, related_name='countries_all', through='MovieCountry')
|
||||
|
||||
class Meta:
|
||||
#!! adding this to ordering, breaks:
|
||||
# models.Country.objects.values("name").annotate(movies=Count('movies'))
|
||||
#'moviecountry__position',
|
||||
ordering = ('name', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def json(self):
|
||||
return self.name
|
||||
|
||||
class MovieCountry(models.Model):
|
||||
movie = models.ForeignKey(Movie)
|
||||
country = models.ForeignKey(Country)
|
||||
position = models.IntegerField()
|
||||
manual = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ('position', 'country')
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s <> %s" % (self.country, self.movie)
|
||||
|
||||
def link(self, movie, country, position):
|
||||
q = self.objects.filter(movie=movie, country=country)
|
||||
if q.count() > 0:
|
||||
link = q[0]
|
||||
link.position = position
|
||||
link.save()
|
||||
else:
|
||||
link = self()
|
||||
link.movie=movie
|
||||
link.country=country
|
||||
link.position=position
|
||||
link.save()
|
||||
return link
|
||||
link = classmethod(link)
|
||||
|
||||
class Language(models.Model):
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
movies = models.ManyToManyField(Movie, related_name='languages_all', through="MovieLanguage")
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def json(self):
|
||||
return self.name
|
||||
|
||||
class MovieLanguage(models.Model):
|
||||
movie = models.ForeignKey(Movie)
|
||||
language = models.ForeignKey(Language)
|
||||
position = models.IntegerField()
|
||||
manual = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ('position', 'language')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.language.name
|
||||
|
||||
def link(self, movie, language, position):
|
||||
q = self.objects.filter(movie=movie, language=language)
|
||||
if q.count() > 0:
|
||||
link = q[0]
|
||||
link.position = position
|
||||
link.save()
|
||||
else:
|
||||
link = self()
|
||||
link.movie=movie
|
||||
link.language=language
|
||||
link.position=position
|
||||
link.save()
|
||||
return link
|
||||
link = classmethod(link)
|
||||
|
||||
class Keyword(models.Model):
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
manual = models.BooleanField(default=False)
|
||||
movies = models.ManyToManyField(Movie, related_name='keywords_all')
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def json(self):
|
||||
return self.name
|
||||
|
||||
class Genre(models.Model):
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
manual = models.BooleanField(default=False)
|
||||
movies = models.ManyToManyField(Movie, related_name='genres_all')
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def json(self):
|
||||
return self.name
|
||||
|
||||
class Location(models.Model):
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
manual = models.BooleanField(default=False)
|
||||
movies = models.ManyToManyField(Movie, related_name='locations_all')
|
||||
#fixme: geo data
|
||||
|
||||
lat_sw = models.FloatField(default=0)
|
||||
lng_sw = models.FloatField(default=0)
|
||||
lat_ne = models.FloatField(default=0)
|
||||
lng_ne = models.FloatField(default=0)
|
||||
lat_center = models.FloatField(default=0)
|
||||
lng_center = models.FloatField(default=0)
|
||||
area = models.FloatField(default=-1)
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def json(self):
|
||||
return self.name
|
||||
|
||||
class Trivia(models.Model):
|
||||
trivia = models.TextField()
|
||||
manual = models.BooleanField(default=False)
|
||||
position = models.IntegerField()
|
||||
movie = models.ForeignKey(Movie, related_name='trivia_all')
|
||||
|
||||
class Meta:
|
||||
ordering = ('position', )
|
||||
|
||||
def __unicode__(self):
|
||||
return self.trivia
|
||||
|
||||
def json(self):
|
||||
trivia = self.trivia
|
||||
trivia = oxlib.fixAmpersands(trivia)
|
||||
trivia = re.sub('<a href="(/name/nm.*?)">(.*?)</a>', '<a href="/?f=name&q=\\2">\\2</a>', trivia)
|
||||
trivia = re.sub('<a href="/title/tt(.*?)/">(.*?)</a>', '<a href="/\\1">\\2</a>', trivia)
|
||||
return trivia
|
||||
|
||||
class Connection(models.Model):
|
||||
subject = models.ForeignKey(Movie, related_name='connections_all')
|
||||
relation = models.CharField(max_length=512)
|
||||
object = models.ForeignKey(Movie)
|
||||
manual = models.BooleanField(default=False)
|
||||
|
||||
def get_or_create(model, subject, relation, object, reverse=True, manual=False):
|
||||
q = model.objects.filter(subject=subject, relation=relation, object=object)
|
||||
if q.count() > 0:
|
||||
o = q[0]
|
||||
else:
|
||||
o = model.objects.create(subject=subject, relation=relation, object=object, manual=manual)
|
||||
o.save()
|
||||
if reverse:
|
||||
_map = {
|
||||
'Edited into': 'Edited from',
|
||||
'Features': 'Featured in',
|
||||
'Follows': 'Followed by',
|
||||
'References': 'Referenced in',
|
||||
'Remake of': 'Remade as',
|
||||
'Spin off from': 'Spin off',
|
||||
'Spoofs': 'Spoofed in',
|
||||
'Version of': 'Version of',
|
||||
}
|
||||
if relation in _map.values():
|
||||
for k in _map:
|
||||
if _map[k] == relation:
|
||||
reverse_relation = k
|
||||
else:
|
||||
reverse_relation = _map[relation]
|
||||
o2 = model.get_or_create(object, reverse_relation, subject, reverse=False)
|
||||
return o
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s %s %s' % (self.subject, self.relation, self.object)
|
||||
|
||||
class Review(models.Model):
|
||||
movie = models.ForeignKey('Movie', related_name='reviews_all')
|
||||
title = models.CharField(blank=True, max_length=2048)
|
||||
url = models.CharField(blank=True, max_length=2048)
|
||||
manual = models.BooleanField(default=False)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def get_or_create(self, movie, url):
|
||||
q = self.objects.filter(movie=movie, url=url)
|
||||
if q.count() > 0:
|
||||
o = q[0]
|
||||
else:
|
||||
o = self.objects.create(movie=movie, url=url)
|
||||
o.save()
|
||||
return o
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def name(self):
|
||||
for w in ReviewWhitelist.objects.all():
|
||||
if w.url in self.url:
|
||||
return w.name
|
||||
return self.title
|
||||
|
||||
def json(self):
|
||||
return (self.name(), self.url)
|
||||
|
||||
class ReviewWhitelist(models.Model):
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
url = models.CharField(max_length=255, unique=True)
|
||||
|
||||
class List(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
user = models.ForeignKey(User)
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
public = models.BooleanField(default=False)
|
||||
movies = models.ManyToManyField(Movie, related_name='lists', through='ListItem')
|
||||
|
||||
def add(self, movie):
|
||||
q = self.movies.filter(id=movie.id)
|
||||
if q.count() == 0:
|
||||
l = ListItem()
|
||||
l.list = self
|
||||
l.movie = movie
|
||||
l.save()
|
||||
|
||||
def remove(self, movie):
|
||||
self.ListItem.objects.all().filter(movie=movie, list=self).delete()
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s (%s)' % (self.title, unicode(self.user))
|
||||
|
||||
class ListItem(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
list = models.ForeignKey(List)
|
||||
movie = models.ForeignKey(Movie)
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s in %s' % (unicode(self.movie), unicode(self.list))
|
||||
|
||||
def stream_path(f, size):
|
||||
name = "%s.%s" % (size, 'ogv')
|
||||
url_hash = f.oshash
|
||||
return os.path.join('stream', url_hash[:2], url_hash[2:4], url_hash[4:6], name)
|
||||
|
||||
class File(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
oshash = models.CharField(blank=True, unique=True, max_length=16)
|
||||
sha1 = models.CharField(blank=True, unique=True, max_length=40)
|
||||
md5 = models.CharField(blank=True, unique=True, max_length=32)
|
||||
|
||||
movie = models.ForeignKey(Movie, related_name="files", default=None)
|
||||
|
||||
computed_path = models.CharField(blank=True, max_length=2048)
|
||||
size = models.IntegerField(default=-1)
|
||||
duration = models.FloatField(default=-1)
|
||||
|
||||
is_video = models.BooleanField(default=False)
|
||||
|
||||
video_codec = models.CharField(blank=True, max_length=256)
|
||||
pixel_format = models.CharField(blank=True, max_length=256)
|
||||
width = models.IntegerField(default=-1)
|
||||
height = models.IntegerField(default=-1)
|
||||
pixel_aspect_ratio = models.CharField(blank=True, max_length=256)
|
||||
display_aspect_ratio = models.CharField(blank=True, max_length=256)
|
||||
framerate = models.CharField(blank=True, max_length=256)
|
||||
|
||||
audio_codec = models.CharField(blank=True, max_length=256)
|
||||
samplerate = models.IntegerField(default=-1)
|
||||
channels = models.IntegerField(default=-1)
|
||||
|
||||
#computed values
|
||||
bpp = models.FloatField(default=-1)
|
||||
pixels = models.IntegerField(default=0)
|
||||
|
||||
part = models.IntegerField(default=0)
|
||||
|
||||
#stream related fields
|
||||
available = models.BooleanField(default=False)
|
||||
stream128 = models.FileField(default=None, upload_to=lambda f, x: stream_path(f, '128'))
|
||||
stream320 = models.FileField(default=None, upload_to=lambda f, x: stream_path(f, '320'))
|
||||
stream640 = models.FileField(default=None, upload_to=lambda f, x: stream_path(f, '640'))
|
||||
|
||||
def save_chunk(self, chunk, name='video.ogv'):
|
||||
if not self.available:
|
||||
#FIXME: this should use stream128 or stream640 depending on configuration
|
||||
video = getattr(self, 'stream128')
|
||||
if not video:
|
||||
video.save(name, ContentFile(chunk))
|
||||
self.save()
|
||||
else:
|
||||
f = open(video.path, 'a')
|
||||
f.write(chunk)
|
||||
f.close()
|
||||
return True
|
||||
return False
|
||||
|
||||
objects = managers.FileManager()
|
||||
|
||||
def get_or_create(model, oshash):
|
||||
try:
|
||||
f = model.objects.get(oshash=oshash)
|
||||
except model.DoesNotExist:
|
||||
f = model.objects.create(oshash=oshash)
|
||||
f.save()
|
||||
return f
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s (%s)" % (self.computed_path, self.oshash)
|
||||
|
||||
class Subtitle(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
user = models.ForeignKey(User)
|
||||
|
||||
file = models.ForeignKey(File, related_name="subtitles")
|
||||
language = models.CharField(max_length=16)
|
||||
srt = models.TextField(blank=True)
|
||||
|
||||
def get_or_create(model, user, oshash, language):
|
||||
q = model.objects.filter(file__oshash=oshash, language=language, user=user)
|
||||
if q.count() > 0:
|
||||
s = q[0]
|
||||
else:
|
||||
f = models.File.get_or_create(oshash=oshash)
|
||||
s = model.objects.create(user=user, language=language, file=f)
|
||||
s.save()
|
||||
return s
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s.%s.srt' % (os.path.splitext(self.movie_file.computed_path)[0], self.language)
|
||||
|
||||
class Layer(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
user = models.ForeignKey(User)
|
||||
movie = models.ForeignKey(Movie)
|
||||
|
||||
#seconds
|
||||
time_in = models.FloatField(default=-1)
|
||||
time_out = models.FloatField(default=-1)
|
||||
|
||||
type = models.CharField(blank=True, max_length=255)
|
||||
value = models.TextField()
|
||||
|
||||
#location = models.ForeignKey('Location', default=None)
|
||||
|
||||
class Archive(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
public = models.BooleanField(default=False)
|
||||
users = models.ManyToManyField(User, related_name='archives')
|
||||
|
||||
class ArchiveFile(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
archive = models.ForeignKey(Archive, related_name='files')
|
||||
file = models.ForeignKey(File)
|
||||
path = models.CharField(blank=True, max_length=2048)
|
||||
|
||||
objects = managers.ArchiveFileManager()
|
||||
|
||||
def update(self, data):
|
||||
"""
|
||||
only add, do not overwrite keys in file
|
||||
"""
|
||||
for key in ('duration', 'video_codec', 'pixel_format', 'width', 'height',
|
||||
'pixel_aspect_ratio', 'display_aspect_ratio', 'framerate',
|
||||
'audio_codec', 'samplerate', 'channels', 'size', 'sha1', 'md5'):
|
||||
if key in data and not getattr(self.file, key):
|
||||
setattr(self.file, key, data[key])
|
||||
self.path = data.get('path', '')
|
||||
self.file.save()
|
||||
self.save()
|
||||
|
||||
def get_or_create(model, archive, oshash):
|
||||
try:
|
||||
f = model.objects.by_oshash(oshash=oshash)
|
||||
except model.DoesNotExist:
|
||||
f = model.objects.create()
|
||||
f.file = File.get_or_create(oshash)
|
||||
f.archive = archive
|
||||
f.save()
|
||||
return f
|
||||
get_or_create = classmethod(get_or_create)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s (%s)' % (self.path, unicode(self.user))
|
||||
|
||||
|
||||
46
oxdb/backend/urls.py
Normal file
46
oxdb/backend/urls.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
# from django.contrib import admin
|
||||
# admin.autodiscover()
|
||||
|
||||
'''
|
||||
files/find
|
||||
files/info
|
||||
files/add
|
||||
files/remove
|
||||
|
||||
movies/find
|
||||
movies/get
|
||||
movies/edit?movie_id...
|
||||
|
||||
subtitles/list?oshash
|
||||
subtitles/get?oshash&language
|
||||
subtitles/add?oshash&language
|
||||
subtitles/remove?oshash&language
|
||||
'''
|
||||
|
||||
urlpatterns = patterns("oxdb.backend.views",
|
||||
(r'^find', 'find'),
|
||||
(r'^files/find', 'find_files'),
|
||||
(r'^files/info', 'file_info'),
|
||||
(r'^archive/(?P<archive>.+)/add', 'add_file'),
|
||||
(r'^archive/(?P<archive>.+)/remove', 'remove_file'),
|
||||
(r'^file/parse', 'file_parse'),
|
||||
(r'^subtitle/get', 'subtitles'),
|
||||
|
||||
# Example:
|
||||
# (r'^oxdata/', include('oxdata.foo.urls')),
|
||||
|
||||
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
||||
# to INSTALLED_APPS to enable admin documentation:
|
||||
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
# (r'^admin/(.*)', admin.site.root),
|
||||
)
|
||||
|
||||
#add user urls. login, logout, preferences etc
|
||||
import user_management.urls
|
||||
urlpatterns += user_management.urls.urlpatterns
|
||||
|
||||
127
oxdb/backend/utils.py
Normal file
127
oxdb/backend/utils.py
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
#
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import hashlib
|
||||
|
||||
import oxlib
|
||||
import oxlib.iso
|
||||
from oxlib.normalize import normalizeName
|
||||
|
||||
def oxid(title, director, year='', seriesTitle='', episodeTitle='', season=0, episode=0):
|
||||
oxid_value = u"\n".join([title, director, year])
|
||||
oxid = hashlib.sha1(oxid_value.encode('utf-8')).hexdigest()
|
||||
if seriesTitle:
|
||||
oxid_value = u"\n".join([seriesTitle, "%02d" % season])
|
||||
oxid = hashlib.sha1(oxid_value.encode('utf-8')).hexdigest()[:20]
|
||||
oxid_value = u"\n".join(["%02d" % episode, episodeTitle, director, year])
|
||||
oxid += hashlib.sha1(oxid_value.encode('utf-8')).hexdigest()[:20]
|
||||
return u"0x" + oxid
|
||||
|
||||
def oxdb_director(director):
|
||||
director = os.path.basename(os.path.dirname(director))
|
||||
if director.endswith('_'):
|
||||
director = "%s." % director[:-1]
|
||||
director = ", ".join([normalizeName(d) for d in director.split('; ')])
|
||||
director = director.replace('Series', '')
|
||||
director = director.replace('Unknown Director', '')
|
||||
director = director.replace('Various Directors', '')
|
||||
return director
|
||||
|
||||
def oxdb_title(_title, searchTitle = False):
|
||||
'''
|
||||
normalize filename to get movie title
|
||||
'''
|
||||
_title = os.path.basename(_title)
|
||||
_title = _title.replace('... ', '_dot_dot_dot_')
|
||||
_title = _title.replace('. ', '_dot__space_')
|
||||
_title = _title.replace(' .', '_space__dot_')
|
||||
title = _title.split('.')[0]
|
||||
title = re.sub('([a-z0-9])_ ', '\\1: ', title)
|
||||
se = re.compile('Season (\d+).Episode (\d+)').findall(_title)
|
||||
if se:
|
||||
se = "S%02dE%02d" % (int(se[0][0]), int(se[0][1]))
|
||||
if 'Part' in _title.split('.')[-2] and 'Episode' not in _title.split('.')[-3]:
|
||||
stitle = _title.split('.')[-3]
|
||||
else:
|
||||
stitle = _title.split('.')[-2]
|
||||
if stitle.startswith('Episode '):
|
||||
stitle = ''
|
||||
if searchTitle:
|
||||
title = '"%s" %s' % (title, stitle)
|
||||
else:
|
||||
title = '%s (%s) %s' % (title, se, stitle)
|
||||
title = title.strip()
|
||||
title = title.replace('_dot_dot_dot_', '... ')
|
||||
title = title.replace('_dot__space_', '. ')
|
||||
title = title.replace('_space__dot_', ' .')
|
||||
return title
|
||||
|
||||
def oxdb_year(data):
|
||||
return oxlib.findRe(data, '\.(\d{4})\.')
|
||||
|
||||
def oxdb_series_title(path):
|
||||
seriesTitle = u''
|
||||
if path.startswith('Series'):
|
||||
seriesTitle = os.path.basename(os.path.dirname(path))
|
||||
else:
|
||||
t = oxdb_title(path)
|
||||
if " (S" in t:
|
||||
seriesTitle = t.split(" (S")[0]
|
||||
return seriesTitle
|
||||
|
||||
def oxdb_episode_title(path):
|
||||
episodeTitle = u''
|
||||
ep = re.compile('.Episode \d+?\.(.*?)\.[a-zA-Z]').findall(path)
|
||||
if ep:
|
||||
episodeTitle = ep[0][0]
|
||||
return episodeTitle
|
||||
|
||||
def oxdb_season_episode(path):
|
||||
season = 0
|
||||
episode = 0
|
||||
path = os.path.basename(path)
|
||||
se = re.compile('Season (\d+).Episode (\d+)').findall(path)
|
||||
if se:
|
||||
season = int(se[0][0])
|
||||
episode = int(se[0][1])
|
||||
else:
|
||||
ep = re.compile('.Episode (\d+?)').findall(path)
|
||||
if ep:
|
||||
episode = int(ep[0][0])
|
||||
if season == 0 and episode == 0:
|
||||
se = re.compile('S(\d\d)E(\d\d)').findall(path)
|
||||
if se:
|
||||
season = int(se[0][0])
|
||||
episode = int(se[0][1])
|
||||
return (season, episode)
|
||||
|
||||
def oxdb_part(path):
|
||||
part = 1
|
||||
path = path.lower()
|
||||
p = re.compile('part\s*?(\d+)\.').findall(path)
|
||||
if p:
|
||||
part = p[0]
|
||||
else:
|
||||
p = re.compile('cd\s*?(\d+)\.').findall(path)
|
||||
if p:
|
||||
part = p[0]
|
||||
return part
|
||||
|
||||
def parsePath(path):
|
||||
import oxweb.imdb
|
||||
search_title = oxdb_title(path, True)
|
||||
r = {}
|
||||
r['title'] = oxdb_title(path)
|
||||
r['director'] = oxdb_director(path)
|
||||
r['episode_title'] = oxdb_episode_title(path)
|
||||
r['season'], r['episode'] = oxdb_season_episode(path)
|
||||
r['series'] = oxdb_series_title(path)
|
||||
r['part'] = oxdb_part(path)
|
||||
r['imdbId'] = oxweb.imdb.guess(search_title, r['director'])
|
||||
return r
|
||||
|
||||
362
oxdb/backend/views.py
Normal file
362
oxdb/backend/views.py
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
import os.path
|
||||
import re
|
||||
from datetime import datetime
|
||||
from urllib2 import unquote
|
||||
|
||||
from django.db.models import Q, Avg, Count
|
||||
from django.contrib.auth.models import User
|
||||
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
|
||||
from django.template import RequestContext
|
||||
from django.core.paginator import Paginator
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils import simplejson as json
|
||||
from oxdb.utils.shortcuts import render_to_json_response
|
||||
from oxdb.utils.decorators import login_required_json
|
||||
|
||||
import models
|
||||
import utils
|
||||
|
||||
'''
|
||||
field.length -> movie.sort.all()[0].field
|
||||
o=0&n=100
|
||||
|
||||
|
||||
a & b | c & d
|
||||
|
||||
query
|
||||
|
||||
l=user:name or l=name
|
||||
q=year:1980,hello,country:usa
|
||||
q=year:1980,hello,country:!usa
|
||||
q=title:^the$
|
||||
q=title:^100%24$
|
||||
q=year:<1970,year:>1960
|
||||
q=year:<1960,year:>1950,title:sex
|
||||
|
||||
!1960-1970
|
||||
2009.08.02.22.26.35-2009.08.02.22.26.35
|
||||
|
||||
!^the
|
||||
|
||||
(dddd.dd.dd)-(dddd.dd.dd)
|
||||
|
||||
5-8
|
||||
10000-20000
|
||||
|
||||
<2009-08-02-22-26-35
|
||||
|
||||
>2009-08-02-22-26-35
|
||||
2009-08-02-22-26-35<
|
||||
|
||||
^the the*
|
||||
*foo foo$
|
||||
*foo* foo
|
||||
|
||||
s=director:asc,year:desc default: director:asc,year:desc
|
||||
r=0:100 or r=100 or r=100: default: 0:100
|
||||
p=id,title,director,date,cast.length default: title,director,year,country
|
||||
q
|
||||
|
||||
List data backend spec:
|
||||
url = //url for request
|
||||
params = [] //additional params passed to url, i.e. query, or group
|
||||
|
||||
the url must understand the following requests:
|
||||
number of items:
|
||||
url?params&n=1
|
||||
> {items: N}
|
||||
items sorted by key range X to Y:
|
||||
url?params&s=key:asc|desc&r=X:Y
|
||||
> {items: [{k0:v0, k1:v1...}, {k0:v0, k1:v1...}]}
|
||||
|
||||
Examples:
|
||||
/json/find?l=all&s=title&f=all&q=&a=desc&p=id,title,director,date,cast.length
|
||||
|
||||
/json/find?r=0:100&l=all&s=title&f=all&q=&a=desc&p=id,title,director,date,cast.length
|
||||
{
|
||||
movies=[
|
||||
{
|
||||
"id":
|
||||
"title": "fsdf",
|
||||
"director":
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
#get sort order for all ids
|
||||
/json/find?r=0:1000&l=all&s=title&f=all&q=&a=desc&p=id
|
||||
{
|
||||
movies=[
|
||||
{
|
||||
"id": id
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/json/find?l=all&s=title&f=all&q=&a=desc
|
||||
{
|
||||
movies: 1234,
|
||||
files: 2345,
|
||||
pixels: 1242345345,
|
||||
size: 1235,
|
||||
duration: 1235,
|
||||
|
||||
}
|
||||
|
||||
/json/find?r=0:100&l=all&s=[name, items]&f=all&q=&a=desc&g=country
|
||||
{
|
||||
groups = [ {name:"USA", movies: 123}, {name:"UK", movies: 1234} ]
|
||||
}
|
||||
|
||||
#find as you type: in table, by sort string
|
||||
|
||||
#auto compleat in find box
|
||||
|
||||
'''
|
||||
def order_query(qs, s, prefix='sort__'):
|
||||
order_by = []
|
||||
for e in s.split(','):
|
||||
o = e.split(':')
|
||||
if len(o) == 1: o.append('asc')
|
||||
order = {'id': 'movieId'}.get(o[0], o[0])
|
||||
order = '%s%s' % (prefix, order)
|
||||
if o[1] == 'desc':
|
||||
order = '-%s' % order
|
||||
order_by.append(order)
|
||||
if order_by:
|
||||
qs = qs.order_by(*order_by)
|
||||
return qs
|
||||
|
||||
def parse_query(request):
|
||||
get = request.GET
|
||||
query = {}
|
||||
query['i'] = 0
|
||||
query['o'] = 100
|
||||
query['s'] = 'title:asc'
|
||||
def parse_dict(s):
|
||||
d = s.split(",")
|
||||
return [i.strip() for i in d]
|
||||
_dicts = ['p', ]
|
||||
_ints = ['n', ]
|
||||
for key in ('s', 'p', 'g', 'l', 'n'):
|
||||
if key in get:
|
||||
if key in _ints:
|
||||
query[key] = int(get[key])
|
||||
elif key in _dicts:
|
||||
query[key] = parse_dict(get[key])
|
||||
else:
|
||||
query[key] = get[key]
|
||||
query['q'] = models.Movie.objects.find(request)
|
||||
if 'r' in get:
|
||||
r = get['r'].split(':')
|
||||
if len(r) == 1: r.append(0)
|
||||
if r[0] == '': r[0] = 0
|
||||
if r[1] == '': r[0] = -1
|
||||
query['i'] = int(r[0])
|
||||
query['o'] = int(r[1])
|
||||
#group by only allows sorting by name or number of itmes
|
||||
return query
|
||||
|
||||
def find(request):
|
||||
query = parse_query(request)
|
||||
response = {}
|
||||
if 'p' in query:
|
||||
response['items'] = []
|
||||
qs = order_query(query['q'], query['s'])
|
||||
if 'n' in query:
|
||||
response = {'items': qs.count()}
|
||||
else:
|
||||
qs = qs[query['i']:query['o']]
|
||||
print qs.query.as_sql()
|
||||
p = Paginator(qs, 100)
|
||||
for i in p.page_range:
|
||||
page = p.page(i)
|
||||
for m in page.object_list:
|
||||
response['items'].append(m.json(query['p']))
|
||||
elif 'g' in query:
|
||||
if query['s'].split(':')[0] not in ('name', 'items'):
|
||||
query['s'] = 'name'
|
||||
#FIXME: also filter lists here
|
||||
response['items'] = []
|
||||
name = 'name'
|
||||
items = 'movies'
|
||||
movie_qs = query['q']
|
||||
_objects = {
|
||||
'country': models.Country.objects,
|
||||
'genre': models.Genre.objects,
|
||||
'language': models.Language.objects,
|
||||
'director': models.Person.objects.filter(cast__role='directors'),
|
||||
}
|
||||
if query['g'] in _objects:
|
||||
qs = _objects[query['g']].filter(movies__id__in=movie_qs).values('name').annotate(movies=Count('movies'))
|
||||
elif query['g'] == "year":
|
||||
qs = movie_qs.values('imdb__year').annotate(movies=Count('id'))
|
||||
name='imdb__year'
|
||||
if 'n' in query:
|
||||
response['items'] = qs.count()
|
||||
else:
|
||||
#replace normalized items/name sort with actual db value
|
||||
order_by = query['s'].split(":")
|
||||
if len(order_by) == 1:
|
||||
order_by.append('desc')
|
||||
if order_by[0] == 'name':
|
||||
order_by = "%s:%s" % (name, order_by[1])
|
||||
else:
|
||||
order_by = "%s:%s" % (items, order_by[1])
|
||||
qs = order_query(qs, order_by, '')
|
||||
qs = qs[query['i']:query['o']]
|
||||
for i in qs:
|
||||
group = {'title': i[name], 'items': i[items]}
|
||||
response['items'].append(group)
|
||||
else:
|
||||
#FIXME: also filter lists here
|
||||
movies = models.Movie.objects.filter(available=True)
|
||||
files = models.File.objects.all()
|
||||
response['items'] = movies.count()
|
||||
response['files'] = files.count()
|
||||
r = files.aggregate(Count('size'), Count('pixels'), Count('duration'))
|
||||
response['pixels'] = r['pixels__count']
|
||||
response['size'] = r['size__count']
|
||||
response['duration'] = r['duration__count']
|
||||
return render_to_json_response(response)
|
||||
|
||||
'''
|
||||
GET info?oshash=a41cde31c581e11d
|
||||
> {
|
||||
"movie_id": 0123456,
|
||||
"duration": 5.266667,
|
||||
"video_codec": "mpeg1",
|
||||
"pixel_format": "yuv420p",
|
||||
"width": 352,
|
||||
"height": 240,
|
||||
"pixel_aspect_ratio": "1:1",
|
||||
"display_aspect_ratio": "22:15",
|
||||
"framerate": "30:1",
|
||||
"audio_codec": "mp2",
|
||||
"samplerate": 44100,
|
||||
"channels": 1,
|
||||
"path": "E/Example, The/An Example.avi",
|
||||
"size": 1646274
|
||||
"oshash": "a41cde31c581e11d",
|
||||
"sha1":..,
|
||||
"md5":..
|
||||
}
|
||||
'''
|
||||
def file_info(request):
|
||||
oshash = request.GET['oshash']
|
||||
f = models.MovieFile.objects.get(oshash=oshash)
|
||||
response = f.json()
|
||||
return render_to_json_response(response)
|
||||
|
||||
|
||||
'''
|
||||
GET subtitles?oshash=a41cde31c581e11d
|
||||
> {
|
||||
"languages": ['en', 'fr', 'de']
|
||||
}
|
||||
GET subtitles?oshash=a41cde31c581e11d&language=en
|
||||
> srt file
|
||||
POST subtitle?oshash=a41cde31c581e11d&language=en
|
||||
srt =
|
||||
'''
|
||||
def subtitles(request):
|
||||
oshash = request.GET['oshash']
|
||||
language = request.GET.get('language', None)
|
||||
if requeset.method == 'POST':
|
||||
user = request.user
|
||||
sub = models.Subtitles.get_or_create(user, oshash, language)
|
||||
sub.srt = request.POST['srt']
|
||||
sub.save()
|
||||
else:
|
||||
if language:
|
||||
q = models.Subtitles.objects.filter(movie_file__oshash=oshash, language=language)
|
||||
if q.count() > 0:
|
||||
return HttpResponse(q[0].srt, content_type='text/x-srt')
|
||||
response = {}
|
||||
l = models.Subtitles.objects.filter(movie_file__oshash=oshash).values('language')
|
||||
response['languages'] = [f['language'] for f in l]
|
||||
return render_to_json_response(response)
|
||||
|
||||
'''
|
||||
GET list
|
||||
> {
|
||||
"files": {
|
||||
"a41cde31c581e11d": {"path": "E/Example, The/An Example.avi", "size":1646274},
|
||||
}
|
||||
}
|
||||
'''
|
||||
@login_required_json
|
||||
def list_files(request):
|
||||
response['files'] = {}
|
||||
qs = models.UserFile.filter(user=request.user)
|
||||
p = Paginator(qs, 1000)
|
||||
for i in p.page_range:
|
||||
page = p.page(i)
|
||||
for f in page.object_list:
|
||||
response['files'][f.movie_file.oshash] = {'path': f.path, 'size': f.movie_file.size}
|
||||
return render_to_json_response(response)
|
||||
|
||||
def find_files(request):
|
||||
query = parse_query(request)
|
||||
response['files'] = {}
|
||||
qs = models.UserFile.filter(user=request.user).filter(movie_file__movie__id__in=quert['q'])
|
||||
p = Paginator(qs, 1000)
|
||||
for i in p.page_range:
|
||||
page = p.page(i)
|
||||
for f in page.object_list:
|
||||
response['files'][f.movie_file.oshash] = {'path': f.path, 'size': f.movie_file.size}
|
||||
return render_to_json_response(response)
|
||||
|
||||
'''
|
||||
POST add
|
||||
> file: {
|
||||
"duration": 5.266667,
|
||||
"video_codec": "mpeg1",
|
||||
"pixel_format": "yuv420p",
|
||||
"width": 352,
|
||||
"height": 240,
|
||||
"pixel_aspect_ratio": "1:1",
|
||||
"display_aspect_ratio": "22:15",
|
||||
"framerate": "30:1",
|
||||
"audio_codec": "mp2",
|
||||
"samplerate": 44100,
|
||||
"channels": 1,
|
||||
"path": "E/Example, The/An Example.avi",
|
||||
"size": 1646274
|
||||
"oshash": "a41cde31c581e11d",
|
||||
"sha1":..,
|
||||
"md5":..
|
||||
}
|
||||
'''
|
||||
#@login_required_json
|
||||
def add_file(request, archive):
|
||||
print request.POST
|
||||
info = json.loads(request.POST['file'])
|
||||
oshash = info['oshash']
|
||||
archive = models.Archive.objects.get(name=archive)
|
||||
if archive.users.filter(user=request.user).count() == 1:
|
||||
user_file = models.ArchiveFile.get_or_create(archive, oshash)
|
||||
user_file.update(request.POST)
|
||||
response = {'status': 200}
|
||||
else:
|
||||
response = {'status': 404}
|
||||
return render_to_json_response(response)
|
||||
|
||||
'''
|
||||
POST remove?oshash=
|
||||
'''
|
||||
@login_required_json
|
||||
def remove_file(request, archive):
|
||||
oshash = request.POST['oshash']
|
||||
archive = models.Archive.objects.get(name=archive)
|
||||
models.UserFiles.objects.filter(movie_file__oshash=oshash, user=request.user).delete()
|
||||
response = {'status': 200}
|
||||
return render_to_json_response(response)
|
||||
|
||||
def file_parse(request):
|
||||
response = utils.parsePath(request.POST['path'])
|
||||
return render_to_json_response(response)
|
||||
|
||||
|
||||
11
oxdb/manage.py
Normal file
11
oxdb/manage.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
from django.core.management import execute_manager
|
||||
try:
|
||||
import settings # Assumed to be in the same directory.
|
||||
except ImportError:
|
||||
import sys
|
||||
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
execute_manager(settings)
|
||||
113
oxdb/settings.py
Normal file
113
oxdb/settings.py
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
# Django settings for oxdb project.
|
||||
import os
|
||||
from os.path import join
|
||||
|
||||
PROJECT_ROOT = os.path.normpath(os.path.dirname(__file__))
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
ADMINS = (
|
||||
# ('Your Name', 'your_email@domain.com'),
|
||||
)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||
DATABASE_NAME = 'dev.sqlite' # Or path to database file if using sqlite3.
|
||||
DATABASE_USER = '' # Not used with sqlite3.
|
||||
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
||||
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
||||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||
|
||||
#CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
|
||||
|
||||
# Local time zone for this installation. Choices can be found here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
# although not all choices may be available on all operating systems.
|
||||
# If running in a Windows environment this must be set to the same as your
|
||||
# system time zone.
|
||||
TIME_ZONE = 'Europe/Berlin'
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# If you set this to False, Django will make some optimizations so as not
|
||||
# to load the internationalization machinery.
|
||||
USE_I18N = True
|
||||
|
||||
# Absolute path to the directory that holds media.
|
||||
# Example: "/home/media/media.lawrence.com/"
|
||||
MEDIA_ROOT = join(PROJECT_ROOT, 'media')
|
||||
STATIC_ROOT = join(PROJECT_ROOT, 'static')
|
||||
TESTS_ROOT = join(PROJECT_ROOT, 'tests')
|
||||
|
||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
# trailing slash if there is a path component (optional in other cases).
|
||||
# Examples: "http://media.lawrence.com", "http://example.com/media/"
|
||||
MEDIA_URL = ''
|
||||
|
||||
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
|
||||
# trailing slash.
|
||||
# Examples: "http://foo.com/media/", "/media/".
|
||||
ADMIN_MEDIA_PREFIX = '/admin/media/'
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.load_template_source',
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
# 'django.template.loaders.eggs.load_template_source',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'oxdb.urls'
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
join(PROJECT_ROOT, 'templates'),
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.humanize',
|
||||
# 'south',
|
||||
|
||||
'backend',
|
||||
)
|
||||
|
||||
#overwrite default settings with local settings
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Make this unique, creates random key first at first time.
|
||||
try:
|
||||
SECRET_KEY
|
||||
except NameError:
|
||||
SECRET_FILE = os.path.join(PROJECT_ROOT, 'secret.txt')
|
||||
try:
|
||||
SECRET_KEY = open(SECRET_FILE).read().strip()
|
||||
except IOError:
|
||||
try:
|
||||
from random import choice
|
||||
SECRET_KEY = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
|
||||
secret = file(SECRET_FILE, 'w')
|
||||
secret.write(SECRET_KEY)
|
||||
secret.close()
|
||||
except IOError:
|
||||
Exception('Please create a %s file with random characters to generate your secret key!' % SECRET_FILE)
|
||||
|
||||
37
oxdb/static/css/ui.css
Normal file
37
oxdb/static/css/ui.css
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
body {
|
||||
background: rgb(16, 16, 16);
|
||||
}
|
||||
|
||||
div {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
input#find {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 24px;
|
||||
width: 240px;
|
||||
}
|
||||
img#loading {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: hidden;
|
||||
}
|
||||
|
||||
|
||||
#sideBrowserPlayer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#statusBar {
|
||||
-moz-box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.75);
|
||||
-webkit-box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
|
||||
.OxCell.OxColumnTitle {
|
||||
//font-weight: bold;
|
||||
}
|
||||
1
oxdb/static/jquery
Symbolic link
1
oxdb/static/jquery
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
js/jquery/
|
||||
19
oxdb/static/js/jquery/jquery.js
vendored
Normal file
19
oxdb/static/js/jquery/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1132
oxdb/static/js/ui.js
Normal file
1132
oxdb/static/js/ui.js
Normal file
File diff suppressed because it is too large
Load diff
BIN
oxdb/static/png/frame.png
Normal file
BIN
oxdb/static/png/frame.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
oxdb/static/png/timeline.png
Normal file
BIN
oxdb/static/png/timeline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
17
oxdb/templates/index.html
Normal file
17
oxdb/templates/index.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>0xdb.org</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<script type="text/javascript" src="/static/js/jquery/jquery.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/js/ox.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/js/ox.ui.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/js/ox.iso.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/js/ox.unicode.js"></script>
|
||||
<script type="text/javascript" src="/static/js/ui.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/static/oxjs/css/ox.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/ui.css"/>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
33
oxdb/urls.py
Normal file
33
oxdb/urls.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# Example:
|
||||
(r'^json/', include('backend.urls')),
|
||||
(r'^$', 'app.views.index'),
|
||||
|
||||
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
||||
# to INSTALLED_APPS to enable admin documentation:
|
||||
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
(r'^admin/(.*)', admin.site.root),
|
||||
)
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += patterns('',
|
||||
(r'^media/(?P<path>.*)$', 'django.views.static.serve',
|
||||
{'document_root': settings.MEDIA_ROOT}),
|
||||
(r'^static/(?P<path>.*)$', 'django.views.static.serve',
|
||||
{'document_root': settings.STATIC_ROOT}),
|
||||
(r'^tests/(?P<path>.*)$', 'django.views.static.serve',
|
||||
{'document_root': settings.TESTS_ROOT}),
|
||||
)
|
||||
|
||||
|
||||
0
oxdb/user_management/__init__.py
Normal file
0
oxdb/user_management/__init__.py
Normal file
23
oxdb/user_management/models.py
Normal file
23
oxdb/user_management/models.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class Group(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
name = models.CharField(blank=True, max_length=255, unique=True)
|
||||
users = models.ManyToManyField(User, related_name='groups')
|
||||
|
||||
class Profile(models.Model):
|
||||
user = models.ForeignKey(User, unique=True)
|
||||
|
||||
class Preference(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
user = models.ForeignKey(User, related_name='preferences')
|
||||
key = models.CharField(blank=True, max_length=255)
|
||||
value = models.TextField(blank=True)
|
||||
|
||||
23
oxdb/user_management/tests.py
Normal file
23
oxdb/user_management/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
|
||||
"""}
|
||||
|
||||
14
oxdb/user_management/urls.py
Normal file
14
oxdb/user_management/urls.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
|
||||
urlpatterns = patterns("oxdb.user_management.views",
|
||||
(r'^preferences', 'preferences'),
|
||||
(r'^login', 'login'),
|
||||
(r'^logout', 'logout'),
|
||||
(r'^register', 'register'),
|
||||
(r'^recover', 'recover'),
|
||||
)
|
||||
|
||||
91
oxdb/user_management/views.py
Normal file
91
oxdb/user_management/views.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
|
||||
from django.template import RequestContext
|
||||
from django.utils import simplejson as json
|
||||
|
||||
from oxdb.utils.shortcuts import render_to_json_response
|
||||
from oxdb.utils.decorators import login_required_json
|
||||
|
||||
import models
|
||||
|
||||
|
||||
def login(request):
|
||||
from django.contrib.auth import authenticate, login
|
||||
response = {'status': 403, 'message': 'login required'}
|
||||
username = request.POST['username']
|
||||
password = request.POST['password']
|
||||
user = authenticate(username=username, password=password)
|
||||
if user is not None:
|
||||
if user.is_active:
|
||||
user_json = {} #FIXME: preferences etc should be in here
|
||||
login(request, user)
|
||||
response = {'status': 200, 'message': 'You are logged in.', 'user': user_json}
|
||||
else:
|
||||
response = {'status': 403, 'message': 'Your account is disabled.'}
|
||||
print "Your account has been disabled!"
|
||||
else:
|
||||
response = {'status': 403, 'message': 'Your username and password were incorrect.'}
|
||||
return render_to_json_response(response)
|
||||
|
||||
def logout(request):
|
||||
response = {'status': 200}
|
||||
if request.user.is_authenticated():
|
||||
request.user.logout()
|
||||
return render_to_json_response(response)
|
||||
|
||||
def register(request):
|
||||
response = {'status': 500, 'message': 'registration failed'}
|
||||
return render_to_json_response(response)
|
||||
|
||||
def recover(request):
|
||||
username = request.POST.get('username', None)
|
||||
user = None
|
||||
q = User.objects.filter(username=username)
|
||||
if q.count() > 0:
|
||||
user = q[0]
|
||||
else:
|
||||
q = User.objects.filter(email=email)
|
||||
if q.count() > 0:
|
||||
user = q[0]
|
||||
if user:
|
||||
user.sendmail(...) #FIXME: send recovery mail
|
||||
response = {'status': 200, 'message': 'recovert email sent.'}
|
||||
else:
|
||||
response = {'status': 500, 'message': 'user or email not found.'}
|
||||
return render_to_json_response(response)
|
||||
|
||||
'''
|
||||
GET preferences/ //get all keys
|
||||
GET preferences/?key= //get key
|
||||
GEt preferences/?key=&value= //set key
|
||||
'''
|
||||
@login_required_json
|
||||
def preferences(request):
|
||||
response = {'status': 200}
|
||||
key = request.GET.get('key', None)
|
||||
value = request.GET.get('value', None)
|
||||
user = request.user
|
||||
if not key: # return all preferences for current user
|
||||
for p in models.Preference.objects.filter(user=user):
|
||||
response['preferences'][p.key] = p.value
|
||||
response['preferences']['email'] = user.email
|
||||
elif value == None: #return one preference
|
||||
p, created = models.Preference.objects.get_or_create(user=user, key=key)
|
||||
response['preferences'][key] = p.value
|
||||
else: # set preference
|
||||
response['message'] = '%s saved.' % key
|
||||
if key == 'password':
|
||||
user.set_password(value)
|
||||
user.save()
|
||||
elsif key == 'email':
|
||||
user.email = vaule
|
||||
user.save()
|
||||
else:
|
||||
p, created = models.Preference.objects.get_or_create(user=user, key=key)
|
||||
p.value = value
|
||||
p.save()
|
||||
return render_to_json_response(response)
|
||||
|
||||
0
oxdb/utils/__init__.py
Normal file
0
oxdb/utils/__init__.py
Normal file
18
oxdb/utils/decorators.py
Normal file
18
oxdb/utils/decorators.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from django.contrib.auth.decorators import user_passes_test
|
||||
|
||||
|
||||
def login_required_json(function=None):
|
||||
"""
|
||||
Decorator for views that checks that the user is logged in
|
||||
return json error if not logged in.
|
||||
"""
|
||||
actual_decorator = user_passes_test(
|
||||
lambda u: u.is_authenticated(),
|
||||
login_url='/json/login',
|
||||
)
|
||||
if function:
|
||||
return actual_decorator(function)
|
||||
return actual_decorator
|
||||
|
||||
14
oxdb/utils/shortcuts.py
Normal file
14
oxdb/utils/shortcuts.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils import simplejson
|
||||
from django.conf import settings
|
||||
|
||||
def render_to_json_response(dictionary, content_type="text/json"):
|
||||
indent=None
|
||||
if settings.DEBUG:
|
||||
content_type = "text/javascript"
|
||||
indent = 2
|
||||
return HttpResponse(simplejson.dumps(dictionary, indent=indent), content_type=content_type)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue