move in preparation for virtualenv setup

This commit is contained in:
j 2009-10-09 16:02:20 +02:00
commit 973b3600af
33 changed files with 0 additions and 0 deletions

0
oxdb/__init__.py Normal file
View file

0
oxdb/app/__init__.py Normal file
View file

3
oxdb/app/models.py Normal file
View file

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

23
oxdb/app/tests.py Normal file
View 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
View 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
View file

173
oxdb/backend/load.py Normal file
View 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
View 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]

View 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']

View 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']

View file

998
oxdb/backend/models.py Normal file
View 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&amp;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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1 @@
js/jquery/

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

File diff suppressed because it is too large Load diff

BIN
oxdb/static/png/frame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

17
oxdb/templates/index.html Normal file
View 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
View 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}),
)

View file

View 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)

View 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
"""}

View 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'),
)

View 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
View file

18
oxdb/utils/decorators.py Normal file
View 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
View 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)