rename Movie to Item

This commit is contained in:
j 2010-09-23 18:01:48 +02:00
parent 0955a03fa4
commit 2ad4abd820
14 changed files with 657 additions and 250 deletions

View file

@ -3,7 +3,7 @@
from django.contrib import admin from django.contrib import admin
#from forms import FileAdminForm, MovieAdminForm, ArchiveFileAdminForm #from forms import FileAdminForm, ItemAdminForm, ArchiveFileAdminForm
import models import models
class FileAdmin(admin.ModelAdmin): class FileAdmin(admin.ModelAdmin):

View file

@ -326,7 +326,7 @@ def divide(num, by):
arr.append(div + (i > by - 1 - mod)) arr.append(div + (i > by - 1 - mod))
return arr return arr
def timeline_strip(movie, cuts, info, prefix): def timeline_strip(item, cuts, info, prefix):
_debug = False _debug = False
duration = info['duration'] duration = info['duration']
video_height = info['video'][0]['height'] video_height = info['video'][0]['height']
@ -353,29 +353,29 @@ def timeline_strip(movie, cuts, info, prefix):
c = cuts.index(frame) c = cuts.index(frame)
if c +1 < len(cuts): if c +1 < len(cuts):
duration = cuts[c + 1] - cuts[c] duration = cuts[c + 1] - cuts[c]
stills = math.ceil(duration / (video_width * timeline_height / video_height)) frames = math.ceil(duration / (video_width * timeline_height / video_height))
widths = divide(duration, stills) widths = divide(duration, frames)
still = frame frame = frame
if _debug: if _debug:
print widths, duration, stills, cuts[c], cuts[c + 1] print widths, duration, frames, cuts[c], cuts[c + 1]
for s in range(int(stills)): for s in range(int(frames)):
still_ratio = widths[s] / timeline_height frame_ratio = widths[s] / timeline_height
if video_ratio > still_ratio: if video_ratio > frame_ratio:
width = int(round(video_height * still_ratio)) width = int(round(video_height * frame_ratio))
left = int((video_width - width) / 2) left = int((video_width - width) / 2)
box = (left, 0, left + width, video_height) box = (left, 0, left + width, video_height)
else: else:
height = int(round(video_width / still_ratio)) height = int(round(video_width / frame_ratio))
top = int((video_height - height) / 2) top = int((video_height - height) / 2)
box = (0, top, video_width, top + height) box = (0, top, video_width, top + height)
if _debug: if _debug:
print frame, 'cut', c, 'still', s, still, 'width', widths[s], box print frame, 'cut', c, 'frame', s, frame, 'width', widths[s], box
#FIXME: why does this have to be still+1? #FIXME: why does this have to be frame+1?
frame_image = Image.open(movie.frame((still+1)/fps)) frame_image = Image.open(item.frame((frame+1)/fps))
frame_image = frame_image.crop(box).resize((widths[s], timeline_height), Image.ANTIALIAS) frame_image = frame_image.crop(box).resize((widths[s], timeline_height), Image.ANTIALIAS)
for x_ in range(widths[s]): for x_ in range(widths[s]):
line_image.append(frame_image.crop((x_, 0, x_ + 1, timeline_height))) line_image.append(frame_image.crop((x_, 0, x_ + 1, timeline_height)))
still += widths[s] frame += widths[s]
if len(line_image) > frame: if len(line_image) > frame:
timeline_image.paste(line_image[frame], (x, 0)) timeline_image.paste(line_image[frame], (x, 0))
if x == timeline_width - 1: if x == timeline_width - 1:

View file

@ -0,0 +1,146 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_column('archive_file', 'movie_id', 'item_id')
def backwards(self, orm):
db.rename_column('archive_file', 'item_id', 'movie_id')
models = {
'archive.file': {
'Meta': {'object_name': 'File'},
'audio_codec': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'bits_per_pixel': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
'channels': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'data': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'display_aspect_ratio': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'duration': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'episode': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
'framerate': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'info': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'is_audio': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_extra': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_subtitle': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_version': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_video': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'item': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['backend.Item']"}),
'language': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
'oshash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '16'}),
'part': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'pixel_format': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'pixels': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'samplerate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'season': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'sort_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
'verified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'video': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'video_codec': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'width': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'archive.fileinstance': {
'Meta': {'unique_together': "(('name', 'folder', 'volume'),)", 'object_name': 'FileInstance'},
'atime': ('django.db.models.fields.IntegerField', [], {'default': '1285254686'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'ctime': ('django.db.models.fields.IntegerField', [], {'default': '1285254686'}),
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'instances'", 'to': "orm['archive.File']"}),
'folder': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'mtime': ('django.db.models.fields.IntegerField', [], {'default': '1285254686'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
'volume': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['archive.Volume']"})
},
'archive.frame': {
'Meta': {'unique_together': "(('file', 'position'),)", 'object_name': 'Frame'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'frames'", 'to': "orm['archive.File']"}),
'frame': ('django.db.models.fields.files.ImageField', [], {'default': 'None', 'max_length': '100', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'position': ('django.db.models.fields.FloatField', [], {})
},
'archive.volume': {
'Meta': {'unique_together': "(('user', 'name'),)", 'object_name': 'Volume'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'volumes'", 'to': "orm['auth.User']"})
},
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'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': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'backend.item': {
'Meta': {'object_name': 'Item'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'imdb': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'itemId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
'json': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'metadata': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'oxdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '42', 'blank': 'True'}),
'poster': ('django.db.models.fields.files.ImageField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'}),
'poster_frame': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
'poster_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'poster_url': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'poster_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'stream_aspect': ('django.db.models.fields.FloatField', [], {'default': '1.3333333333333333'})
},
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['archive']

View file

@ -23,7 +23,7 @@ from firefogg import Firefogg
import chardet import chardet
from backend import utils from backend import utils
from pandora.backend.models import Movie from pandora.backend.models import Item
import extract import extract
@ -46,7 +46,7 @@ class File(models.Model):
verified = models.BooleanField(default=False) verified = models.BooleanField(default=False)
oshash = models.CharField(max_length=16, unique=True) oshash = models.CharField(max_length=16, unique=True)
movie = models.ForeignKey(Movie, related_name='files') item = models.ForeignKey(Item, related_name='files')
name = models.CharField(max_length=2048, default="") # canoncial path/file name = models.CharField(max_length=2048, default="") # canoncial path/file
sort_name = models.CharField(max_length=2048, default="") # sort path/file name sort_name = models.CharField(max_length=2048, default="") # sort path/file name
@ -260,8 +260,8 @@ class FileInstance(models.Model):
return u"%s's %s <%s>"% (self.volume.user, self.name, self.file.oshash) return u"%s's %s <%s>"% (self.volume.user, self.name, self.file.oshash)
@property @property
def movieId(self): def itemId(self):
return File.objects.get(oshash=self.oshash).movieId return File.objects.get(oshash=self.oshash).itemId
def frame_path(frame, name): def frame_path(frame, name):
ext = os.path.splitext(name)[-1] ext = os.path.splitext(name)[-1]

View file

@ -56,7 +56,7 @@ def api_update(request):
param data param data
volume: '', volume: '',
files: [ files: [
{oshash:, path:, ctime:, atime:, mtime:, } {oshash:, path:, mtime:, }
] ]
info: {oshash: object} info: {oshash: object}
@ -88,9 +88,9 @@ def api_update(request):
same_folder = models.FileInstance.objects.filter(folder=folder, volume=volume) same_folder = models.FileInstance.objects.filter(folder=folder, volume=volume)
if same_folder.count() > 0: if same_folder.count() > 0:
movie = same_folder[0].file.movie item = same_folder[0].file.item
else: else:
movie = None item = None
path = os.path.join(folder, name) path = os.path.join(folder, name)
@ -98,7 +98,7 @@ def api_update(request):
if instance.count()>0: if instance.count()>0:
instance = instance[0] instance = instance[0]
updated = False updated = False
for key in ('atime', 'mtime', 'ctime', 'name', 'folder'): for key in ('mtime', 'name', 'folder'):
if f[key] != getattr(instance, key): if f[key] != getattr(instance, key):
setattr(instance, key, f[key]) setattr(instance, key, f[key])
updated=True updated=True
@ -111,24 +111,24 @@ def api_update(request):
file_object = file_objects[0] file_object = file_objects[0]
#new oshash, add to database #new oshash, add to database
else: else:
if not movie: if not item:
movie_info = parse_path(folder) item_info = parse_path(folder)
movie = backend.models.getMovie(movie_info) item = backend.models.getItem(item_info)
file_object = models.File() file_object = models.File()
file_object.oshash = oshash file_object.oshash = oshash
file_object.name = name file_object.name = name
file_object.movie = movie file_object.item = item
file_object.save() file_object.save()
response['data']['info'].append(oshash) response['data']['info'].append(oshash)
instance = models.FileInstance() instance = models.FileInstance()
instance.volume = volume instance.volume = volume
instance.file = file_object instance.file = file_object
for key in ('atime', 'mtime', 'ctime', 'name', 'folder'): for key in ('mtime', 'name', 'folder'):
setattr(instance, key, f[key]) setattr(instance, key, f[key])
instance.save() instance.save()
#remove deleted files #remove deleted files
#FIXME: can this have any bad consequences? i.e. on the selction of used movie files. #FIXME: can this have any bad consequences? i.e. on the selction of used item files.
models.FileInstance.objects.filter(volume=volume).exclude(file__oshash__in=all_files).delete() models.FileInstance.objects.filter(volume=volume).exclude(file__oshash__in=all_files).delete()
user_profile = user.get_profile() user_profile = user.get_profile()
@ -255,7 +255,7 @@ def api_editFile(request): #FIXME: should this be file.files. or part of update
def lookup_file(request, oshash): def lookup_file(request, oshash):
f = get_object_or_404(models.File, oshash=oshash) f = get_object_or_404(models.File, oshash=oshash)
return redirect(f.movie.get_absolute_url()) return redirect(f.item.get_absolute_url())
""" """
@ -270,7 +270,7 @@ def api_fileInfo(request):
oshash = json.loads(request.POST['data']) oshash = json.loads(request.POST['data'])
elif 'oshash' in request.GET: elif 'oshash' in request.GET:
oshash = request.GET['oshash'] oshash = request.GET['oshash']
f = models.MovieFile.objects.get(oshash=oshash) f = models.ItemFile.objects.get(oshash=oshash)
response = {'data': f.json()} response = {'data': f.json()}
return render_to_json_response(response) return render_to_json_response(response)
@ -301,11 +301,11 @@ def api_subtitles(request):
else: else:
response = json_response({}) response = json_response({})
if language: if language:
q = models.Subtitles.objects.filter(movie_file__oshash=oshash, language=language) q = models.Subtitles.objects.filter(item_file__oshash=oshash, language=language)
if q.count() > 0: if q.count() > 0:
response['data']['subtitle'] = q[0].srt response['data']['subtitle'] = q[0].srt
return render_to_json_response(response) return render_to_json_response(response)
l = models.Subtitles.objects.filter(movie_file__oshash=oshash).values('language') l = models.Subtitles.objects.filter(item_file__oshash=oshash).values('language')
response['data']['languages'] = [f['language'] for f in l] response['data']['languages'] = [f['language'] for f in l]
return render_to_json_response(response) return render_to_json_response(response)
""" """

View file

@ -3,27 +3,27 @@
from django.contrib import admin from django.contrib import admin
#from forms import FileAdminForm, MovieAdminForm, ArchiveFileAdminForm #from forms import FileAdminForm, ItemAdminForm, ArchiveFileAdminForm
import models import models
''' '''
#class MovieImdbAdmin(admin.ModelAdmin): #class ItemImdbAdmin(admin.ModelAdmin):
# search_fields = ['imdbId', 'title'] # search_fields = ['imdbId', 'title']
#admin.site.register(models.MovieImdb, MovieImdbAdmin) #admin.site.register(models.ItemImdb, ItemImdbAdmin)
class MovieImdbInline(admin.StackedInline): class ItemImdbInline(admin.StackedInline):
model = models.MovieImdb model = models.ItemImdb
class MovieOxdbInline(admin.StackedInline): class ItemOxdbInline(admin.StackedInline):
model = models.MovieOxdb model = models.ItemOxdb
''' '''
class MovieAdmin(admin.ModelAdmin): class ItemAdmin(admin.ModelAdmin):
search_fields = ['movieId', 'imdb__title', 'oxdb__title'] search_fields = ['itemId', 'imdb__title', 'oxdb__title']
#form = MovieAdminForm #form = ItemAdminForm
#inlines = [MovieImdbInline, MovieOxdbInline] #inlines = [ItemImdbInline, ItemOxdbInline]
admin.site.register(models.Movie, MovieAdmin) admin.site.register(models.Item, ItemAdmin)

View file

@ -12,7 +12,7 @@ ajax_filtered_js = (
) )
""" """
class FileAdminForm(forms.ModelForm): class FileAdminForm(forms.ModelForm):
movie = ForeignKeyByLetter(models.Movie, field_name='imdb__title') item = ForeignKeyByLetter(models.Item, field_name='imdb__title')
class Meta: class Meta:
model = models.File model = models.File
@ -30,12 +30,12 @@ class ArchiveFileAdminForm(forms.ModelForm):
js = ajax_filtered_js js = ajax_filtered_js
class MovieAdminForm(forms.ModelForm): class ItemAdminForm(forms.ModelForm):
imdb = ForeignKeyByLetter(models.MovieImdb, field_name='title') imdb = ForeignKeyByLetter(models.ItemImdb, field_name='title')
oxdb = ForeignKeyByLetter(models.MovieOxdb, field_name='title') oxdb = ForeignKeyByLetter(models.ItemOxdb, field_name='title')
class Meta: class Meta:
model = models.Movie model = models.Item
class Media: class Media:
js = ajax_filtered_js js = ajax_filtered_js

View file

@ -19,7 +19,7 @@ def debug(*msgs):
'''Import data from imdb into database, '''Import data from imdb into database,
param: impdb id param: impdb id
return: Movie Object, None if failed return: Item Object, None if failed
''' '''
def loadIMDb(imdbId): def loadIMDb(imdbId):
@ -27,17 +27,17 @@ def loadIMDb(imdbId):
debug("IMDb ID not valid") debug("IMDb ID not valid")
return None return None
try: try:
movie = models.Movie.byImdbId(imdbId) item = models.Item.byImdbId(imdbId)
except models.Movie.DoesNotExist: except models.Item.DoesNotExist:
#this shound not happen, just in case previous imports failed #this shound not happen, just in case previous imports failed
try: try:
imdb = models.MovieImdb.objects.get(imdbId=imdbId) imdb = models.ItemImdb.objects.get(imdbId=imdbId)
except models.MovieImdb.DoesNotExist: except models.ItemImdb.DoesNotExist:
imdb = models.MovieImdb() imdb = models.ItemImdb()
imdb.imdbId = imdbId imdb.imdbId = imdbId
imdb.save() imdb.save()
movie = models.Movie() item = models.Item()
movie.imdb = imdb item.imdb = imdb
info = ox.web.imdb.getMovieInfo(imdbId) info = ox.web.imdb.getMovieInfo(imdbId)
for key in ('title', for key in ('title',
@ -50,7 +50,7 @@ def loadIMDb(imdbId):
'season', 'season',
'episode'): 'episode'):
if key in info: if key in info:
setattr(movie.imdb, key, info[key]) setattr(item.imdb, key, info[key])
debug(key, info[key]) debug(key, info[key])
_info_map = { _info_map = {
'episode title': 'episode_title', 'episode title': 'episode_title',
@ -58,86 +58,86 @@ def loadIMDb(imdbId):
} }
for key in _info_map.keys(): for key in _info_map.keys():
if key in info: if key in info:
setattr(movie.imdb, _info_map.get(key, key), info[key]) setattr(item.imdb, _info_map.get(key, key), info[key])
movie.imdb.plot = ox.web.imdb.getMoviePlot(imdbId) item.imdb.plot = ox.web.imdb.getMoviePlot(imdbId)
debug("plot", movie.imdb.plot) debug("plot", item.imdb.plot)
movie.imdb.runtime = ox.web.imdb.getMovieRuntimeSeconds(imdbId) item.imdb.runtime = ox.web.imdb.getMovieRuntimeSeconds(imdbId)
business = ox.web.imdb.getMovieBusinessSum(imdbId) business = ox.web.imdb.getMovieBusinessSum(imdbId)
for key in ('gross', 'profit', 'budget'): for key in ('gross', 'profit', 'budget'):
setattr(movie.imdb, key, business[key]) setattr(item.imdb, key, business[key])
movie.imdb.save() item.imdb.save()
movie.oxdbId = "__init__%s" % random.randint(0, 100000) item.oxdbId = "__init__%s" % random.randint(0, 100000)
movie.save() item.save()
models.AlternativeTitle.objects.filter(movie=movie, manual=False).delete() models.AlternativeTitle.objects.filter(item=item, manual=False).delete()
for i in ox.web.imdb.getMovieAKATitles(imdbId): for i in ox.web.imdb.getMovieAKATitles(imdbId):
t = models.AlternativeTitle() t = models.AlternativeTitle()
t.movie = movie t.item = item
t.title = i[0] t.title = i[0]
t.type = i[1] t.type = i[1]
t.save() t.save()
#FIXME: related tables should be cleaned to not accumulate cruft #FIXME: related tables should be cleaned to not accumulate cruft
#Country #Country
models.MovieCountry.objects.filter(movie=movie, manual=False).delete() models.ItemCountry.objects.filter(item=item, manual=False).delete()
position = 0 position = 0
if 'country' in info: if 'country' in info:
for i in info['country']: for i in info['country']:
debug("add country", i) debug("add country", i)
country, created = models.Country.objects.get_or_create(name=i) country, created = models.Country.objects.get_or_create(name=i)
models.MovieCountry.link(movie, country, position) models.ItemCountry.link(item, country, position)
position += 1 position += 1
#Language #Language
models.MovieLanguage.objects.filter(movie=movie, manual=False).delete() models.ItemLanguage.objects.filter(item=item, manual=False).delete()
position = 0 position = 0
if 'language' in info: if 'language' in info:
for i in info['language']: for i in info['language']:
debug("add language", i) debug("add language", i)
language, created = models.Language.objects.get_or_create(name=i) language, created = models.Language.objects.get_or_create(name=i)
models.MovieLanguage.link(movie, language, position) models.ItemLanguage.link(item, language, position)
position += 1 position += 1
#Location #Location
movie.locations_all.filter(manual=False).delete() item.locations_all.filter(manual=False).delete()
locations = ox.web.imdb.getMovieLocations(imdbId) locations = ox.web.imdb.getMovieLocations(imdbId)
for i in locations: for i in locations:
debug("add location", i) debug("add location", i)
location, created = models.Location.objects.get_or_create(name=i) location, created = models.Location.objects.get_or_create(name=i)
location.movies.add(movie) location.items.add(item)
#Genre #Genre
movie.genres_all.filter(manual=False).delete() item.genres_all.filter(manual=False).delete()
if 'genre' in info: if 'genre' in info:
for i in info['genre']: for i in info['genre']:
debug("add genre", i) debug("add genre", i)
genre, created = models.Genre.objects.get_or_create(name=i) genre, created = models.Genre.objects.get_or_create(name=i)
genre.movies.add(movie) genre.items.add(item)
#Keyword #Keyword
movie.keywords_all.filter(manual=False).delete() item.keywords_all.filter(manual=False).delete()
keywords = ox.web.imdb.getMovieKeywords(imdbId) keywords = ox.web.imdb.getMovieKeywords(imdbId)
for g in keywords: for g in keywords:
debug("add keyword", g) debug("add keyword", g)
keyword, created = models.Keyword.objects.get_or_create(name=g) keyword, created = models.Keyword.objects.get_or_create(name=g)
keyword.movies.add(movie) keyword.items.add(item)
movie.trivia_all.filter(manual=False).delete() item.trivia_all.filter(manual=False).delete()
position = 0 position = 0
trivia = ox.web.imdb.getMovieTrivia(imdbId) trivia = ox.web.imdb.getMovieTrivia(imdbId)
for i in trivia: for i in trivia:
debug("add trivia", i) debug("add trivia", i)
t = models.Trivia() t = models.Trivia()
t.movie = movie t.item = item
t.trivia = i t.trivia = i
t.position = position t.position = position
t.save() t.save()
position += 1 position += 1
position = 0 position = 0
models.Cast.objects.filter(movie=movie).filter(manual=False).delete() models.Cast.objects.filter(item=item).filter(manual=False).delete()
credits = ox.web.imdb.getMovieCredits(imdbId) credits = ox.web.imdb.getMovieCredits(imdbId)
for role in credits: for role in credits:
for p in credits[role]: for p in credits[role]:
@ -147,29 +147,29 @@ def loadIMDb(imdbId):
#FIXME: we could save character information here #FIXME: we could save character information here
character = stripTags(p[1]) character = stripTags(p[1])
person = models.Person.get_or_create(name, imdb_id) person = models.Person.get_or_create(name, imdb_id)
models.Cast.link(movie, person, role, character, position) models.Cast.link(item, person, role, character, position)
position += 1 position += 1
movie.connections_all.filter(manual=False).delete() item.connections_all.filter(manual=False).delete()
connections = ox.web.imdb.getMovieConnections(imdbId) connections = ox.web.imdb.getMovieConnections(imdbId)
for relation in connections: for relation in connections:
for otherId in connections[relation]: for otherId in connections[relation]:
try: try:
object = models.Movie.objects.get(imdb__imdbId=otherId) object = models.Item.objects.get(imdb__imdbId=otherId)
debug("add connection", relation, object) debug("add connection", relation, object)
models.Connection.get_or_create(movie, relation, object) models.Connection.get_or_create(item, relation, object)
except models.Movie.DoesNotExist: except models.Item.DoesNotExist:
pass pass
reviews = ox.web.imdb.getMovieExternalReviews(imdbId) reviews = ox.web.imdb.getMovieExternalReviews(imdbId)
movie.reviews_all.filter(manual=False).delete() item.reviews_all.filter(manual=False).delete()
for r in reviews: for r in reviews:
debug("add review", r) debug("add review", r)
review = models.Review.get_or_create(movie, r) review = models.Review.get_or_create(item, r)
review.title = reviews[r] review.title = reviews[r]
review.save() review.save()
movie.oxdbId = movie.oxid() item.oxdbId = item.oxid()
movie.save() item.save()
return movie return item

View file

@ -36,7 +36,7 @@ def parseCondition(condition):
''' '''
k = condition.get('key', 'all') k = condition.get('key', 'all')
k = {'id': 'movieId'}.get(k, k) k = {'id': 'itemId'}.get(k, k)
if not k: k = 'all' if not k: k = 'all'
v = condition['value'] v = condition['value']
op = condition.get('operator', None) op = condition.get('operator', None)
@ -49,9 +49,9 @@ def parseCondition(condition):
if keyType(k) == "string": if keyType(k) == "string":
in_find=True in_find=True
if op == '=': if op == '=':
if k in models.Movie.facet_keys: if k in models.Item.facet_keys:
in_find=False in_find=False
v = models.Movie.objects.filter(facets__key=k, facets__value=v) v = models.Item.objects.filter(facets__key=k, facets__value=v)
k = 'id__in' k = 'id__in'
else: else:
k = '%s__iexact' % k k = '%s__iexact' % k
@ -63,7 +63,7 @@ def parseCondition(condition):
k = '%s__iendswith' % k k = '%s__iendswith' % k
else: # elif op == '~': else: # elif op == '~':
k = '%s__icontains' % k k = '%s__icontains' % k
if in_find and not k.startswith('movieId'): if in_find and not k.startswith('itemId'):
k = 'find__%s' % k k = 'find__%s' % k
k = str(k) k = str(k)
if exclude: if exclude:
@ -151,9 +151,9 @@ def parseConditions(conditions, operator):
return q return q
return None return None
class MovieManager(Manager): class ItemManager(Manager):
def get_query_set(self): def get_query_set(self):
return super(MovieManager, self).get_query_set() return super(ItemManager, self).get_query_set()
def filter_list(self, qs, l, user): def filter_list(self, qs, l, user):
if l != "all": if l != "all":
@ -195,7 +195,7 @@ class MovieManager(Manager):
#join query with operator #join query with operator
qs = self.get_query_set() qs = self.get_query_set()
#only include movies that have hard metadata #only include items that have hard metadata
qs = qs.filter(available=True) qs = qs.filter(available=True)
conditions = parseConditions(data['query']['conditions'], conditions = parseConditions(data['query']['conditions'],
data['query'].get('operator', '&')) data['query'].get('operator', '&'))
@ -212,17 +212,17 @@ class FileManager(Manager):
def get_query_set(self): def get_query_set(self):
return super(FileManager, self).get_query_set() return super(FileManager, self).get_query_set()
def movie_files(self, movie): def item_files(self, item):
q = self.get_query_set() q = self.get_query_set()
return q.filter(type=1, movie=movie) return q.filter(type=1, item=item)
class ArchiveFileManager(Manager): class ArchiveFileManager(Manager):
def get_query_set(self): def get_query_set(self):
return super(ArchiveFileManager, self).get_query_set() return super(ArchiveFileManager, self).get_query_set()
def movie_files(self, movie): def item_files(self, item):
q = self.get_query_set() q = self.get_query_set()
return q.filter(file__is_video=True, file__movie=movie) return q.filter(file__is_video=True, file__item=item)
def by_oshash(self, oshash): def by_oshash(self, oshash):
q = self.get_query_set() q = self.get_query_set()

View file

@ -0,0 +1,261 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('backend_moviesort', 'backend_itemsort')
db.rename_table('backend_moviefind', 'backend_itemfind')
db.rename_table('backend_movie', 'backend_item')
db.rename_column('backend_item', 'movieId', 'itemId')
db.rename_column('backend_itemsort', 'movieId', 'itemId')
db.rename_column('backend_itemsort', 'movie_id', 'item_id')
db.rename_column('backend_itemfind', 'movie_id', 'item_id')
db.rename_column('backend_posterurl', 'movie_id', 'item_id')
db.rename_column('backend_stream', 'movie_id', 'item_id')
db.rename_column('backend_facet', 'movie_id', 'item_id')
db.rename_column('backend_layer', 'movie_id', 'item_id')
db.rename_column('backend_listitem', 'movie_id', 'item_id')
db.create_unique('backend_posterurl', ['url', 'item_id', 'service'])
db.execute("UPDATE backend_item SET poster=REPLACE(poster,'movies/','items/') WHERE poster LIKE 'movies/%'")
db.execute("UPDATE backend_stream SET video=REPLACE(video,'movies/','items/') WHERE video LIKE 'movies/%'")
def backwards(self, orm):
db.rename_table('backend_itemsort', 'backend_moviesort')
db.rename_table('backend_itemfind', 'backend_moviefind')
db.rename_table('backend_item', 'backend_movie')
db.rename_column('backend_item', 'itemId', 'movieId')
db.rename_column('backend_itemsort', 'itemId', 'movieId')
db.rename_column('backend_itemsort', 'item_id', 'movie')
db.rename_column('backend_itemfind', 'item_id', 'movie')
db.rename_column('backend_posterurl', 'item_id', 'movie')
db.rename_column('backend_stream', 'item_id', 'movie')
db.rename_column('backend_facet', 'item_id', 'movie_id')
db.rename_column('backend_layer', 'item_id', 'movie_id')
db.rename_column('backend_listitem', 'item_id', 'movie_id')
db.create_unique('backend_posterurl', ['url', 'movie_id', 'service'])
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'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': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'backend.collection': {
'Meta': {'object_name': 'Collection'},
'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'}),
'items': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Item']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
'subdomain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048'}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'collections'", 'symmetrical': 'False', 'to': "orm['auth.User']"})
},
'backend.facet': {
'Meta': {'object_name': 'Facet'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'db_index': 'True'}),
'item': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'facets'", 'to': "orm['backend.Item']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'value_sort': ('django.db.models.fields.CharField', [], {'max_length': '200'})
},
'backend.layer': {
'Meta': {'object_name': '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'}),
'item': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Item']"}),
'start': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
'stop': ('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': {
'Meta': {'object_name': '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'}),
'lists': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'lists'", 'symmetrical': 'False', 'through': "orm['backend.ListItem']", 'to': "orm['backend.Item']"}),
'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': {
'Meta': {'object_name': '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'}),
'item': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['backend.Item']"})
},
'backend.location': {
'Meta': {'object_name': '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'}),
'manual': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'items': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'locations_all'", 'symmetrical': 'False', 'to': "orm['backend.Item']"}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
},
'backend.item': {
'Meta': {'object_name': 'Item'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'imdb': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'json': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'metadata': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'itemId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
'oxdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '42', 'blank': 'True'}),
'poster': ('django.db.models.fields.files.ImageField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'}),
'poster_frame': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
'poster_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'poster_url': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'poster_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'stream_aspect': ('django.db.models.fields.FloatField', [], {'default': '1.3333333333333333'})
},
'backend.itemfind': {
'Meta': {'object_name': 'ItemFind'},
'actor': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'all': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'character': ('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'}),
'dialog': ('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'}),
'keyword': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'language': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'item': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'find'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['backend.Item']"}),
'producer': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'title': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'trivia': ('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.itemsort': {
'Meta': {'object_name': 'ItemSort'},
'aspectratio': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'bitrate': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'cast': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'cinematographer': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'cinematographer_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'connections': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'country': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'country_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'dialog': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'director': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'director_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'duration': ('django.db.models.fields.FloatField', [], {'default': '-1', 'db_index': 'True'}),
'editor': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'editor_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'filename': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'files': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'genre': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'keywords': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'language': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'language_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'item': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'sort'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['backend.Item']"}),
'itemId': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'blank': 'True'}),
'pixels': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'producer': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'producer_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'rating': ('django.db.models.fields.FloatField', [], {'db_index': 'True', 'blank': 'True'}),
'resolution': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'risk': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'runtime': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'scenes': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'size': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'summary': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'db_index': 'True'}),
'title_desc': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'db_index': 'True'}),
'trivia': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'votes': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
'words': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'wpm': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'writer': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'writer_desc': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'blank': 'True'}),
'year': ('django.db.models.fields.CharField', [], {'max_length': '4', 'db_index': 'True'}),
'year_desc': ('django.db.models.fields.CharField', [], {'max_length': '4', 'db_index': 'True'})
},
'backend.person': {
'Meta': {'object_name': 'Person'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'imdbId': ('django.db.models.fields.CharField', [], {'max_length': '7', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'name_sort': ('django.db.models.fields.CharField', [], {'max_length': '200'})
},
'backend.posterurl': {
'Meta': {'object_name': 'PosterUrl'},
'height': ('django.db.models.fields.IntegerField', [], {'default': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'item': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'poster_urls'", 'to': "orm['backend.Item']"}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'width': ('django.db.models.fields.IntegerField', [], {'default': '80'})
},
'backend.reviewwhitelist': {
'Meta': {'object_name': '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.stream': {
'Meta': {'unique_together': "(('item', 'profile'),)", 'object_name': 'Stream'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'info': ('oxdjango.fields.DictField', [], {'default': '{}'}),
'item': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'streams'", 'to': "orm['backend.Item']"}),
'profile': ('django.db.models.fields.CharField', [], {'default': "'96p.webm'", 'max_length': '255'}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'derivatives'", 'null': 'True', 'to': "orm['backend.Stream']"}),
'video': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['backend']

View file

@ -29,50 +29,50 @@ import utils
from archive import extract from archive import extract
def getMovie(info): def getItem(info):
''' '''
info dict with: info dict with:
imdbId, title, director, episode_title, season, series imdbId, title, director, episode_title, season, series
''' '''
if 'imdbId' in info and info['imdbId']: if 'imdbId' in info and info['imdbId']:
try: try:
movie = Movie.objects.get(movieId=info['imdbId']) item = Item.objects.get(itemId=info['imdbId'])
except Movie.DoesNotExist: except Item.DoesNotExist:
movie = Movie(movieId=info['imdbId']) item = Item(itemId=info['imdbId'])
if 'title' in info and 'directors' in info: if 'title' in info and 'directors' in info:
movie.imdb = { item.imdb = {
'title': info['title'], 'title': info['title'],
'directors': info['directors'], 'directors': info['directors'],
'year': info.get('year', '') 'year': info.get('year', '')
} }
#FIXME: this should be done async #FIXME: this should be done async
#movie.save() #item.save()
#tasks.updateImdb.delay(movie.movieId) #tasks.updateImdb.delay(item.itemId)
movie.updateImdb() item.updateImdb()
else: else:
q = Movie.objects.filter(find__title=info['title']) q = Item.objects.filter(find__title=info['title'])
if q.count() > 1: if q.count() > 1:
print "FIXME: check more than title here!!?" print "FIXME: check more than title here!!?"
movie = q[0] item = q[0]
else: else:
try: try:
movie = Movie.objects.get(movieId=info['oxdbId']) item = Item.objects.get(itemId=info['oxdbId'])
except Movie.DoesNotExist: except Item.DoesNotExist:
movie = Movie() item = Item()
movie.metadata = { item.metadata = {
'title': info['title'], 'title': info['title'],
'directors': info['directors'], 'directors': info['directors'],
'year': info.get('year', '') 'year': info.get('year', '')
} }
movie.movieId = info['oxdbId'] item.itemId = info['oxdbId']
for key in ('episode_title', 'series_title', 'season', 'episode'): for key in ('episode_title', 'series_title', 'season', 'episode'):
if key in info and info[key]: if key in info and info[key]:
movie.metadata[key] = info[key] item.metadata[key] = info[key]
movie.save() item.save()
return movie return item
class Movie(models.Model): class Item(models.Model):
person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character') person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character')
facet_keys = person_keys + ('country', 'language', 'genre', 'keyword') facet_keys = person_keys + ('country', 'language', 'genre', 'keyword')
@ -80,14 +80,14 @@ class Movie(models.Model):
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
published = models.DateTimeField(default=datetime.now, editable=False) published = models.DateTimeField(default=datetime.now, editable=False)
#only movies that have metadata from files are available, #only items that have metadata from files are available,
#this is indicated by setting available to True #this is indicated by setting available to True
available = models.BooleanField(default=False, db_index=True) available = models.BooleanField(default=False, db_index=True)
movieId = models.CharField(max_length=128, unique=True, blank=True) itemId = models.CharField(max_length=128, unique=True, blank=True)
oxdbId = models.CharField(max_length=42, unique=True, blank=True) oxdbId = models.CharField(max_length=42, unique=True, blank=True)
objects = managers.MovieManager() objects = managers.ItemManager()
def get(self, key, default=None): def get(self, key, default=None):
if self.metadata and key in self.metadata: if self.metadata and key in self.metadata:
@ -124,11 +124,11 @@ class Movie(models.Model):
json = fields.DictField(default={}, editable=False) json = fields.DictField(default={}, editable=False)
def updateImdb(self): def updateImdb(self):
if len(self.movieId) == 7: if len(self.itemId) == 7:
self.imdb = ox.web.imdb.Imdb(self.movieId) self.imdb = ox.web.imdb.Imdb(self.itemId)
self.save() self.save()
poster = models.ImageField(default=None, blank=True, upload_to=lambda m, x: os.path.join(movieid_path(m.movieId), "poster.jpg")) poster = models.ImageField(default=None, blank=True, upload_to=lambda m, x: os.path.join(itemid_path(m.itemId), "poster.jpg"))
poster_url = models.TextField(blank=True) poster_url = models.TextField(blank=True)
poster_height = models.IntegerField(default=0) poster_height = models.IntegerField(default=0)
poster_width = models.IntegerField(default=0) poster_width = models.IntegerField(default=0)
@ -145,7 +145,7 @@ class Movie(models.Model):
return self.get('title') return self.get('title')
def get_absolute_url(self): def get_absolute_url(self):
return '/timeline#%s' % self.movieId return '/timeline#%s' % self.itemId
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.json = self.get_json() self.json = self.get_json()
@ -158,7 +158,7 @@ class Movie(models.Model):
else: else:
self.poster_height = 128 self.poster_height = 128
self.poster_width = 80 self.poster_width = 80
super(Movie, self).save(*args, **kwargs) super(Item, self).save(*args, **kwargs)
self.updateFind() self.updateFind()
self.updateSort() self.updateSort()
self.updateFacets() self.updateFacets()
@ -169,27 +169,27 @@ class Movie(models.Model):
os.unlink(f) os.unlink(f)
for f in glob("%sstrip*"%self.timeline_prefix[:-8]): for f in glob("%sstrip*"%self.timeline_prefix[:-8]):
os.unlink(f) os.unlink(f)
super(Movie, self).delete(*args, **kwargs) super(Item, self).delete(*args, **kwargs)
def mergeWith(self, other): def mergeWith(self, other):
''' '''
move all related tables to other and delete self move all related tables to other and delete self
''' '''
for stream in self.streams.all(): for stream in self.streams.all():
stream.movie = other stream.item = other
stream.save() stream.save()
for l in self.lists.all(): for l in self.lists.all():
l.movies.remove(self) l.items.remove(self)
if l.movies.filter(id=other.id) == 0: if l.items.filter(id=other.id) == 0:
l.movies.add(other) l.items.add(other)
#FIXME: should this really happen for layers? #FIXME: should this really happen for layers?
for l in self.layer.all(): for l in self.layer.all():
l.movies.remove(self) l.items.remove(self)
if l.movies.filter(id=other.id) == 0: if l.items.filter(id=other.id) == 0:
l.movies.add(other) l.items.add(other)
if hasattr(self, 'files'): if hasattr(self, 'files'):
for f in self.files.all(): for f in self.files.all():
f.movie = other f.item = other
f.save() f.save()
self.delete() self.delete()
other.save() other.save()
@ -198,7 +198,7 @@ class Movie(models.Model):
JSON cache related functions JSON cache related functions
''' '''
_public_fields = { _public_fields = {
'movieId': 'id', 'itemId': 'id',
'title': 'title', 'title': 'title',
'year': 'year', 'year': 'year',
@ -230,7 +230,7 @@ class Movie(models.Model):
poster = {} poster = {}
poster['width'] = self.poster_width poster['width'] = self.poster_width
poster['height'] = self.poster_height poster['height'] = self.poster_height
poster['url'] = '/%s/poster.jpg' % self.movieId poster['url'] = '/%s/poster.jpg' % self.itemId
''' '''
if self.poster: if self.poster:
poster['url'] = self.poster.url poster['url'] = self.poster.url
@ -264,7 +264,7 @@ class Movie(models.Model):
if 'video' in s.info and s.info['video']: if 'video' in s.info and s.info['video']:
stream['aspectRatio'] = s.info['video'][0]['width'] / s.info['video'][0]['height'] stream['aspectRatio'] = s.info['video'][0]['width'] / s.info['video'][0]['height']
if settings.XSENDFILE or settings.XACCELREDIRECT: if settings.XSENDFILE or settings.XACCELREDIRECT:
stream['baseUrl'] = '/%s' % self.movieId stream['baseUrl'] = '/%s' % self.itemId
else: else:
stream['baseUrl'] = os.path.dirname(s.video.url) stream['baseUrl'] = os.path.dirname(s.video.url)
stream['profiles'] = list(set(map(lambda s: int(os.path.splitext(s['profile'])[0][:-1]), self.streams.all().values('profile')))) stream['profiles'] = list(set(map(lambda s: int(os.path.splitext(s['profile'])[0][:-1]), self.streams.all().values('profile'))))
@ -281,7 +281,7 @@ class Movie(models.Model):
return layers return layers
def get_json(self, fields=None): def get_json(self, fields=None):
movie = {} item = {}
for key in self._public_fields: for key in self._public_fields:
pub_key = self._public_fields.get(key, key) pub_key = self._public_fields.get(key, key)
if not fields or pub_key in fields: if not fields or pub_key in fields:
@ -290,18 +290,18 @@ class Movie(models.Model):
else: else:
value = self.get(key) value = self.get(key)
if callable(value): if callable(value):
movie[pub_key] = value() item[pub_key] = value()
else: else:
movie[pub_key] = value item[pub_key] = value
if not fields: if not fields:
movie['stream'] = self.get_stream() item['stream'] = self.get_stream()
movie['poster'] = self.get_poster() item['poster'] = self.get_poster()
movie['posters'] = self.get_posters() item['posters'] = self.get_posters()
if fields: if fields:
for f in fields: for f in fields:
if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'): if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'):
movie[f] = getattr(self.sort, f[:-7]) item[f] = getattr(self.sort, f[:-7])
return movie return item
def fields(self): def fields(self):
fields = {} fields = {}
@ -325,8 +325,8 @@ class Movie(models.Model):
def updateFind(self): def updateFind(self):
try: try:
f = self.find f = self.find
except MovieFind.DoesNotExist: except ItemFind.DoesNotExist:
f = MovieFind(movie=self) f = ItemFind(item=self)
f.title = '\n'.join([self.get('title'), self.get('original_title', '')]) f.title = '\n'.join([self.get('title'), self.get('original_title', '')])
#FIXME: filter us/int title #FIXME: filter us/int title
@ -349,7 +349,7 @@ class Movie(models.Model):
#FIXME: #FIXME:
#f.dialog = 'fixme' #f.dialog = 'fixme'
f.dialog = '\n'.join([l.value for l in Layer.objects.filter(type='subtitle', movie=self).order_by('start')]) f.dialog = '\n'.join([l.value for l in Layer.objects.filter(type='subtitle', item=self).order_by('start')])
#FIXME: collate filenames #FIXME: collate filenames
#f.filename = self.filename #f.filename = self.filename
@ -362,8 +362,8 @@ class Movie(models.Model):
def updateSort(self): def updateSort(self):
try: try:
s = self.sort s = self.sort
except MovieSort.DoesNotExist: except ItemSort.DoesNotExist:
s = MovieSort(movie=self) s = ItemSort(item=self)
def sortNames(values): def sortNames(values):
sort_value = '' sort_value = ''
@ -391,7 +391,7 @@ class Movie(models.Model):
for key in ('keywords', 'genres', 'cast', 'summary', 'trivia', 'connections'): for key in ('keywords', 'genres', 'cast', 'summary', 'trivia', 'connections'):
setattr(s, key, len(self.get(key, ''))) setattr(s, key, len(self.get(key, '')))
s.movieId = self.movieId.replace('0x', 'xx') s.itemId = self.itemId.replace('0x', 'xx')
s.rating = self.get('rating', -1) s.rating = self.get('rating', -1)
s.votes = self.get('votes', -1) s.votes = self.get('votes', -1)
@ -430,37 +430,37 @@ class Movie(models.Model):
current_values = [i[1] for i in self.get('actor', [])] current_values = [i[1] for i in self.get('actor', [])]
else: else:
current_values = self.get(utils.plural_key(key), []) current_values = self.get(utils.plural_key(key), [])
saved_values = [i.value for i in Facet.objects.filter(movie=self, key=key)] saved_values = [i.value for i in Facet.objects.filter(item=self, key=key)]
removed_values = filter(lambda x: x not in current_values, saved_values) removed_values = filter(lambda x: x not in current_values, saved_values)
if removed_values: if removed_values:
Facet.objects.filter(movie=self, key=key, value__in=removed_values).delete() Facet.objects.filter(item=self, key=key, value__in=removed_values).delete()
for value in current_values: for value in current_values:
if value not in saved_values: if value not in saved_values:
value_sort = value value_sort = value
if key in self.person_keys: if key in self.person_keys:
value_sort = getPersonSort(value) value_sort = getPersonSort(value)
f = Facet(key=key, value=value, value_sort=value_sort) f = Facet(key=key, value=value, value_sort=value_sort)
f.movie = self f.item = self
f.save() f.save()
year = self.get('year', None) year = self.get('year', None)
if year: if year:
f, created = Facet.objects.get_or_create(key='year', value=year, value_sort=year, movie=self) f, created = Facet.objects.get_or_create(key='year', value=year, value_sort=year, item=self)
else: else:
Facet.objects.filter(movie=self, key='year').delete() Facet.objects.filter(item=self, key='year').delete()
''' '''
Video related functions Video related functions
''' '''
def frame(self, position, width=128): def frame(self, position, width=128):
stream = self.streams.filter(profile=settings.VIDEO_PROFILE+'.webm')[0] stream = self.streams.filter(profile=settings.VIDEO_PROFILE+'.webm')[0]
path = os.path.join(settings.MEDIA_ROOT, movieid_path(self.movieId), 'frames', "%d"%width, "%s.jpg"%position) path = os.path.join(settings.MEDIA_ROOT, itemid_path(self.itemId), 'frames', "%d"%width, "%s.jpg"%position)
if not os.path.exists(path): if not os.path.exists(path):
extract.frame(stream.video.path, path, position, width) extract.frame(stream.video.path, path, position, width)
return path return path
@property @property
def timeline_prefix(self): def timeline_prefix(self):
return os.path.join(settings.MEDIA_ROOT, movieid_path(self.movieId), 'timeline') return os.path.join(settings.MEDIA_ROOT, itemid_path(self.itemId), 'timeline')
def updateStreams(self): def updateStreams(self):
files = {} files = {}
@ -469,7 +469,7 @@ class Movie(models.Model):
#FIXME: how to detect if something changed? #FIXME: how to detect if something changed?
if files: if files:
stream, created = Stream.objects.get_or_create(movie=self, profile='%s.webm' % settings.VIDEO_PROFILE) stream, created = Stream.objects.get_or_create(item=self, profile='%s.webm' % settings.VIDEO_PROFILE)
stream.video.name = stream_path(stream) stream.video.name = stream_path(stream)
cmd = [] cmd = []
@ -501,7 +501,7 @@ class Movie(models.Model):
def update_poster_urls(self): def update_poster_urls(self):
_current = {} _current = {}
for s in settings.POSTER_SERVICES: for s in settings.POSTER_SERVICES:
url = '%s?movieId=%s'%(s, self.movieId) url = '%s?itemId=%s'%(s, self.itemId)
try: try:
data = json.loads(ox.net.readUrlUnicode(url)) data = json.loads(ox.net.readUrlUnicode(url))
except: except:
@ -514,7 +514,7 @@ class Movie(models.Model):
#FIXME: remove urls that are no longer listed #FIXME: remove urls that are no longer listed
for service in _current: for service in _current:
for poster in _current[service]: for poster in _current[service]:
p, created = PosterUrl.objects.get_or_create(movie=self, url=poster['url'], service=service) p, created = PosterUrl.objects.get_or_create(item=self, url=poster['url'], service=service)
if created: if created:
p.width = poster['width'] p.width = poster['width']
p.height = poster['height'] p.height = poster['height']
@ -558,7 +558,7 @@ class Movie(models.Model):
posters = {} posters = {}
for f in self.files.filter(is_main=True, available=True): for f in self.files.filter(is_main=True, available=True):
for frame in f.frames.all(): for frame in f.frames.all():
path = os.path.join(movieid_path(self.movieId), 'poster.pandora.%s.%s.jpg'%(part, frame.position)) path = os.path.join(itemid_path(self.itemId), 'poster.pandora.%s.%s.jpg'%(part, frame.position))
path = os.path.abspath(os.path.join(settings.MEDIA_ROOT, path)) path = os.path.abspath(os.path.join(settings.MEDIA_ROOT, path))
posters[path] = frame.frame.path posters[path] = frame.frame.path
part += 1 part += 1
@ -574,18 +574,18 @@ class Movie(models.Model):
'-f', frame, '-f', frame,
'-p', poster '-p', poster
] ]
if len(self.movieId) == 7: if len(self.itemId) == 7:
cmd += ['-i', self.movieId] cmd += ['-i', self.itemId]
cmd += ['-o', self.oxdbId] cmd += ['-o', self.oxdbId]
p = subprocess.Popen(cmd) p = subprocess.Popen(cmd)
p.wait() p.wait()
return posters.keys() return posters.keys()
class MovieFind(models.Model): class ItemFind(models.Model):
""" """
used to search movies, all search values are in here used to search items, all search values are in here
""" """
movie = models.OneToOneField('Movie', related_name='find', primary_key=True) item = models.OneToOneField('Item', related_name='find', primary_key=True)
all = models.TextField(blank=True) all = models.TextField(blank=True)
title = models.TextField(blank=True) title = models.TextField(blank=True)
@ -612,7 +612,7 @@ class MovieFind(models.Model):
#only for own files or as admin? #only for own files or as admin?
filename = models.TextField(blank=True, default='') filename = models.TextField(blank=True, default='')
_private_fields = ('id', 'movie') _private_fields = ('id', 'item')
#return available find fields #return available find fields
#FIXME: should return mapping name -> verbose_name #FIXME: should return mapping name -> verbose_name
def fields(self): def fields(self):
@ -625,11 +625,11 @@ class MovieFind(models.Model):
return tuple(fields) return tuple(fields)
fields = classmethod(fields) fields = classmethod(fields)
class MovieSort(models.Model): class ItemSort(models.Model):
""" """
used to sort movies, all sort values are in here used to sort items, all sort values are in here
""" """
movie = models.OneToOneField('Movie', related_name='sort', primary_key=True) item = models.OneToOneField('Item', related_name='sort', primary_key=True)
title = models.CharField(max_length=1000, db_index=True) title = models.CharField(max_length=1000, db_index=True)
director = models.TextField(blank=True, db_index=True) director = models.TextField(blank=True, db_index=True)
@ -659,7 +659,7 @@ class MovieSort(models.Model):
wpm = models.IntegerField('Words per Minute', null=True, blank=True, db_index=True) wpm = models.IntegerField('Words per Minute', null=True, blank=True, db_index=True)
risk = models.IntegerField(null=True, blank=True, db_index=True) risk = models.IntegerField(null=True, blank=True, db_index=True)
movieId = models.CharField('ID', max_length=128, blank=True, db_index=True) itemId = models.CharField('ID', max_length=128, blank=True, db_index=True)
duration = models.FloatField(default=-1, db_index=True) duration = models.FloatField(default=-1, db_index=True)
resolution = models.IntegerField(blank=True, db_index=True) resolution = models.IntegerField(blank=True, db_index=True)
@ -683,7 +683,7 @@ class MovieSort(models.Model):
language_desc = models.TextField(blank=True, db_index=True) language_desc = models.TextField(blank=True, db_index=True)
_private_fields = ('id', 'movie') _private_fields = ('id', 'item')
#return available sort fields #return available sort fields
#FIXME: should return mapping name -> verbose_name #FIXME: should return mapping name -> verbose_name
def fields(self): def fields(self):
@ -697,7 +697,7 @@ class MovieSort(models.Model):
fields = classmethod(fields) fields = classmethod(fields)
class Facet(models.Model): class Facet(models.Model):
movie = models.ForeignKey('Movie', related_name='facets') item = models.ForeignKey('Item', related_name='facets')
key = models.CharField(max_length=200, db_index=True) key = models.CharField(max_length=200, db_index=True)
value = models.CharField(max_length=200) value = models.CharField(max_length=200)
value_sort = models.CharField(max_length=200) value_sort = models.CharField(max_length=200)
@ -749,7 +749,7 @@ class Person(models.Model):
class Location(models.Model): class Location(models.Model):
name = models.CharField(max_length=200, unique=True) name = models.CharField(max_length=200, unique=True)
manual = models.BooleanField(default=False) manual = models.BooleanField(default=False)
movies = models.ManyToManyField(Movie, related_name='locations_all') items = models.ManyToManyField(Item, related_name='locations_all')
#fixme: geo data #fixme: geo data
lat_sw = models.FloatField(default=0) lat_sw = models.FloatField(default=0)
@ -779,18 +779,18 @@ class List(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
name = models.CharField(max_length=255, unique=True) name = models.CharField(max_length=255, unique=True)
public = models.BooleanField(default=False) public = models.BooleanField(default=False)
movies = models.ManyToManyField(Movie, related_name='lists', through='ListItem') items = models.ManyToManyField(Item, related_name='lists', through='ListItem')
def add(self, movie): def add(self, item):
q = self.movies.filter(id=movie.id) q = self.items.filter(id=item.id)
if q.count() == 0: if q.count() == 0:
l = ListItem() l = ListItem()
l.list = self l.list = self
l.movie = movie l.item = item
l.save() l.save()
def remove(self, movie): def remove(self, item):
self.ListItem.objects.all().filter(movie=movie, list=self).delete() self.ListItem.objects.all().filter(item=item, list=self).delete()
def __unicode__(self): def __unicode__(self):
return u'%s (%s)' % (self.title, unicode(self.user)) return u'%s (%s)' % (self.title, unicode(self.user))
@ -805,17 +805,17 @@ class ListItem(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
list = models.ForeignKey(List) list = models.ForeignKey(List)
movie = models.ForeignKey(Movie) item = models.ForeignKey(Item)
def __unicode__(self): def __unicode__(self):
return u'%s in %s' % (unicode(self.movie), unicode(self.list)) return u'%s in %s' % (unicode(self.item), unicode(self.list))
class Layer(models.Model): class Layer(models.Model):
#FIXME: here having a movie,start index would be good #FIXME: here having a item,start index would be good
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User) user = models.ForeignKey(User)
movie = models.ForeignKey(Movie) item = models.ForeignKey(Item)
#seconds #seconds
start = models.FloatField(default=-1) start = models.FloatField(default=-1)
@ -841,22 +841,22 @@ class Collection(models.Model):
users = models.ManyToManyField(User, related_name='collections') users = models.ManyToManyField(User, related_name='collections')
name = models.CharField(blank=True, max_length=2048) name = models.CharField(blank=True, max_length=2048)
subdomain = models.CharField(unique=True, max_length=2048) subdomain = models.CharField(unique=True, max_length=2048)
movies = models.ForeignKey(Movie) items = models.ForeignKey(Item)
def editable(self, user): def editable(self, user):
return self.users.filter(id=user.id).count() > 0 return self.users.filter(id=user.id).count() > 0
def movieid_path(h): def itemid_path(h):
return os.path.join('movies', h[:2], h[2:4], h[4:6], h[6:]) return os.path.join('items', h[:2], h[2:4], h[4:6], h[6:])
def stream_path(stream): def stream_path(stream):
return os.path.join(movieid_path(stream.movie.movieId), stream.profile) return os.path.join(itemid_path(stream.item.itemId), stream.profile)
class Stream(models.Model): class Stream(models.Model):
class Meta: class Meta:
unique_together = ("movie", "profile") unique_together = ("item", "profile")
movie = models.ForeignKey(Movie, related_name='streams') item = models.ForeignKey(Item, related_name='streams')
profile = models.CharField(max_length=255, default='96p.webm') profile = models.CharField(max_length=255, default='96p.webm')
video = models.FileField(default=None, blank=True, upload_to=lambda f, x: stream_path(f)) video = models.FileField(default=None, blank=True, upload_to=lambda f, x: stream_path(f))
source = models.ForeignKey('Stream', related_name='derivatives', default=None, null=True) source = models.ForeignKey('Stream', related_name='derivatives', default=None, null=True)
@ -869,7 +869,7 @@ class Stream(models.Model):
def extract_derivatives(self): def extract_derivatives(self):
if settings.VIDEO_H264: if settings.VIDEO_H264:
profile = self.profile.replace('.webm', '.mp4') profile = self.profile.replace('.webm', '.mp4')
derivative, created = Stream.objects.get_or_create(profile=profile, movie=self.movie) derivative, created = Stream.objects.get_or_create(profile=profile, item=self.item)
if created: if created:
derivative.source = self derivative.source = self
derivative.video.name = self.video.name.replace(self.profile, profile) derivative.video.name = self.video.name.replace(self.profile, profile)
@ -879,7 +879,7 @@ class Stream(models.Model):
for p in settings.VIDEO_DERIVATIVES: for p in settings.VIDEO_DERIVATIVES:
profile = p + '.webm' profile = p + '.webm'
target = self.video.path.replace(self.profile, profile) target = self.video.path.replace(self.profile, profile)
derivative, created = Stream.objects.get_or_create(profile=profile, movie=self.movie) derivative, created = Stream.objects.get_or_create(profile=profile, item=self.item)
if created: if created:
derivative.source = self derivative.source = self
derivative.video.name = self.video.name.replace(self.profile, profile) derivative.video.name = self.video.name.replace(self.profile, profile)
@ -888,7 +888,7 @@ class Stream(models.Model):
if settings.VIDEO_H264: if settings.VIDEO_H264:
profile = p + '.mp4' profile = p + '.mp4'
derivative, created = Stream.objects.get_or_create(profile=profile, movie=self.movie) derivative, created = Stream.objects.get_or_create(profile=profile, item=self.item)
if created: if created:
derivative.source = self derivative.source = self
derivative.video.name = self.video.name.replace(self.profile, profile) derivative.video.name = self.video.name.replace(self.profile, profile)
@ -907,7 +907,7 @@ class Stream(models.Model):
self.save() self.save()
def __unicode__(self): def __unicode__(self):
return u"%s (%s)" % (self.profile, self.movie) return u"%s (%s)" % (self.profile, self.item)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.video and not self.info: if self.video and not self.info:
@ -916,15 +916,15 @@ class Stream(models.Model):
class PosterUrl(models.Model): class PosterUrl(models.Model):
class Meta: class Meta:
unique_together = ("movie", "service", "url") unique_together = ("item", "service", "url")
ordering = ('-height', ) ordering = ('-height', )
movie = models.ForeignKey(Movie, related_name='poster_urls') item = models.ForeignKey(Item, related_name='poster_urls')
url = models.CharField(max_length=1024) url = models.CharField(max_length=1024)
service = models.CharField(max_length=1024) service = models.CharField(max_length=1024)
width = models.IntegerField(default=80) width = models.IntegerField(default=80)
height = models.IntegerField(default=128) height = models.IntegerField(default=128)
def __unicode__(self): def __unicode__(self):
return u'%s %s %dx%d' % (unicode(self.movie), self.service, self.width, self.height) return u'%s %s %dx%d' % (unicode(self.item), self.service, self.width, self.height)

View file

@ -13,19 +13,19 @@ def cronjob(**kwargs):
print "do some cleanup stuff once a day" print "do some cleanup stuff once a day"
@task(ignore_resulsts=True, queue='default') @task(ignore_resulsts=True, queue='default')
def updatePoster(movieId): def updatePoster(itemId):
movie = models.Movie.objects.get(movieId=movieId) item = models.Item.objects.get(itemId=itemId)
movie.download_poster(True) item.download_poster(True)
@task(ignore_resulsts=True, queue='default') @task(ignore_resulsts=True, queue='default')
def updateImdb(imdbId): def updateImdb(imdbId):
movie = models.Movie.objects.get(movieId=imdbId) item = models.Item.objects.get(itemId=imdbId)
movie.updateImdb() item.updateImdb()
@task(ignore_resulsts=True) @task(ignore_resulsts=True)
def findMovie(fileId): def findItem(fileId):
f = models.File.objects.get(pk=fileId) f = models.File.objects.get(pk=fileId)
f.findMovie() f.findItem()
@task(ignore_resulsts=True, queue="encoding") @task(ignore_resulsts=True, queue="encoding")
def extractData(fileId): def extractData(fileId):
@ -37,11 +37,11 @@ def extractData(fileId):
f.extract() f.extract()
@task(ignore_resulsts=True, queue="encoding") @task(ignore_resulsts=True, queue="encoding")
def updateMovie(movidId): def updateItem(movidId):
''' '''
update movie update item
create proxy stream and other related files extracted from movieFiles create proxy stream and other related files extracted from itemFiles
''' '''
m = models.Movie.objects.get(pk=movieId) m = models.Item.objects.get(pk=itemId)
m.extract() m.extract()

View file

@ -57,7 +57,7 @@ def oxdb_directors(director):
def oxdb_title(_title, searchTitle = False): def oxdb_title(_title, searchTitle = False):
''' '''
normalize filename to get movie title normalize filename to get item title
''' '''
_title = os.path.basename(_title) _title = os.path.basename(_title)
_title = _title.replace('... ', '_dot_dot_dot_') _title = _title.replace('... ', '_dot_dot_dot_')

View file

@ -103,8 +103,8 @@ def _order_query(qs, sort, prefix='sort__'):
for e in sort: for e in sort:
operator = e['operator'] operator = e['operator']
if operator != '-': operator = '' if operator != '-': operator = ''
key = {'id': 'movieId'}.get(e['key'], e['key']) key = {'id': 'itemId'}.get(e['key'], e['key'])
#FIXME: this should be a property of models.MovieSort!!! #FIXME: this should be a property of models.ItemSort!!!
if operator=='-' and key in ('title', 'director', 'writer', 'producer', 'editor', 'cinematographer', 'language', 'country', 'year'): if operator=='-' and key in ('title', 'director', 'writer', 'producer', 'editor', 'cinematographer', 'language', 'country', 'year'):
key = '%s_desc' % key key = '%s_desc' % key
order = '%s%s%s' % (operator, prefix, key) order = '%s%s%s' % (operator, prefix, key)
@ -120,7 +120,7 @@ def _parse_query(data, user):
for key in ('sort', 'keys', 'group', 'list', 'range', 'ids'): for key in ('sort', 'keys', 'group', 'list', 'range', 'ids'):
if key in data: if key in data:
query[key] = data[key] query[key] = data[key]
query['qs'] = models.Movie.objects.find(data, user) query['qs'] = models.Item.objects.find(data, user)
#group by only allows sorting by name or number of itmes #group by only allows sorting by name or number of itmes
return query return query
@ -204,10 +204,10 @@ Positions
else: else:
query['sort'] = [{'key': 'name', 'operator':'+'}] query['sort'] = [{'key': 'name', 'operator':'+'}]
response['data']['items'] = [] response['data']['items'] = []
items = 'movies' items = 'items'
movie_qs = query['qs'] item_qs = query['qs']
qs = models.Facet.objects.filter(key=query['group']).filter(movie__id__in=movie_qs) qs = models.Facet.objects.filter(key=query['group']).filter(item__id__in=item_qs)
qs = qs.values('value').annotate(movies=Count('id')).order_by() qs = qs.values('value').annotate(items=Count('id')).order_by()
name = 'value' name = 'value'
name_sort = 'value_sort' name_sort = 'value_sort'
@ -234,7 +234,7 @@ Positions
qs = _order_query(query['qs'], query['sort']) qs = _order_query(query['qs'], query['sort'])
response['data']['positions'] = {} response['data']['positions'] = {}
ids = [j['movieId'] for j in qs.values('movieId')] ids = [j['itemId'] for j in qs.values('itemId')]
response['data']['positions'] = _get_positions(ids, query['ids']) response['data']['positions'] = _get_positions(ids, query['ids'])
elif 'keys' in query: elif 'keys' in query:
@ -251,8 +251,8 @@ Positions
qs = qs[query['range'][0]:query['range'][1]] qs = qs[query['range'][0]:query['range'][1]]
response['data']['items'] = [only_p(m['json']) for m in qs.values('json')] response['data']['items'] = [only_p(m['json']) for m in qs.values('json')]
else: # otherwise stats else: # otherwise stats
movies = query['qs'] items = query['qs']
files = File.objects.all().filter(movie__in=movies) files = File.objects.all().filter(item__in=items)
r = files.aggregate( r = files.aggregate(
Sum('duration'), Sum('duration'),
Sum('pixels'), Sum('pixels'),
@ -260,9 +260,9 @@ Positions
) )
response['data']['duration'] = r['duration__sum'] response['data']['duration'] = r['duration__sum']
response['data']['files'] = files.count() response['data']['files'] = files.count()
response['data']['items'] = movies.count() response['data']['items'] = items.count()
response['data']['pixels'] = r['pixels__sum'] response['data']['pixels'] = r['pixels__sum']
response['data']['runtime'] = movies.aggregate(Sum('sort__runtime'))['sort__runtime__sum'] response['data']['runtime'] = items.aggregate(Sum('sort__runtime'))['sort__runtime__sum']
if response['data']['runtime'] == None: if response['data']['runtime'] == None:
response['data']['runtime'] = 1337 response['data']['runtime'] = 1337
response['data']['size'] = r['size__sum'] response['data']['size'] = r['size__sum']
@ -277,7 +277,7 @@ def api_getItem(request):
''' '''
response = json_response({}) response = json_response({})
itemId = json.loads(request.POST['data']) itemId = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=itemId) item = get_object_or_404_json(models.Item, itemId=itemId)
#FIXME: check permissions #FIXME: check permissions
info = item.get_json() info = item.get_json()
info['stream'] = item.get_stream() info['stream'] = item.get_stream()
@ -294,7 +294,7 @@ def api_editItem(request):
'data': {}} 'data': {}}
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=data['id']) item = get_object_or_404_json(models.Item, itemId=data['id'])
if item.editable(request.user): if item.editable(request.user):
response = json_response(status=501, text='not implemented') response = json_response(status=501, text='not implemented')
item.edit(data) item.edit(data)
@ -312,7 +312,7 @@ def api_removeItem(request):
''' '''
response = json_response({}) response = json_response({})
itemId = json.loads(request.POST['data']) itemId = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=itemId) item = get_object_or_404_json(models.Item, itemId=itemId)
if item.editable(request.user): if item.editable(request.user):
response = json_response(status=501, text='not implemented') response = json_response(status=501, text='not implemented')
else: else:
@ -436,12 +436,12 @@ def api_parse(request): #parse path and return info
def api_setPosterFrame(request): #parse path and return info def api_setPosterFrame(request): #parse path and return info
''' '''
param data param data
{id: movieId, position: float} {id: itemId, position: float}
return {'status': {'code': int, 'text': string}, return {'status': {'code': int, 'text': string},
data: {}} data: {}}
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=data['id']) item = get_object_or_404_json(models.Item, itemId=data['id'])
if item.editable(request.user): if item.editable(request.user):
#FIXME: some things need to be updated after changing this #FIXME: some things need to be updated after changing this
item.poster_frame = data['position'] item.poster_frame = data['position']
@ -454,12 +454,12 @@ def api_setPosterFrame(request): #parse path and return info
def api_setPoster(request): #parse path and return info def api_setPoster(request): #parse path and return info
''' '''
param data param data
{id: movieId, url: string} {id: itemId, url: string}
return {'status': {'code': int, 'text': string}, return {'status': {'code': int, 'text': string},
data: {poster: {url,width,height}}} data: {poster: {url,width,height}}}
''' '''
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
item = get_object_or_404_json(models.Movie, movieId=data['id']) item = get_object_or_404_json(models.Item, itemId=data['id'])
if item.editable(request.user): if item.editable(request.user):
valid_urls = [p.url for p in item.poster_urls.all()] valid_urls = [p.url for p in item.poster_urls.all()]
if data['url'] in valid_urls: if data['url'] in valid_urls:
@ -467,7 +467,7 @@ def api_setPoster(request): #parse path and return info
if item.poster: if item.poster:
item.poster.delete() item.poster.delete()
item.save() item.save()
tasks.updatePoster.delay(item.movieId) tasks.updatePoster.delay(item.itemId)
response = json_response(status=200, text='ok') response = json_response(status=200, text='ok')
response['data']['poster'] = item.get_poster() response['data']['poster'] = item.get_poster()
else: else:
@ -535,45 +535,45 @@ def apidoc(request):
media delivery media delivery
''' '''
def frame(request, id, position, size): def frame(request, id, position, size):
movie = get_object_or_404(models.Movie, movieId=id) item = get_object_or_404(models.Item, itemId=id)
position = float(position.replace(',', '.')) position = float(position.replace(',', '.'))
frame = movie.frame(position, int(size)) frame = item.frame(position, int(size))
if not frame: if not frame:
raise Http404 raise Http404
return HttpFileResponse(frame, content_type='image/jpeg') return HttpFileResponse(frame, content_type='image/jpeg')
def poster(request, id, size=None): def poster(request, id, size=None):
movie = get_object_or_404(models.Movie, movieId=id) item = get_object_or_404(models.Item, itemId=id)
if size == 'large': if size == 'large':
size = None size = None
if movie.poster: if item.poster:
if size: if size:
size = int(size) size = int(size)
poster_path = movie.poster.path.replace('.jpg', '.%d.jpg'%size) poster_path = item.poster.path.replace('.jpg', '.%d.jpg'%size)
if not os.path.exists(poster_path): if not os.path.exists(poster_path):
poster_size = max(movie.poster.width, movie.poster.height) poster_size = max(item.poster.width, item.poster.height)
if size > poster_size: if size > poster_size:
return redirect('/%s/poster.jpg' % movie.movieId) return redirect('/%s/poster.jpg' % item.itemId)
extract.resize_image(movie.poster.path, poster_path, size=size) extract.resize_image(item.poster.path, poster_path, size=size)
else: else:
poster_path = movie.poster.path poster_path = item.poster.path
else: else:
if not size: size='large' if not size: size='large'
return redirect('http://0xdb.org/%s/poster.%s.jpg' % (movie.movieId, size)) return redirect('http://0xdb.org/%s/poster.%s.jpg' % (item.itemId, size))
poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png') poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png')
return HttpFileResponse(poster_path, content_type='image/jpeg') return HttpFileResponse(poster_path, content_type='image/jpeg')
def timeline(request, id, timeline, size, position): def timeline(request, id, timeline, size, position):
movie = get_object_or_404(models.Movie, movieId=id) item = get_object_or_404(models.Item, itemId=id)
if timeline == 'strip': if timeline == 'strip':
timeline = '%s.%s.%04d.png' %(movie.timeline_prefix[:-8] + 'strip', size, int(position)) timeline = '%s.%s.%04d.png' %(item.timeline_prefix[:-8] + 'strip', size, int(position))
else: else:
timeline = '%s.%s.%04d.png' %(movie.timeline_prefix, size, int(position)) timeline = '%s.%s.%04d.png' %(item.timeline_prefix, size, int(position))
return HttpFileResponse(timeline, content_type='image/png') return HttpFileResponse(timeline, content_type='image/png')
def video(request, id, profile): def video(request, id, profile):
movie = get_object_or_404(models.Movie, movieId=id) item = get_object_or_404(models.Item, itemId=id)
stream = get_object_or_404(movie.streams, profile=profile) stream = get_object_or_404(item.streams, profile=profile)
path = stream.video.path path = stream.video.path
content_type = path.endswith('.mp4') and 'video/mp4' or 'video/webm' content_type = path.endswith('.mp4') and 'video/mp4' or 'video/webm'
return HttpFileResponse(path, content_type=content_type) return HttpFileResponse(path, content_type=content_type)