diff --git a/.bzrignore b/.bzrignore index b21790c..03a40b2 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,2 +1,6 @@ secret.txt local_settings.py +lib +include +src +bin diff --git a/README b/README new file mode 100644 index 0000000..ee3287b --- /dev/null +++ b/README @@ -0,0 +1,36 @@ + +To setup a local instance of 0xdb: + + bzr branch http://code.0xdb.org/oxdb oxdb + cd oxdb + virtualenv . + pip -E . install -r requirements.txt + + +you need python, bazaar, pip and virtualenv: + + apt-get install python-setuptools bzr + east_install pip + pip install virtualenv + +also it uses system python moduels, so make sure you have + ipython, dbmodule(psycopg2, python-mysqldb,..) +installed via apt-get/pip/easy_install in your system path. + + +Install rabbitmq and carrot: + sudo apt-get install rabbitmq-server + + sudo rabbitmqctl add_user oxdb password + sudo rabbitmqctl add_vhost /oxdb + sudo rabbitmqctl set_permissions -p /oxdb oxdb "^oxdb-.*" ".*" ".*" + + + update BROKER_* settings in local_settings.py: + +Development: + we are using django, http://docs.djangoproject.com/en/dev/ + communication between webserver and background tasks is done via rabbitmq + http://github.com/ask/carrot/ for more info on the lib used to communicate + + diff --git a/apache/vhost.conf.in b/apache/vhost.conf.in new file mode 100644 index 0000000..b491e21 --- /dev/null +++ b/apache/vhost.conf.in @@ -0,0 +1,24 @@ + + + + Options -Indexes + + + Order deny,allow + Allow from all + + + Alias /.bzr /oxdb/.bzr + Alias /static __PREFIX__/oxdb/static + Alias /favicon.ico __PREFIX__/oxdb/static/favicon.ico + Alias /media __PREFIX__/oxdb/media + Alias /admin/media __PREFIX__/src/django/django/contrib/admin/media + WSGIScriptAlias / __PREFIX__/wsgi/django.wsgi + + WSGIDaemonProcess oxdb user=oxdb group=oxdb threads=25 python-path=__PREFIX__/lib/python2.6/site-packages/ + WSGIProcessGroup oxdb + + ServerSignature Off + + + diff --git a/oxdb/backend/admin.py b/oxdb/backend/admin.py new file mode 100644 index 0000000..2341c9c --- /dev/null +++ b/oxdb/backend/admin.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +# Written 2009 by j@mailb.org + +from django.contrib import admin + +from forms import FileAdminForm, MovieAdminForm, ArchiveFileAdminForm +import models + + +#class MovieImdbAdmin(admin.ModelAdmin): +# search_fields = ['imdbId', 'title'] +#admin.site.register(models.MovieImdb, MovieImdbAdmin) + +class MovieImdbInline(admin.StackedInline): + model = models.MovieImdb + +class MovieOxdbInline(admin.StackedInline): + model = models.MovieOxdb + +class MovieAdmin(admin.ModelAdmin): + search_fields = ['movieId', 'imdb__title', 'oxdb__title'] + form = MovieAdminForm + #inlines = [MovieImdbInline, MovieOxdbInline] + +admin.site.register(models.Movie, MovieAdmin) + + +class FileAdmin(admin.ModelAdmin): + search_fields = ['path', 'video_codec'] + + form = FileAdminForm + +admin.site.register(models.File, FileAdmin) + +class ArchiveFileAdmin(admin.ModelAdmin): + search_fields = ['path', 'archive__name'] + form = ArchiveFileAdminForm + +admin.site.register(models.ArchiveFile, ArchiveFileAdmin) + + +class ArchiveAdmin(admin.ModelAdmin): + search_fields = ['name'] +admin.site.register(models.Archive, ArchiveAdmin) + diff --git a/oxdb/backend/fields.py b/oxdb/backend/fields.py new file mode 100644 index 0000000..e556ecc --- /dev/null +++ b/oxdb/backend/fields.py @@ -0,0 +1,47 @@ +from django.db import models +from django.utils import simplejson as json + + +class DictField(models.TextField): + """DictField is a textfield that contains JSON-serialized dictionaries.""" + + # Used so to_python() is called + __metaclass__ = models.SubfieldBase + + def to_python(self, value): + """Convert our string value to python after we load it from the DB""" + if isinstance(value, dict): + return value + + value = json.loads(value) + assert isinstance(value, dict) + return value + + def get_db_prep_save(self, value): + """Convert our JSON object to a string before we save""" + assert isinstance(value, dict) + value = json.dumps(value) + return super(DictField, self).get_db_prep_save(value) + + +class TupleField(models.TextField): + """TupleField is a textfield that contains JSON-serialized tuples.""" + + # Used so to_python() is called + __metaclass__ = models.SubfieldBase + + def to_python(self, value): + """Convert our string value to JSON after we load it from the DB""" + if isinstance(value, tuple): + return value + + value = json.loads(value) + assert isinstance(value, list) + return tuple(value) + + def get_db_prep_save(self, value): + """Convert our JSON object to a string before we save""" + assert isinstance(value, tuple) + value = json.dumps(value) + return super(TupleField, self).get_db_prep_save(value) + diff --git a/oxdb/backend/forms.py b/oxdb/backend/forms.py new file mode 100644 index 0000000..15cc3d2 --- /dev/null +++ b/oxdb/backend/forms.py @@ -0,0 +1,42 @@ +from ajax_filtered_fields.forms import AjaxManyToManyField, ForeignKeyByLetter +from django.conf import settings +from django import forms + +import models + +ajax_filtered_js = ( + settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js", + settings.ADMIN_MEDIA_PREFIX + "js/SelectFilter2.js", + settings.STATIC_URL + 'js/jquery/jquery.js', + settings.STATIC_URL + 'js/ajax_filtered_fields.js', +) + +class FileAdminForm(forms.ModelForm): + movie = ForeignKeyByLetter(models.Movie, field_name='imdb__title') + + class Meta: + model = models.File + + class Media: + js = ajax_filtered_js + +class ArchiveFileAdminForm(forms.ModelForm): + file = ForeignKeyByLetter(models.File, field_name='path') + + class Meta: + model = models.ArchiveFile + + class Media: + js = ajax_filtered_js + + +class MovieAdminForm(forms.ModelForm): + imdb = ForeignKeyByLetter(models.MovieImdb, field_name='title') + oxdb = ForeignKeyByLetter(models.MovieOxdb, field_name='title') + + class Meta: + model = models.Movie + + class Media: + js = ajax_filtered_js + diff --git a/oxdb/backend/load.py b/oxdb/backend/load.py index 0226a56..fd86bbd 100644 --- a/oxdb/backend/load.py +++ b/oxdb/backend/load.py @@ -5,8 +5,8 @@ import os.path from django.db import models from django.contrib.auth.models import User -import ox.web.imdb -from ox import stripTags, findRe +import oxweb.imdb +from oxlib import stripTags, findRe import models @@ -37,14 +37,14 @@ def loadIMDb(imdbId): movie = models.Movie() movie.imdb = imdb - info = ox.web.imdb.getMovieInfo(imdbId) + info = oxweb.imdb.getMovieInfo(imdbId) for key in ('title', 'tagline', 'year', 'release_date', 'rating', 'votes', - 'series_imdb' + 'series_imdb', 'season', 'episode'): if key in info: @@ -58,11 +58,11 @@ def loadIMDb(imdbId): if key in info: setattr(movie.imdb, _info_map.get(key, key), info[key]) - movie.imdb.plot = ox.web.imdb.getMoviePlot(imdbId) + movie.imdb.plot = oxweb.imdb.getMoviePlot(imdbId) debug("plot", movie.imdb.plot) - movie.imdb.runtime = ox.web.imdb.getMovieRuntimeSeconds(imdbId) - business = ox.web.imdb.getMovieBusinessSum(imdbId) + movie.imdb.runtime = oxweb.imdb.getMovieRuntimeSeconds(imdbId) + business = oxweb.imdb.getMovieBusinessSum(imdbId) for key in ('gross', 'profit', 'budget'): setattr(movie.imdb, key, business[key]) @@ -70,7 +70,7 @@ def loadIMDb(imdbId): movie.oxdbId = "__init__%s" % random.randint(0, 100000) movie.save() models.AlternativeTitle.objects.filter(movie=movie, manual=False).delete() - for i in ox.web.imdb.getMovieAKATitles(imdbId): + for i in oxweb.imdb.getMovieAKATitles(imdbId): t = models.AlternativeTitle() t.movie = movie t.title = i[0] @@ -100,7 +100,7 @@ def loadIMDb(imdbId): #Location movie.locations_all.filter(manual=False).delete() - locations = ox.web.imdb.getMovieLocations(imdbId) + locations = oxweb.imdb.getMovieLocations(imdbId) for i in locations: debug("add location", i) location = models.Location.get_or_create(i) @@ -116,7 +116,7 @@ def loadIMDb(imdbId): #Keyword movie.keywords_all.filter(manual=False).delete() - keywords = ox.web.imdb.getMovieKeywords(imdbId) + keywords = oxweb.imdb.getMovieKeywords(imdbId) for g in keywords: debug("add keyword", g) keyword = models.Keyword.get_or_create(g) @@ -124,7 +124,7 @@ def loadIMDb(imdbId): movie.trivia_all.filter(manual=False).delete() position = 0 - trivia = ox.web.imdb.getMovieTrivia(imdbId) + trivia = oxweb.imdb.getMovieTrivia(imdbId) for i in trivia: debug("add trivia", i) t = models.Trivia() @@ -136,7 +136,7 @@ def loadIMDb(imdbId): position = 0 models.Cast.objects.filter(movie=movie).filter(manual=False).delete() - credits = ox.web.imdb.getMovieCredits(imdbId) + credits = oxweb.imdb.getMovieCredits(imdbId) for role in credits: for p in credits[role]: name = stripTags(p[0]) @@ -149,7 +149,7 @@ def loadIMDb(imdbId): position += 1 movie.connections_all.filter(manual=False).delete() - connections = ox.web.imdb.getMovieConnections(imdbId) + connections = oxweb.imdb.getMovieConnections(imdbId) for relation in connections: for otherId in connections[relation]: try: @@ -159,7 +159,7 @@ def loadIMDb(imdbId): except models.Movie.DoesNotExist: pass - reviews = ox.web.imdb.getMovieExternalReviews(imdbId) + reviews = oxweb.imdb.getMovieExternalReviews(imdbId) movie.reviews_all.filter(manual=False).delete() for r in reviews: debug("add review", r) diff --git a/oxdb/backend/managers.py b/oxdb/backend/managers.py index 57b9e58..eb32a99 100644 --- a/oxdb/backend/managers.py +++ b/oxdb/backend/managers.py @@ -132,7 +132,7 @@ class FileManager(Manager): def movie_files(self, movie): q = self.get_query_set() - return q.filter(is_video=True, movie=movie) + return q.filter(type=1, movie=movie) class ArchiveFileManager(Manager): def get_query_set(self): @@ -144,9 +144,10 @@ class ArchiveFileManager(Manager): def by_oshash(self, oshash): q = self.get_query_set() - q.filter(movie_file__oshash=oshash) + q = q.filter(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] + else: + return q[0] diff --git a/oxdb/backend/migrations/0001_initial.py b/oxdb/backend/migrations/0001_initial.py index 8ee506a..d6ad0ee 100644 --- a/oxdb/backend/migrations/0001_initial.py +++ b/oxdb/backend/migrations/0001_initial.py @@ -2,7 +2,7 @@ from south.db import db from django.db import models -from oxdb.backend.models import * +from backend.models import * class Migration: @@ -12,8 +12,9 @@ class Migration: db.create_table('backend_trivia', ( ('id', orm['backend.Trivia:id']), ('trivia', orm['backend.Trivia:trivia']), - ('movie', orm['backend.Trivia:movie']), + ('manual', orm['backend.Trivia:manual']), ('position', orm['backend.Trivia:position']), + ('movie', orm['backend.Trivia:movie']), )) db.send_create_signal('backend', ['Trivia']) @@ -23,6 +24,7 @@ class Migration: ('movie', orm['backend.AlternativeTitle:movie']), ('title', orm['backend.AlternativeTitle:title']), ('type', orm['backend.AlternativeTitle:type']), + ('manual', orm['backend.AlternativeTitle:manual']), )) db.send_create_signal('backend', ['AlternativeTitle']) @@ -32,6 +34,7 @@ class Migration: ('movie', orm['backend.MovieLanguage:movie']), ('language', orm['backend.MovieLanguage:language']), ('position', orm['backend.MovieLanguage:position']), + ('manual', orm['backend.MovieLanguage:manual']), )) db.send_create_signal('backend', ['MovieLanguage']) @@ -40,10 +43,12 @@ class Migration: ('id', orm['backend.Movie:id']), ('created', orm['backend.Movie:created']), ('modified', orm['backend.Movie:modified']), - ('accessed', orm['backend.Movie:accessed']), + ('available', orm['backend.Movie:available']), ('movieId', orm['backend.Movie:movieId']), - ('imdbId', orm['backend.Movie:imdbId']), ('oxdbId', orm['backend.Movie:oxdbId']), + ('imdb', orm['backend.Movie:imdb']), + ('oxdb', orm['backend.Movie:oxdb']), + ('rights_level', orm['backend.Movie:rights_level']), ('title', orm['backend.Movie:title']), ('year', orm['backend.Movie:year']), ('runtime', orm['backend.Movie:runtime']), @@ -56,26 +61,29 @@ class Migration: ('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']), + ('directors', orm['backend.Movie:directors']), + ('writers', orm['backend.Movie:writers']), + ('editors', orm['backend.Movie:editors']), + ('producers', orm['backend.Movie:producers']), + ('cinematographers', orm['backend.Movie:cinematographers']), + ('cast', orm['backend.Movie:cast']), + ('alternative_titles', orm['backend.Movie:alternative_titles']), + ('genres', orm['backend.Movie:genres']), + ('keywords', orm['backend.Movie:keywords']), + ('countries', orm['backend.Movie:countries']), + ('languages', orm['backend.Movie:languages']), + ('trivia', orm['backend.Movie:trivia']), + ('locations', orm['backend.Movie:locations']), + ('connections', orm['backend.Movie:connections']), + ('reviews', orm['backend.Movie:reviews']), + ('stream128', orm['backend.Movie:stream128']), + ('stream320', orm['backend.Movie:stream320']), + ('stream640', orm['backend.Movie:stream640']), ('scene_height', orm['backend.Movie:scene_height']), )) db.send_create_signal('backend', ['Movie']) @@ -86,6 +94,7 @@ class Migration: ('created', orm['backend.Archive:created']), ('modified', orm['backend.Archive:modified']), ('name', orm['backend.Archive:name']), + ('public', orm['backend.Archive:public']), )) db.send_create_signal('backend', ['Archive']) @@ -95,11 +104,36 @@ class Migration: ('created', orm['backend.ArchiveFile:created']), ('modified', orm['backend.ArchiveFile:modified']), ('archive', orm['backend.ArchiveFile:archive']), - ('movie_file', orm['backend.ArchiveFile:movie_file']), + ('file', orm['backend.ArchiveFile:file']), ('path', orm['backend.ArchiveFile:path']), )) db.send_create_signal('backend', ['ArchiveFile']) + # Adding model 'MovieOxdb' + db.create_table('backend_movieoxdb', ( + ('id', orm['backend.MovieOxdb:id']), + ('created', orm['backend.MovieOxdb:created']), + ('modified', orm['backend.MovieOxdb:modified']), + ('title', orm['backend.MovieOxdb:title']), + ('year', orm['backend.MovieOxdb:year']), + ('runtime', orm['backend.MovieOxdb:runtime']), + ('release_date', orm['backend.MovieOxdb:release_date']), + ('tagline', orm['backend.MovieOxdb:tagline']), + ('plot', orm['backend.MovieOxdb:plot']), + ('plot_outline', orm['backend.MovieOxdb:plot_outline']), + ('rating', orm['backend.MovieOxdb:rating']), + ('votes', orm['backend.MovieOxdb:votes']), + ('budget', orm['backend.MovieOxdb:budget']), + ('gross', orm['backend.MovieOxdb:gross']), + ('profit', orm['backend.MovieOxdb:profit']), + ('series_imdb', orm['backend.MovieOxdb:series_imdb']), + ('series_title', orm['backend.MovieOxdb:series_title']), + ('episode_title', orm['backend.MovieOxdb:episode_title']), + ('season', orm['backend.MovieOxdb:season']), + ('episode', orm['backend.MovieOxdb:episode']), + )) + db.send_create_signal('backend', ['MovieOxdb']) + # Adding model 'Language' db.create_table('backend_language', ( ('id', orm['backend.Language:id']), @@ -115,9 +149,22 @@ class Migration: )) db.send_create_signal('backend', ['ReviewWhitelist']) + # Adding model 'Layer' + db.create_table('backend_layer', ( + ('id', orm['backend.Layer:id']), + ('created', orm['backend.Layer:created']), + ('modified', orm['backend.Layer:modified']), + ('user', orm['backend.Layer:user']), + ('movie', orm['backend.Layer:movie']), + ('time_in', orm['backend.Layer:time_in']), + ('time_out', orm['backend.Layer:time_out']), + ('type', orm['backend.Layer:type']), + ('value', orm['backend.Layer:value']), + )) + db.send_create_signal('backend', ['Layer']) + # 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']), @@ -135,6 +182,8 @@ class Migration: ('summary', orm['backend.MovieSort:summary']), ('trivia', orm['backend.MovieSort:trivia']), ('connections', orm['backend.MovieSort:connections']), + ('rating', orm['backend.MovieSort:rating']), + ('votes', orm['backend.MovieSort:votes']), ('scenes', orm['backend.MovieSort:scenes']), ('words', orm['backend.MovieSort:words']), ('wpm', orm['backend.MovieSort:wpm']), @@ -163,6 +212,7 @@ class Migration: ('computed_path', orm['backend.File:computed_path']), ('size', orm['backend.File:size']), ('duration', orm['backend.File:duration']), + ('is_video', orm['backend.File:is_video']), ('video_codec', orm['backend.File:video_codec']), ('pixel_format', orm['backend.File:pixel_format']), ('width', orm['backend.File:width']), @@ -176,6 +226,10 @@ class Migration: ('bpp', orm['backend.File:bpp']), ('pixels', orm['backend.File:pixels']), ('part', orm['backend.File:part']), + ('available', orm['backend.File:available']), + ('stream128', orm['backend.File:stream128']), + ('stream320', orm['backend.File:stream320']), + ('stream640', orm['backend.File:stream640']), )) db.send_create_signal('backend', ['File']) @@ -190,6 +244,7 @@ class Migration: db.create_table('backend_genre', ( ('id', orm['backend.Genre:id']), ('name', orm['backend.Genre:name']), + ('manual', orm['backend.Genre:manual']), )) db.send_create_signal('backend', ['Genre']) @@ -199,6 +254,7 @@ class Migration: ('movie', orm['backend.MovieCountry:movie']), ('country', orm['backend.MovieCountry:country']), ('position', orm['backend.MovieCountry:position']), + ('manual', orm['backend.MovieCountry:manual']), )) db.send_create_signal('backend', ['MovieCountry']) @@ -208,6 +264,7 @@ class Migration: ('movie', orm['backend.Review:movie']), ('title', orm['backend.Review:title']), ('url', orm['backend.Review:url']), + ('manual', orm['backend.Review:manual']), )) db.send_create_signal('backend', ['Review']) @@ -217,7 +274,7 @@ class Migration: ('created', orm['backend.Subtitle:created']), ('modified', orm['backend.Subtitle:modified']), ('user', orm['backend.Subtitle:user']), - ('movie_file', orm['backend.Subtitle:movie_file']), + ('file', orm['backend.Subtitle:file']), ('language', orm['backend.Subtitle:language']), ('srt', orm['backend.Subtitle:srt']), )) @@ -231,6 +288,7 @@ class Migration: ('role', orm['backend.Cast:role']), ('character', orm['backend.Cast:character']), ('position', orm['backend.Cast:position']), + ('manual', orm['backend.Cast:manual']), )) db.send_create_signal('backend', ['Cast']) @@ -247,9 +305,36 @@ class Migration: db.create_table('backend_keyword', ( ('id', orm['backend.Keyword:id']), ('name', orm['backend.Keyword:name']), + ('manual', orm['backend.Keyword:manual']), )) db.send_create_signal('backend', ['Keyword']) + # Adding model 'MovieImdb' + db.create_table('backend_movieimdb', ( + ('id', orm['backend.MovieImdb:id']), + ('created', orm['backend.MovieImdb:created']), + ('modified', orm['backend.MovieImdb:modified']), + ('imdbId', orm['backend.MovieImdb:imdbId']), + ('title', orm['backend.MovieImdb:title']), + ('year', orm['backend.MovieImdb:year']), + ('runtime', orm['backend.MovieImdb:runtime']), + ('release_date', orm['backend.MovieImdb:release_date']), + ('tagline', orm['backend.MovieImdb:tagline']), + ('plot', orm['backend.MovieImdb:plot']), + ('plot_outline', orm['backend.MovieImdb:plot_outline']), + ('rating', orm['backend.MovieImdb:rating']), + ('votes', orm['backend.MovieImdb:votes']), + ('budget', orm['backend.MovieImdb:budget']), + ('gross', orm['backend.MovieImdb:gross']), + ('profit', orm['backend.MovieImdb:profit']), + ('series_imdb', orm['backend.MovieImdb:series_imdb']), + ('series_title', orm['backend.MovieImdb:series_title']), + ('episode_title', orm['backend.MovieImdb:episode_title']), + ('season', orm['backend.MovieImdb:season']), + ('episode', orm['backend.MovieImdb:episode']), + )) + db.send_create_signal('backend', ['MovieImdb']) + # Adding model 'List' db.create_table('backend_list', ( ('id', orm['backend.List:id']), @@ -267,6 +352,7 @@ class Migration: ('subject', orm['backend.Connection:subject']), ('relation', orm['backend.Connection:relation']), ('object', orm['backend.Connection:object']), + ('manual', orm['backend.Connection:manual']), )) db.send_create_signal('backend', ['Connection']) @@ -274,6 +360,7 @@ class Migration: db.create_table('backend_location', ( ('id', orm['backend.Location:id']), ('name', orm['backend.Location:name']), + ('manual', orm['backend.Location:manual']), ('lat_sw', orm['backend.Location:lat_sw']), ('lng_sw', orm['backend.Location:lng_sw']), ('lat_ne', orm['backend.Location:lat_ne']), @@ -286,7 +373,6 @@ class Migration: # 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']), @@ -368,12 +454,18 @@ class Migration: # Deleting model 'ArchiveFile' db.delete_table('backend_archivefile') + # Deleting model 'MovieOxdb' + db.delete_table('backend_movieoxdb') + # Deleting model 'Language' db.delete_table('backend_language') # Deleting model 'ReviewWhitelist' db.delete_table('backend_reviewwhitelist') + # Deleting model 'Layer' + db.delete_table('backend_layer') + # Deleting model 'MovieSort' db.delete_table('backend_moviesort') @@ -404,6 +496,9 @@ class Migration: # Deleting model 'Keyword' db.delete_table('backend_keyword') + # Deleting model 'MovieImdb' + db.delete_table('backend_movieimdb') + # Deleting model 'List' db.delete_table('backend_list') @@ -463,7 +558,8 @@ class Migration: }, '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']"}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alternative_titles_all'", 'to': "orm['backend.Movie']"}), 'title': ('django.db.models.fields.TextField', [], {}), 'type': ('django.db.models.fields.CharField', [], {'max_length': '1000'}) }, @@ -472,29 +568,32 @@ class Migration: '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'}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']"}) }, 'backend.archivefile': { - 'archive': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Archive']"}), + 'archive': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['backend.Archive']"}), 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'file': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.File']"}), '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'}), + 'character': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'cast_relation'", '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'}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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']"}) + 'subject': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'connections_all'", 'to': "orm['backend.Movie']"}) }, 'backend.country': { 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), @@ -503,6 +602,7 @@ class Migration: }, 'backend.file': { 'audio_codec': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', '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'}), @@ -512,6 +612,7 @@ class Migration: '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'}), + 'is_video': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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']"}), @@ -523,16 +624,21 @@ class Migration: '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'}), + 'stream128': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100'}), + 'stream320': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100'}), + 'stream640': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100'}), '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'}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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'}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}) }, @@ -541,6 +647,17 @@ class Migration: 'movies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['backend.Movie']"}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}) }, + 'backend.layer': { + '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': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}), + 'time_in': ('django.db.models.fields.FloatField', [], {'default': '-1'}), + 'time_out': ('django.db.models.fields.FloatField', [], {'default': '-1'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, 'backend.list': { 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), @@ -566,84 +683,136 @@ class Migration: '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'}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), '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'}), + 'alternative_titles': ('fields.TupleField', [], {'default': '()'}), + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}), 'budget': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'cast': ('fields.TupleField', [], {'default': '()'}), + 'cinematographers': ('fields.TupleField', [], {'default': '()'}), + 'connections': ('fields.TupleField', [], {'default': '()'}), + 'countries': ('fields.TupleField', [], {'default': '()'}), 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'directors': ('fields.TupleField', [], {'default': '()'}), + 'editors': ('fields.TupleField', [], {'default': '()'}), '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'}), + 'genres': ('fields.TupleField', [], {'default': '()'}), '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'}), + 'imdb': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'movie'", 'unique': 'True', 'null': 'True', 'to': "orm['backend.MovieImdb']"}), + 'keywords': ('fields.TupleField', [], {'default': '()'}), + 'languages': ('fields.TupleField', [], {'default': '()'}), + 'locations': ('fields.TupleField', [], {'default': '()'}), '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'}), + 'oxdb': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'movie'", 'unique': 'True', 'null': 'True', 'to': "orm['backend.MovieOxdb']"}), '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'}), + 'producers': ('fields.TupleField', [], {'default': '()'}), 'profit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'rating': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), 'release_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'reviews': ('fields.TupleField', [], {'default': '()'}), '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'}), + 'stream128': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100'}), + 'stream320': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100'}), + 'stream640': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100'}), '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'}), + 'trivia': ('fields.TupleField', [], {'default': '()'}), 'votes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'wikipedia_url': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'writers': ('fields.TupleField', [], {'default': '()'}), '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'}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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'}), + 'cast': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'cinematographer': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'country': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'director': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'editor': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'filename': ('django.db.models.fields.TextField', [], {'default': "''", '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'}), + 'language': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'locations': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'movie': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'find'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['backend.Movie']"}), + 'producer': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), + 'title': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'trivia': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'writer': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'writer': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'year': ('django.db.models.fields.CharField', [], {'max_length': '4'}) + }, + 'backend.movieimdb': { + 'budget': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'episode': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), + 'episode_title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1000', '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'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'plot': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'plot_outline': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'profit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'release_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'runtime': ('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.CharField', [], {'default': "''", 'max_length': '1000', 'blank': 'True'}), + 'tagline': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), + 'votes': ('django.db.models.fields.IntegerField', [], {'null': 'True', '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']"}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), 'movie': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Movie']"}), 'position': ('django.db.models.fields.IntegerField', [], {}) }, + 'backend.movieoxdb': { + 'budget': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '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'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'plot': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'plot_outline': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'profit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'release_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'runtime': ('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'}), + 'tagline': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), + 'votes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'year': ('django.db.models.fields.CharField', [], {'max_length': '4'}) + }, 'backend.moviesort': { 'aspectratio': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}), 'bitrate': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}), @@ -657,13 +826,13 @@ class Migration: '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']"}), + 'movie': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'sort'", 'unique': 'True', 'primary_key': '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'}), + 'rating': ('django.db.models.fields.FloatField', [], {'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'}), @@ -672,6 +841,7 @@ class Migration: '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'}), + 'votes': ('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'}), @@ -686,7 +856,8 @@ class Migration: }, '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']"}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reviews_all'", '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'}) }, @@ -697,16 +868,17 @@ class Migration: }, 'backend.subtitle': { 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subtitles'", 'to': "orm['backend.File']"}), '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']"}), + 'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'trivia_all'", 'to': "orm['backend.Movie']"}), 'position': ('django.db.models.fields.IntegerField', [], {}), 'trivia': ('django.db.models.fields.TextField', [], {}) }, diff --git a/oxdb/backend/migrations/0002_extend_movies.py b/oxdb/backend/migrations/0002_extend_movies.py deleted file mode 100644 index aa481ee..0000000 --- a/oxdb/backend/migrations/0002_extend_movies.py +++ /dev/null @@ -1,349 +0,0 @@ -# -*- 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'] diff --git a/oxdb/backend/models.py b/oxdb/backend/models.py index 502e229..17a710d 100644 --- a/oxdb/backend/models.py +++ b/oxdb/backend/models.py @@ -7,13 +7,15 @@ import random from django.db import models from django.db.models import Q from django.contrib.auth.models import User -import ox -from ox import stripTags -from ox.normalize import canonicalTitle, canonicalName +from django.core.files.base import ContentFile +import oxlib +from oxlib import stripTags +from oxlib.normalize import canonicalTitle, canonicalName +from django.utils import simplejson as json import utils import managers - +import fields class MovieImdb(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -36,10 +38,13 @@ class MovieImdb(models.Model): 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='') + series_title = models.CharField(max_length=1000, blank=True, default='') + episode_title = models.CharField(max_length=1000, blank=True, default='') season = models.IntegerField(default=-1) episode = models.IntegerField(default=-1) + + def __unicode__(self): + return u"%s (%s)" % (self.title, self.imdbId) class MovieOxdb(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -66,6 +71,9 @@ class MovieOxdb(models.Model): season = models.IntegerField(default=-1) episode = models.IntegerField(default=-1) + def __unicode__(self): + return u"%s (%s)" % (self.title, self.year) + def newMovie(title, director, year): movie = Movie() oxdb = MovieOxdb() @@ -80,13 +88,18 @@ def newMovie(title, director, year): movie.save() return movie +def movie_path(f, size): + name = "%s.%s" % (size, 'ogv') + url_hash = f.movieId + return os.path.join('movie', url_hash[:2], url_hash[2:4], url_hash[4:6], name) + 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) + available = models.BooleanField(default=False, db_index=True) movieId = models.CharField(max_length=128, unique=True, blank=True) oxdbId = models.CharField(max_length=42, unique=True, blank=True) @@ -139,9 +152,9 @@ class Movie(models.Model): def keywords(self): return self._manual(self.keywords_all) def countries(self): - return self._manual(self.countries_all, 'moviecountry__manual') + return self._manual(self.countries_all, 'moviecountry__manual').order_by('moviecountry__position') def languages(self): - return self._manual(self.languages_all, 'movielanguage__manual') + return self._manual(self.languages_all, 'movielanguage__manual').order_by('movielanguage__position') def trivia(self): return self._manual(self.trivia_all) def locations(self): @@ -169,12 +182,59 @@ class Movie(models.Model): rights_level = models.IntegerField(default=-1) + ''' + #these values get populated with imdb/oxdb values on save() + #edits will be overwritten + 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) + ''' + + json = fields.DictField(default={}, editable=False) + + ''' + directors = fields.TupleField(default=()) + writers = fields.TupleField(default=()) + editors = fields.TupleField(default=()) + producers = fields.TupleField(default=()) + cinematographers = fields.TupleField(default=()) + cast = fields.TupleField(default=()) + alternative_titles = fields.TupleField(default=()) + genres = fields.TupleField(default=()) + keywords = fields.TupleField(default=()) + countries = fields.TupleField(default=()) + languages = fields.TupleField(default=()) + trivia = fields.TupleField(default=()) + locations = fields.TupleField(default=()) + connections = fields.DictField(default={}) + reviews = fields.TupleField(default=()) + ''' + #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) + #FIXME: use data.0xdb.org/posters for that #what of this is still required? still_pos = models.IntegerField(null=True, blank=True) poster = models.TextField(blank=True) @@ -182,13 +242,20 @@ class Movie(models.Model): posters_available = models.TextField(blank=True) poster_height = models.IntegerField(null=True, blank=True) poster_width = models.IntegerField(null=True, blank=True) + ''' + #stream related fields + ''' + ''' + stream128 = models.FileField(default=None, blank=True, upload_to=lambda f, x: movie_path(f, '128')) + stream320 = models.FileField(default=None, blank=True, upload_to=lambda f, x: movie_path(f, '320')) + stream640 = models.FileField(default=None, blank=True, upload_to=lambda f, x: movie_path(f, '640')) + #FIXME: is this still required? should this not be aspect ratio? depends on stream??? 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() @@ -200,6 +267,26 @@ class Movie(models.Model): mid = self.oxdbId self.movieId = mid + if self.id: + self.json = self.get_json() + ''' + #populate auto values for faster results + #FIXME: why is it not possible to use setattr to set List instead of db value? + common_fields = [f.name for f in MovieImdb._meta.fields] + only_relevant = lambda f: f not in ('id', 'created', 'modified', 'imdbId') + common_fields = filter(only_relevant, common_fields) + for f in common_fields: + setattr(self, f, self.get(f)) + for f in ('directors', 'writers', 'editors', 'producers', 'cinematographers', + 'reviews', 'countries', 'languages', + 'keywords', 'genres', 'trivia', 'alternative_titles'): + value = getattr(self, 'get_' + f) + setattr(self, f, tuple([v.json() for v in value()])) + for f in ('cast', ): + value = getattr(self, 'get_' + f) + setattr(self, f, value()) + self.connections = self.connections_json() + ''' super(Movie, self).save(*args, **kwargs) self.updateFind() self.updateSort() @@ -229,7 +316,7 @@ class Movie(models.Model): 'alternative_titles': 'alternative_titles', 'connections_json': 'connections' } - def json(self, fields=None): + def get_json(self, fields=None): movie = {} for key in self._public_fields: pub_key = self._public_fields.get(key, key) @@ -238,8 +325,9 @@ class Movie(models.Model): value = getattr(self, key) else: value = self.get(key) - if key in ('directors', 'writers', 'reviews', - 'countries', 'languages', 'keywords', 'genres', 'trivia', 'alternative_titles'): + if key in ('directors', 'writers', 'editors', 'cinematographers', 'producers', + '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() @@ -392,7 +480,7 @@ class MovieFind(models.Model): movie = models.OneToOneField('Movie', related_name='find', primary_key=True) all = models.TextField(blank=True) - title = models.CharField(max_length=1000) + title = models.TextField(blank=True) director = models.TextField(blank=True, default='') country = models.TextField(blank=True, default='') year = models.CharField(max_length=4) @@ -414,18 +502,17 @@ class MovieFind(models.Model): filename = models.TextField(blank=True, default='') _private_fields = ('id', 'movie') - _public_names = { - 'movieId': 'id' - } - def options(self): - options = [] + #return available find fields + #FIXME: should return mapping name -> verbose_name + def fields(self): + fields = [] 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) + name = f.verbose_name + name = name[0].capitalize() + name[1:] + fields.append(name) + return tuple(fields) + fields = classmethod(fields) class MovieSort(models.Model): """ @@ -457,14 +544,14 @@ class MovieSort(models.Model): votes = models.IntegerField(blank=True) scenes = models.IntegerField(blank=True) words = models.IntegerField(null=True, blank=True) - wpm = models.IntegerField(null=True, blank=True) + wpm = models.IntegerField('Words per Minute', null=True, blank=True) risk = models.IntegerField(null=True, blank=True) - movieId = models.CharField(max_length=128, blank=True) + movieId = models.CharField('ID', max_length=128, blank=True) duration = models.FloatField(default=-1) resolution = models.IntegerField(blank=True) - aspectratio = models.IntegerField(blank=True) + aspectratio = models.IntegerField('Aspect Ratio', blank=True) bitrate = models.IntegerField(blank=True) pixels = models.IntegerField(blank=True) filename = models.IntegerField(blank=True) @@ -472,18 +559,17 @@ class MovieSort(models.Model): size = models.IntegerField(blank=True) _private_fields = ('id', 'movie') - _public_names = { - 'movieId': 'id' - } - def options(self): - options = [] + #return available sort fields + #FIXME: should return mapping name -> verbose_name + def fields(self): + fields = [] 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) + name = f.verbose_name + name = name[0].capitalize() + name[1:] + fields.append(name) + return tuple(fields) + fields = classmethod(fields) class AlternativeTitle(models.Model): movie = models.ForeignKey(Movie, related_name='alternative_titles_all') @@ -522,7 +608,7 @@ class Person(models.Model): def save(self, *args, **kwargs): if not self.name_sort: - self.name_sort = ox.normalize.canonicalName(self.name) + self.name_sort = oxlib.normalize.canonicalName(self.name) super(Person, self).save(*args, **kwargs) def get_or_create(model, name, imdbId=None): @@ -544,10 +630,10 @@ class Person(models.Model): return self.name class Cast(models.Model): - movie = models.ForeignKey(Movie) + movie = models.ForeignKey(Movie, related_name='cast_relation') person = models.ForeignKey(Person) role = models.CharField(max_length=200) - character = models.CharField(max_length=200, blank=True) + character = models.CharField(max_length=1000, blank=True) position = models.IntegerField() manual = models.BooleanField(default=False) @@ -736,7 +822,8 @@ class Trivia(models.Model): def json(self): trivia = self.trivia - trivia = ox.fixAmpersands(trivia) + trivia = oxlib.fixAmpersands(trivia) + trivia = re.sub(' ', '', trivia) trivia = re.sub('(.*?)', '\\2', trivia) trivia = re.sub('(.*?)', '\\2', trivia) return trivia @@ -764,6 +851,7 @@ class Connection(models.Model): 'Spin off from': 'Spin off', 'Spoofs': 'Spoofed in', 'Version of': 'Version of', + 'Alternate language version of': 'Alternate language version of', } if relation in _map.values(): for k in _map: @@ -846,22 +934,37 @@ def stream_path(f, size): url_hash = f.oshash return os.path.join('stream', url_hash[:2], url_hash[2:4], url_hash[4:6], name) +def still_path(f, still): + name = "%s.%s" % (still, 'png') + url_hash = f.oshash + return os.path.join('still', url_hash[:2], url_hash[2:4], url_hash[4:6], name) + +FILE_TYPES = ( + (0, 'unknown'), + (1, 'video'), + (2, 'audio'), + (3, 'subtitle'), +) + class File(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) + verified = models.BooleanField(default=False) oshash = models.CharField(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) + sha1 = models.CharField(blank=True, null=True, unique=True, max_length=40) + md5 = models.CharField(blank=True, null=True, unique=True, max_length=32) - movie = models.ForeignKey(Movie, related_name="files", default=None) + movie = models.ForeignKey(Movie, related_name="files", default=None, null=True) - computed_path = models.CharField(blank=True, max_length=2048) - size = models.IntegerField(default=-1) + type = models.IntegerField(default=0, choices=FILE_TYPES) + info = fields.DictField(default={}) + #FIMXE: why do i need those in the db? could jsut have them in info + + path = models.CharField(blank=True, max_length=2048) + size = models.BigIntegerField(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) @@ -876,16 +979,20 @@ class File(models.Model): #computed values bpp = models.FloatField(default=-1) - pixels = models.IntegerField(default=0) + pixels = models.BigIntegerField(default=0) part = models.IntegerField(default=0) + needs_data = models.BooleanField(default=True) + #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')) + timeline = models.ImageField(default=None, null=True, upload_to=lambda f, x: still_path(f, '0')) + def save_chunk(self, chunk, name='video.ogv'): if not self.available: #FIXME: this should use stream128 or stream640 depending on configuration @@ -912,7 +1019,56 @@ class File(models.Model): get_or_create = classmethod(get_or_create) def __unicode__(self): - return "%s (%s)" % (self.computed_path, self.oshash) + return "%s (%s)" % (self.path, self.oshash) + + def update(self, data=None): + """ + only add, do not overwrite keys in file + """ + if data and not self.info: + self.info = data + _video_map = { + 'codec': 'video_codec', + } + if 'video' in self.info and self.info['video']: + for key in ('codec', 'pixel_format', 'width', 'height', + 'pixel_aspect_ratio', 'display_aspect_ratio', 'framerate'): + if key in self.info['video'][0]: + setattr(self, _video_map.get(key, key), self.info['video'][0][key]) + _audio_map = { + 'codec': 'audio_codec', + } + if 'audio' in self.info and self.info['audio']: + for key in ('codec', 'samplerate', 'channels'): + if key in self.info['audio'][0]: + setattr(self, _audio_map.get(key, key), self.info['audio'][0][key]) + + for key in ('duration', 'size', 'sha1', 'md5'): + if key in self.info: + setattr(self, key, self.info[key]) + + #detect and assign type based on extension or detected video track + if os.path.splitext(self.info['path'])[-1] in ('.rar', '.sub', '.idx'): + self.type = 0 + elif 'video' in self.info: + self.type = 1 + elif os.path.splitext(self.info['path'])[-1] in ('.mp3', '.oga'): + self.type = 2 + elif os.path.splitext(self.info['path'])[-1] in ('.srt', ): + self.type = 3 + #FIXME: this should be computed and not submitted path + self.path = self.info['path'] + self.save() + +class Still(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + file = models.ForeignKey(File, related_name="stills") + position = models.FloatField() + still = models.ImageField(default=None, null=True, upload_to=lambda f, x: still_path(f, '0')) + + def __unicode__(self): + return '%s at %s' % (self.file, self.position) class Subtitle(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -935,7 +1091,7 @@ class Subtitle(models.Model): 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) + return '%s.%s.srt' % (os.path.splitext(self.movie_file.path)[0], self.language) class Layer(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -958,6 +1114,9 @@ class Archive(models.Model): name = models.CharField(max_length=255, unique=True) public = models.BooleanField(default=False) users = models.ManyToManyField(User, related_name='archives') + + def __unicode__(self): + return '%s' % (self.name) class ArchiveFile(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -967,32 +1126,27 @@ class ArchiveFile(models.Model): 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.file.update(data) 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 + file = File.get_or_create(oshash) + file.save() + f = model.objects.create(archive=archive, file=file) f.save() return f get_or_create = classmethod(get_or_create) def __unicode__(self): - return '%s (%s)' % (self.path, unicode(self.user)) + return '%s (%s)' % (self.path, unicode(self.archive)) diff --git a/oxdb/backend/urls.py b/oxdb/backend/urls.py index f738b46..ea0b31e 100644 --- a/oxdb/backend/urls.py +++ b/oxdb/backend/urls.py @@ -20,12 +20,11 @@ subtitles/add?oshash&language subtitles/remove?oshash&language ''' -urlpatterns = patterns("oxdb.backend.views", +urlpatterns = patterns("backend.views", (r'^find', 'find'), (r'^files/find', 'find_files'), (r'^files/info', 'file_info'), - (r'^archive/(?P.+)/add', 'add_file'), - (r'^archive/(?P.+)/remove', 'remove_file'), + (r'^archive/(?P.+)/update', 'update_archive'), (r'^file/parse', 'file_parse'), (r'^subtitle/get', 'subtitles'), diff --git a/oxdb/backend/utils.py b/oxdb/backend/utils.py index 0602d65..25f2a9c 100644 --- a/oxdb/backend/utils.py +++ b/oxdb/backend/utils.py @@ -8,9 +8,9 @@ import sys import re import hashlib -import ox -import ox.iso -from ox.normalize import normalizeName +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]) @@ -62,7 +62,7 @@ def oxdb_title(_title, searchTitle = False): return title def oxdb_year(data): - return ox.findRe(data, '\.(\d{4})\.') + return oxlib.findRe(data, '\.(\d{4})\.') def oxdb_series_title(path): seriesTitle = u'' diff --git a/oxdb/backend/views.py b/oxdb/backend/views.py index 618db48..a9c3e96 100644 --- a/oxdb/backend/views.py +++ b/oxdb/backend/views.py @@ -4,16 +4,22 @@ import os.path import re from datetime import datetime from urllib2 import unquote +import json 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.http import HttpResponse from django.contrib.auth.decorators import login_required -from django.utils import simplejson as json -from ox.django.shortcuts import render_to_json_response -from ox.django.decorators import login_required_json +try: + import simplejson as json +except ImportError: + from django.utils import simplejson as json +from oxdjango.shortcuts import render_to_json_response +from oxdjango.decorators import login_required_json + import models import utils @@ -168,13 +174,18 @@ def find(request): if 'n' in query: response = {'items': qs.count()} else: + _p = query['p'] + def only_p(m): + r = {} + if m: + m = json.loads(m) + for p in _p: + r[p] = m[p] + return r 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'])) + + response['items'] = [only_p(m['json']) for m in qs.values('json')] + elif 'g' in query: if query['s'].split(':')[0] not in ('name', 'items'): query['s'] = 'name' @@ -207,9 +218,9 @@ def find(request): 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) + + response['items'] = [{'title': i[name], 'items': i[items]} for i in qs] + else: #FIXME: also filter lists here movies = models.Movie.objects.filter(available=True) @@ -225,23 +236,15 @@ def find(request): ''' 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 + "movie_id": 0123456, ?? "oshash": "a41cde31c581e11d", "sha1":.., "md5":.. + "duration": 5.266667, + "video": [], + "audio": [], + "path": "E/Example, The/An Example.avi", + "size": 1646274 } ''' def file_info(request): @@ -264,7 +267,7 @@ srt = def subtitles(request): oshash = request.GET['oshash'] language = request.GET.get('language', None) - if requeset.method == 'POST': + if request.method == 'POST': user = request.user sub = models.Subtitles.get_or_create(user, oshash, language) sub.srt = request.POST['srt'] @@ -289,6 +292,7 @@ GET list ''' @login_required_json def list_files(request): + response = {} response['files'] = {} qs = models.UserFile.filter(user=request.user) p = Paginator(qs, 1000) @@ -299,9 +303,10 @@ def list_files(request): return render_to_json_response(response) def find_files(request): + response = {} query = parse_query(request) response['files'] = {} - qs = models.UserFile.filter(user=request.user).filter(movie_file__movie__id__in=quert['q']) + qs = models.UserFile.filter(user=request.user).filter(movie_file__movie__id__in=query['q']) p = Paginator(qs, 1000) for i in p.page_range: page = p.page(i) @@ -310,7 +315,7 @@ def find_files(request): return render_to_json_response(response) ''' -POST add +POST metadata > file: { "duration": 5.266667, "video_codec": "mpeg1", @@ -331,8 +336,7 @@ POST add } ''' #@login_required_json -def add_file(request, archive): - print request.POST +def add_metadata(request, archive): info = json.loads(request.POST['file']) oshash = info['oshash'] archive = models.Archive.objects.get(name=archive) @@ -344,15 +348,99 @@ def add_file(request, archive): response = {'status': 404} return render_to_json_response(response) +class StillForm(forms.Form): + still = forms.FileField() + position = forms.FloatField() + +#@login_required_json +def add_still(request, oshash): + response = {'status': 500} + f = get_object_or_404(models.File, oshash=oshash) + + form = TimelineForm(request.POST, request.FILES) + if form.is_valid(): + ff = form.cleaned_data['still'] + position = form.cleaned_data['position'] + + still = models.Still(file=f, position=position) + still.save() + still.still.save(ff, ff.name) + response = {'status': 200} + response['url'] = still.url() + return render_to_json_response(response) + +class TimelineForm(forms.Form): + timeline = forms.FileField() + +#FIXME: should everybody be able to overwrite timelines? +#@login_required_json +def add_timeline(request, oshash): + response = {'status': 500} + f = get_object_or_404(models.File, oshash=oshash) + + form = TimelineForm(request.POST, request.FILES) + if form.is_valid(): + ff = form.cleaned_data['timeline'] + f.timeline.save(ff.name, ff) + response = {'status': 200} + response['url'] = f.timeline.url() + return render_to_json_response(response) + + +class VideoForm(forms.Form): + video = forms.FileField() + +#@login_required_json +def add_video(request, oshash): + response = {'status': 500} + f = get_object_or_404(models.File, oshash=oshash) + + form = VideoForm(request.POST, request.FILES) + if form.is_valid(): + ff = form.cleaned_data['video'] + f.stream128.save(ff.name, ff) + response = {'status': 200} + response['url'] = f.stream128.url() + return render_to_json_response(response) + ''' -POST remove?oshash= +POST update + > files: { + oshash: { 'path': .., ..}, + oshash: { 'path': .., ..}, + } ''' -@login_required_json -def remove_file(request, archive): - oshash = request.POST['oshash'] +#@login_required_json +def update_archive(request, archive): + print "update request" archive = models.Archive.objects.get(name=archive) - models.UserFiles.objects.filter(movie_file__oshash=oshash, user=request.user).delete() - response = {'status': 200} + files = json.loads(request.POST['files']) + print "update request for", archive.name + needs_data = [] + rename = {} + for oshash in files: + print 'checking', oshash + data = files[oshash] + q = models.ArchiveFile.objects.filter(archive=archive, file__oshash=oshash) + if q.count() == 0: + print "adding file", oshash, data['path'] + f = models.ArchiveFile.get_or_create(archive, oshash) + f.update(data) + #FIXME: only add if it was not in File + else: + f = q[0] + if data['path'] != f.path: + f.path = data['path'] + f.save() + if f.file.needs_data: + needs_data.append(oshash) + if f.path != f.file.path: + rename[oshash] = f.file.path + print "processed files for", archive.name + #remove all files not in files.keys() from ArchiveFile + response = {} + response['info'] = needs_data + response['rename'] = rename return render_to_json_response(response) def file_parse(request): diff --git a/oxdb/settings.py b/oxdb/settings.py index 9d7249b..a4ca7be 100644 --- a/oxdb/settings.py +++ b/oxdb/settings.py @@ -52,6 +52,8 @@ TESTS_ROOT = join(PROJECT_ROOT, 'tests') # Examples: "http://media.lawrence.com", "http://example.com/media/" MEDIA_URL = '' +STATIC_URL = '/static/' + # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". @@ -61,7 +63,7 @@ ADMIN_MEDIA_PREFIX = '/admin/media/' TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', -# 'django.template.loaders.eggs.load_template_source', + 'django.template.loaders.eggs.load_template_source', ) MIDDLEWARE_CLASSES = ( @@ -88,6 +90,14 @@ INSTALLED_APPS = ( 'backend', ) +#rabbitmq connection settings +BROKER_HOST = "127.0.0.1" +BROKER_PORT = 5672 +BROKER_USER = "oxdb" +BROKER_PASSWORD = "0xdb" +BROKER_VHOST = "/oxdb" + + #overwrite default settings with local settings try: from local_settings import * diff --git a/oxdb/static/js/ajax_filtered_fields.js b/oxdb/static/js/ajax_filtered_fields.js new file mode 100644 index 0000000..887348d --- /dev/null +++ b/oxdb/static/js/ajax_filtered_fields.js @@ -0,0 +1,91 @@ +ajax_filtered_fields = { + + request_url: "/ajax_filtered_fields/json_index/", + data_loaded: "data_loaded", + + _appendOption: function(obj, selector) { + // append a json data row as an option to the selector + var option = $(''); + option.attr({value: obj[0]}); + option.appendTo(selector); + return option; + }, + + _removeOptions: function(selector) { + // remove all options from selector + selector.children("option").each(function(i) { + $(this).remove(); + }); + }, + + getManyToManyJSON: function(element_id, app_label, object_name, + lookup_string, select_related) { + // manage the ManyToMany ajax request + var selector_from = $("#" + element_id + "_from"); + var selector_to = $("#" + element_id + "_to"); + + $("#" + element_id + "_input").val(""); + selector_from.attr("disabled", true); + selector_to.attr("disabled", true); + + this._removeOptions(selector_from); + + $.getJSON(this.request_url, { + app_label: app_label, + object_name: object_name, + lookup_string: lookup_string, + select_related: select_related}, + function(data){ + $.each(data, function(i, obj){ + var option_is_selected = selector_to.children("option[value='" + obj[0] + "']").length; + if (!option_is_selected) { + ajax_filtered_fields._appendOption(obj, selector_from); + }; + }); + SelectBox.init(element_id + "_from"); + selector_from.attr("disabled", false); + selector_to.attr("disabled", false); + selector_from.trigger(ajax_filtered_fields.data_loaded); + }); + }, + + getForeignKeyJSON: function(element_id, app_label, object_name, + lookup_string, select_related) { + // manage the ForeignKey ajax request + var selector = $("#" + element_id); + var hidden = $("#hidden-" + element_id); + + $("#" + element_id + "_input").val(""); + selector.attr("disabled", true); + + this._removeOptions(selector); + + $.getJSON(this.request_url, { + app_label: app_label, + object_name: object_name, + lookup_string: lookup_string, + select_related: select_related}, + function(data){ + var selection = hidden.val(); + ajax_filtered_fields._appendOption(new Array("", "---------"), selector); + $.each(data, function(i, obj){ + ajax_filtered_fields._appendOption(obj, selector); + }); + selector.children("option[value='" + selection + "']").attr("selected", "selected"); + selector.attr("disabled", false); + SelectBox.init(element_id); + ajax_filtered_fields.bindForeignKeyOptions(element_id); + selector.trigger(ajax_filtered_fields.data_loaded); + }); + }, + + bindForeignKeyOptions: function(element_id) { + // bind the dummy options to the hidden field that do the work + var selector = $("#" + element_id); + var hidden = $("#hidden-" + element_id); + selector.change(function(e) { + hidden.val($(this).val()); + }); + } + +}; diff --git a/oxdb/static/js/ui.js b/oxdb/static/js/ui.js index e782515..1990a66 100644 --- a/oxdb/static/js/ui.js +++ b/oxdb/static/js/ui.js @@ -568,7 +568,7 @@ $(function() { items.push({ size: 64, id: code, - icon: "http://oil21.org/tmp/flags/" + flag + ".png", + icon: "http://localhost/oxdbstatic/flags/" + flag + ".png", title: strings[0] + (strings.length > 1 ? "
" + strings[1] : ""), info: Ox.formatNumber(v.items) + " Movie" + (v.items > 1 ? "s" : "") }); diff --git a/oxdb/urls.py b/oxdb/urls.py index 810f5c2..d968507 100644 --- a/oxdb/urls.py +++ b/oxdb/urls.py @@ -9,6 +9,7 @@ admin.autodiscover() urlpatterns = patterns('', # Example: + (r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')), (r'^json/', include('backend.urls')), (r'^$', 'app.views.index'), diff --git a/oxdb/user_management/views.py b/oxdb/user_management/views.py index 689363a..c3da9bf 100644 --- a/oxdb/user_management/views.py +++ b/oxdb/user_management/views.py @@ -6,8 +6,8 @@ from django.shortcuts import render_to_response, get_object_or_404, get_list_or_ from django.template import RequestContext from django.utils import simplejson as json -from ox.django.shortcuts import render_to_json_response -from ox.django.decorators import login_required_json +from oxdjango.shortcuts import render_to_json_response +from oxdjango.decorators import login_required_json import models @@ -51,7 +51,7 @@ def recover(request): if q.count() > 0: user = q[0] if user: - user.sendmail(...) #FIXME: send recovery mail + #user.sendmail(...) #FIXME: send recovery mail response = {'status': 200, 'message': 'recovert email sent.'} else: response = {'status': 500, 'message': 'user or email not found.'} @@ -80,7 +80,7 @@ def preferences(request): if key == 'password': user.set_password(value) user.save() - elsif key == 'email': + elif key == 'email': user.email = vaule user.save() else: