cablegates/pandora/backend/models.py

647 lines
23 KiB
Python
Raw Normal View History

2009-06-08 16:08:59 +00:00
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
2010-02-03 12:05:38 +00:00
from datetime import datetime
2009-06-08 16:08:59 +00:00
import os.path
import random
2010-02-03 12:05:38 +00:00
import re
2009-06-08 16:08:59 +00:00
from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User
2009-12-31 15:04:32 +00:00
from django.core.files.base import ContentFile
from django.utils import simplejson as json
from django.conf import settings
2010-02-03 12:05:38 +00:00
from oxdjango import fields
2010-07-07 22:46:41 +00:00
import ox
from ox import stripTags
from ox.normalize import canonicalTitle, canonicalName
2010-02-06 08:28:35 +00:00
from firefogg import Firefogg
2009-06-08 16:08:59 +00:00
2009-08-01 14:14:54 +00:00
import managers
2010-01-16 20:42:11 +00:00
import load
2010-02-03 12:05:38 +00:00
import utils
2010-02-16 10:13:44 +00:00
import extract
2009-06-08 16:08:59 +00:00
2010-07-14 14:35:10 +00:00
def plural_key(term):
return {
'country': 'countries',
}.get(term, term + 's')
2010-01-16 20:42:11 +00:00
def getMovie(info):
'''
info dict with:
imdbId, title, director, episode_title, season, series
'''
2010-01-22 23:57:06 +00:00
if 'imdbId' in info and info['imdbId']:
2010-01-16 20:42:11 +00:00
try:
movie = Movie.objects.get(movieId=info['imdbId'])
2010-01-22 23:57:06 +00:00
except Movie.DoesNotExist:
movie = Movie(movieId=info['imdbId'])
if 'title' in info and 'directors' in info:
movie.imdb = {
'title': info['title'],
'directors': info['directors'],
'year': info.get('year', '')
}
#FIXME: this should be done async
#movie.save()
#tasks.updateImdb.delay(movie.movieId)
movie.updateImdb()
2010-01-16 20:42:11 +00:00
else:
q = Movie.objects.filter(find__title=info['title'])
2010-01-16 20:42:11 +00:00
if q.count() > 1:
print "FIXME: check more than title here!!?"
2010-01-16 20:42:11 +00:00
movie = q[0]
else:
try:
movie = Movie.objects.get(movieId=info['oxdbId'])
except Movie.DoesNotExist:
movie = Movie()
movie.metadata = {
'title': info['title'],
'directors': info['directors'],
'year': info.get('year', '')
}
movie.movieId = info['oxdbId']
for key in ('episode_title', 'series_title', 'season', 'episode'):
if key in info:
movie.metadata[key] = info[key]
2010-01-16 21:04:38 +00:00
movie.save()
2010-01-16 20:42:11 +00:00
return movie
2009-12-31 15:04:32 +00:00
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)
2010-07-05 12:07:59 +00:00
def poster_path(f):
name = "%s.%s" % (f.movieId, 'jpg')
url_hash = f.movieId
return os.path.join('poster', url_hash[:2], url_hash[2:4], url_hash[4:6], name)
class Movie(models.Model):
2010-07-16 10:13:16 +00:00
person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character')
2010-07-15 15:55:10 +00:00
facet_keys = person_keys + ('country', 'language', 'genre', 'keyword')
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
2010-01-16 20:42:11 +00:00
published = models.DateTimeField(default=datetime.now, editable=False)
2009-06-08 16:08:59 +00:00
#only movies that have metadata from files are available,
#this is indicated by setting available to True
2009-12-31 15:04:32 +00:00
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)
2009-08-01 14:14:54 +00:00
objects = managers.MovieManager()
def get(self, key, default=None):
if self.metadata and key in self.metadata:
return self.metadata[key]
if self.imdb and key in self.imdb:
return self.imdb[key]
return default
def editable(self, user):
#FIXME: make permissions work
return False
def edit(self, data):
#FIXME: how to map the keys to the right place to write them to?
for key in data:
if key != 'id':
setattr(self.metadata, key, data[key])
self.oxdb.save()
self.save()
def reviews(self):
reviews = self.get('reviews', [])
whitelist = [w for w in ReviewWhitelist.objects.all()]
_reviews = {}
for r in reviews:
for w in whitelist:
if w.url in r[0]:
_reviews[w.title] = r[0]
return _reviews
imdb = fields.DictField(default={}, editable=False)
metadata = fields.DictField(default={}, editable=False)
2009-12-31 15:04:32 +00:00
json = fields.DictField(default={}, editable=False)
def updateImdb(self):
if len(self.movieId) == 7:
self.imdb = ox.web.imdb.Imdb(self.movieId)
self.save()
2009-08-16 12:23:29 +00:00
#FIXME: use data.0xdb.org
2009-12-31 15:04:32 +00:00
'''
2009-06-08 16:08:59 +00:00
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)
2009-12-31 15:04:32 +00:00
#FIXME: use data.0xdb.org/posters for that
2009-06-08 16:08:59 +00:00
#what of this is still required?
still_pos = models.IntegerField(null=True, blank=True)
poster = models.TextField(blank=True)
posters_disabled = models.TextField(blank=True)
posters_available = models.TextField(blank=True)
2010-07-05 12:07:59 +00:00
poster = models.ImageField(default=None, blank=True, upload_to=poster_path)
2009-12-31 15:04:32 +00:00
'''
2010-07-05 08:30:17 +00:00
poster_height = models.IntegerField(default=0)
poster_width = models.IntegerField(default=0)
2009-06-08 16:08:59 +00:00
2009-12-31 15:04:32 +00:00
#stream related fields
'''
'''
2010-02-08 10:26:25 +00:00
stream_low = models.FileField(default=None, blank=True, upload_to=lambda f, x: movie_path(f, 'low'))
stream_mid = models.FileField(default=None, blank=True, upload_to=lambda f, x: movie_path(f, 'mid'))
stream_high = models.FileField(default=None, blank=True, upload_to=lambda f, x: movie_path(f, 'high'))
2009-12-31 15:04:32 +00:00
#FIXME: is this still required? should this not be aspect ratio? depends on stream???
2009-06-08 16:08:59 +00:00
scene_height = models.IntegerField(null=True, blank=True)
def __unicode__(self):
return u'%s (%s)' % (self.get('title'), self.get('year'))
2009-06-08 16:08:59 +00:00
def save(self, *args, **kwargs):
self.json = self.get_json()
if not self.oxdbId:
self.oxdbId = self.oxid()
2010-07-05 12:07:59 +00:00
2009-06-08 16:08:59 +00:00
super(Movie, self).save(*args, **kwargs)
2009-08-16 12:23:29 +00:00
self.updateFind()
self.updateSort()
self.updateFacets()
2009-06-08 16:08:59 +00:00
_public_fields = {
'movieId': 'id',
'title': 'title',
'year': 'year',
'runtime': 'runtime',
'release_date': 'release_date',
'countries': 'country',
'directors': 'director',
'languages': 'language',
'genres': 'genre',
'keywords': 'keyword',
2009-06-08 16:08:59 +00:00
'cast': 'cast',
'series_title': 'series_title',
'episode_title': 'episode_title',
'season': 'season',
'episode': 'episode',
'reviews': 'reviews',
2009-08-01 14:14:54 +00:00
'trivia': 'trivia',
'rating': 'rating',
'votes': 'votes',
2009-08-16 12:23:29 +00:00
'alternative_titles': 'alternative_titles',
2010-07-05 08:30:17 +00:00
'connections_json': 'connections',
2010-07-05 08:38:53 +00:00
'poster_width': 'posterWidth',
'poster_height': 'posterHeight'
2009-06-08 16:08:59 +00:00
}
2009-12-31 15:04:32 +00:00
def get_json(self, fields=None):
2009-06-08 16:08:59 +00:00
movie = {}
for key in self._public_fields:
pub_key = self._public_fields.get(key, key)
if not fields or pub_key in fields:
if hasattr(self, key):
value = getattr(self, key)
else:
value = self.get(key)
if callable(value):
movie[pub_key] = value()
2009-06-08 16:08:59 +00:00
else:
movie[pub_key] = value
if fields:
for f in fields:
if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'):
2010-07-05 12:07:59 +00:00
movie[f] = getattr(self.sort, f[:-7])
2009-06-08 16:08:59 +00:00
return movie
2009-08-16 12:23:29 +00:00
def fields(self):
fields = {}
for f in self._meta.fields:
if f.name in self._public_fields:
fields[f.name] = {}
fields[f.name]['order'] = 'desc'
fields[f.name]['type'] = type(f)
return fields
fields = classmethod(fields)
2009-06-08 16:08:59 +00:00
def oxid(self):
return utils.oxid(self.get('title', ''), self.get('directors', []), str(self.get('year', '')),
self.get('series title', ''), self.get('episode title', ''),
self.get('season', ''), self.get('episode', ''))
2009-08-16 12:23:29 +00:00
def frame(self, position, width=128):
#FIXME: compute offset and so on
f = self.files.all()[0]
return f.frame(position, width)
2009-08-16 12:23:29 +00:00
def updateFind(self):
try:
f = self.find
except MovieFind.DoesNotExist:
f = MovieFind(movie=self)
2010-07-14 14:35:10 +00:00
f.title = '\n'.join([self.get('title'), self.get('original_title', '')])
2010-02-22 09:25:29 +00:00
#FIXME: filter us/int title
#f.title += ' '.join([t.title for t in self.alternative_titles()])
2010-07-14 14:35:10 +00:00
f.year = self.get('year', '')
2010-07-14 14:35:10 +00:00
2010-07-15 15:55:10 +00:00
for key in self.facet_keys:
2010-07-16 10:13:16 +00:00
if key == 'actor':
values = [i[0] for i in self.get('actor', [])]
elif key == 'character':
values = [i[1] for i in self.get('actor', [])]
else:
values = self.get(plural_key(key), [])
setattr(f, key, '|%s|'%'|'.join(values))
f.summary = self.get('plot', '') + self.get('plot_outline', '')
f.trivia = ' '.join(self.get('trivia', []))
f.location = '|%s|'%'|'.join(self.get('filming_locations', []))
2010-07-13 22:20:14 +00:00
#FIXME:
#f.dialog = 'fixme'
f.dialog = '\n'.join([l.value for l in Layer.objects.filter(type='subtitle', movie=self).order_by('start')])
#FIXME: collate filenames
#f.filename = self.filename
f.all = ' '.join(filter(None, [f.title, f.director, f.country, str(f.year), f.language,
2009-08-16 12:23:29 +00:00
f.writer, f.producer, f.editor, f.cinematographer,
f.actor, f.character, f.genre, f.keyword, f.summary, f.trivia,
f.location, f.filename]))
2009-08-16 12:23:29 +00:00
f.save()
def updateSort(self):
try:
s = self.sort
except MovieSort.DoesNotExist:
s = MovieSort(movie=self)
2009-08-16 12:23:29 +00:00
def sortNames(values):
sort_value = ''
if values:
sort_value = '; '.join([getPersonSort(name) for name in values])
2009-08-16 12:23:29 +00:00
if not sort_value:
sort_value = ''
2009-08-16 12:23:29 +00:00
return sort_value
#title
title = canonicalTitle(self.get('title'))
2009-08-16 12:23:29 +00:00
title = re.sub(u'[\'!¿¡,\.;\-"\:\*\[\]]', '', title)
title = title.replace(u'Æ', 'Ae')
#pad numbered titles
numbers = re.compile('^(\d+)').findall(title)
if numbers:
padded = '%010d' % int(numbers[0])
title = re.sub('^(\d+)', padded, title)
s.title = title.strip()
s.country = ','.join(self.get('countries', []))
s.year = self.get('year', '')
2009-08-16 12:23:29 +00:00
2010-07-15 15:55:10 +00:00
for key in self.person_keys:
2010-07-14 14:35:10 +00:00
setattr(s, key, sortNames(self.get(plural_key(key), [])))
for key in ('language', 'country'):
setattr(s, key, ','.join(self.get(plural_key(key), [])))
s.runtime = self.get('runtime', 0)
2009-08-16 12:23:29 +00:00
2010-07-16 10:13:16 +00:00
for key in ('keywords', 'genres', 'cast', 'summary', 'trivia', 'connections'):
setattr(s, key, len(self.get(key, '')))
2010-07-13 22:20:14 +00:00
s.movieId = self.movieId.replace('0x', 'xx')
s.rating = self.get('rating', -1)
s.votes = self.get('votes', -1)
2009-08-16 12:23:29 +00:00
# data from related subtitles
s.scenes = 0 #FIXME
2010-07-13 22:20:14 +00:00
s.dialog = 0 #FIXME
2009-08-16 12:23:29 +00:00
s.words = 0 #FIXME
s.wpm = 0 #FIXME
s.risk = 0 #FIXME
# data from related files
s.duration = 0 #FIXME
s.resolution = 0 #FIXME
s.aspectratio = 0 #FIXME
s.bitrate = 0 #FIXME
s.pixels = 0 #FIXME
s.filename = 0 #FIXME
s.files = 0 #FIXME
s.size = 0 #FIXME
2010-07-15 15:55:10 +00:00
for key in ('title', 'language', 'country') + self.person_keys:
setattr(s, '%s_desc'%key, getattr(s, key))
if not getattr(s, key):
setattr(s, key, u'zzzzzzzzzzzzzzzzzzzzzzzzz')
if not s.year:
s.year_desc = '';
s.year = '9999';
2010-07-13 22:20:14 +00:00
#FIXME: also deal with number based rows like genre, keywords etc
2009-08-16 12:23:29 +00:00
s.save()
2009-06-08 16:08:59 +00:00
def updateFacets(self):
#FIXME: what to do with Unkown Director, Year, Country etc.
2010-07-15 15:55:10 +00:00
for key in self.facet_keys:
2010-07-16 10:13:16 +00:00
if key == 'actor':
current_values = [i[0] for i in self.get('actor', [])]
elif key == 'character':
current_values = [i[1] for i in self.get('actor', [])]
else:
current_values = self.get(plural_key(key), [])
saved_values = [i.value for i in Facet.objects.filter(movie=self, key=key)]
removed_values = filter(lambda x: x not in current_values, saved_values)
if removed_values:
Facet.objects.filter(movie=self, key=key, value__in=removed_values).delete()
for value in current_values:
if value not in saved_values:
value_sort = value
2010-07-15 15:55:10 +00:00
if key in self.person_keys:
value_sort = getPersonSort(value)
f = Facet(key=key, value=value, value_sort=value_sort)
f.movie = self
f.save()
2010-07-13 22:20:14 +00:00
year = self.get('year', None)
if year:
f, created = Facet.objects.get_or_create(key='year', value=year, value_sort=year, movie=self)
else:
Facet.objects.filter(movie=self, key='year').delete()
2009-06-08 16:08:59 +00:00
class MovieFind(models.Model):
2009-08-16 12:23:29 +00:00
"""
used to search movies, all search values are in here
"""
movie = models.OneToOneField('Movie', related_name='find', primary_key=True)
2009-06-08 16:08:59 +00:00
2009-08-16 12:23:29 +00:00
all = models.TextField(blank=True)
2009-12-31 15:04:32 +00:00
title = models.TextField(blank=True)
director = models.TextField(blank=True, default='')
country = models.TextField(blank=True, default='')
2009-06-08 16:08:59 +00:00
year = models.CharField(max_length=4)
language = models.TextField(blank=True, default='')
writer = models.TextField(blank=True, default='')
producer = models.TextField(blank=True, default='')
editor = models.TextField(blank=True, default='')
cinematographer = models.TextField(blank=True, default='')
actor = models.TextField(blank=True, default='')
character = models.TextField(blank=True, default='')
2010-07-13 22:20:14 +00:00
dialog = models.TextField(blank=True, default='')
2009-06-08 16:08:59 +00:00
#person
genre = models.TextField(blank=True)
keyword = models.TextField(blank=True)
2009-06-08 16:08:59 +00:00
summary = models.TextField(blank=True)
trivia = models.TextField(blank=True)
location = models.TextField(blank=True, default='')
2009-06-08 16:08:59 +00:00
#only for own files or as admin?
filename = models.TextField(blank=True, default='')
2009-06-08 16:08:59 +00:00
_private_fields = ('id', 'movie')
2009-12-31 15:04:32 +00:00
#return available find fields
#FIXME: should return mapping name -> verbose_name
def fields(self):
fields = []
2009-06-08 16:08:59 +00:00
for f in self._meta.fields:
if f.name not in self._private_fields:
2009-12-31 15:04:32 +00:00
name = f.verbose_name
name = name[0].capitalize() + name[1:]
fields.append(name)
return tuple(fields)
fields = classmethod(fields)
2009-06-08 16:08:59 +00:00
class MovieSort(models.Model):
2009-08-16 12:23:29 +00:00
"""
used to sort movies, all sort values are in here
"""
movie = models.OneToOneField('Movie', related_name='sort', primary_key=True)
2009-06-08 16:08:59 +00:00
2010-04-20 10:10:39 +00:00
title = models.CharField(max_length=1000, db_index=True)
director = models.TextField(blank=True, db_index=True)
country = models.TextField(blank=True, db_index=True)
year = models.CharField(max_length=4, db_index=True)
producer = models.TextField(blank=True, db_index=True)
writer = models.TextField(blank=True, db_index=True)
editor = models.TextField(blank=True, db_index=True)
cinematographer = models.TextField(blank=True, db_index=True)
language = models.TextField(blank=True, db_index=True)
runtime = models.IntegerField(blank=True, null=True, db_index=True)
keywords = models.IntegerField(blank=True, db_index=True)
genre = models.TextField(blank=True, db_index=True)
cast = models.IntegerField(blank=True, db_index=True)
summary = models.IntegerField(blank=True, db_index=True)
trivia = models.IntegerField(blank=True, db_index=True)
connections = models.IntegerField(blank=True, db_index=True)
rating = models.FloatField(blank=True, db_index=True)
votes = models.IntegerField(blank=True, db_index=True)
scenes = models.IntegerField(blank=True, db_index=True)
2010-07-13 22:20:14 +00:00
dialog = models.IntegerField(null=True, blank=True, db_index=True)
2010-04-20 10:10:39 +00:00
words = models.IntegerField(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)
movieId = models.CharField('ID', max_length=128, blank=True, db_index=True)
duration = models.FloatField(default=-1, db_index=True)
resolution = models.IntegerField(blank=True, db_index=True)
aspectratio = models.IntegerField('Aspect Ratio', blank=True, db_index=True)
bitrate = models.IntegerField(blank=True, db_index=True)
pixels = models.BigIntegerField(blank=True, db_index=True)
filename = models.IntegerField(blank=True, db_index=True)
files = models.IntegerField(blank=True, db_index=True)
size = models.BigIntegerField(blank=True, db_index=True)
2009-06-08 16:08:59 +00:00
#required to move empty values to the bottom for both asc and desc sort
title_desc = models.CharField(max_length=1000, db_index=True)
director_desc = models.TextField(blank=True, db_index=True)
country_desc = models.TextField(blank=True, db_index=True)
year_desc = models.CharField(max_length=4, db_index=True)
producer_desc = models.TextField(blank=True, db_index=True)
writer_desc = models.TextField(blank=True, db_index=True)
editor_desc = models.TextField(blank=True, db_index=True)
cinematographer_desc = models.TextField(blank=True, db_index=True)
language_desc = models.TextField(blank=True, db_index=True)
2009-06-08 16:08:59 +00:00
_private_fields = ('id', 'movie')
2009-12-31 15:04:32 +00:00
#return available sort fields
#FIXME: should return mapping name -> verbose_name
def fields(self):
fields = []
2009-06-08 16:08:59 +00:00
for f in self._meta.fields:
if f.name not in self._private_fields:
2009-12-31 15:04:32 +00:00
name = f.verbose_name
name = name[0].capitalize() + name[1:]
fields.append(name)
return tuple(fields)
fields = classmethod(fields)
2009-06-08 16:08:59 +00:00
class Facet(models.Model):
movie = models.ForeignKey('Movie', related_name='facets')
key = models.CharField(max_length=200, db_index=True)
value = models.CharField(max_length=200)
value_sort = models.CharField(max_length=200)
2009-06-08 16:08:59 +00:00
def save(self, *args, **kwargs):
if not self.value_sort:
self.value_sort = self.value
super(Facet, self).save(*args, **kwargs)
2009-08-16 12:23:29 +00:00
def getPersonSort(name):
person, created = Person.objects.get_or_create(name=name)
name_sort = person.name_sort.replace(u'\xc5k', 'A')
return name_sort
2009-06-08 16:08:59 +00:00
class Person(models.Model):
name = models.CharField(max_length=200)
imdbId = models.CharField(max_length=7, blank=True)
name_sort = models.CharField(max_length=200)
class Meta:
ordering = ('name_sort', )
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
if not self.name_sort:
2010-07-07 22:46:41 +00:00
self.name_sort = ox.normalize.canonicalName(self.name)
2009-06-08 16:08:59 +00:00
super(Person, self).save(*args, **kwargs)
def get_or_create(model, name, imdbId=None):
if imdbId:
q = model.objects.filter(name=name, imdbId=imdbId)
else:
2009-08-01 14:14:54 +00:00
q = model.objects.all().filter(name=name)
2009-06-08 16:08:59 +00:00
if q.count() > 0:
o = q[0]
else:
o = model.objects.create(name=name)
if imdbId:
o.imdbId = imdbId
o.save()
return o
get_or_create = classmethod(get_or_create)
def json(self):
return self.name
class Location(models.Model):
2009-08-01 14:14:54 +00:00
name = models.CharField(max_length=200, unique=True)
manual = models.BooleanField(default=False)
movies = models.ManyToManyField(Movie, related_name='locations_all')
2009-06-08 16:08:59 +00:00
#fixme: geo data
2009-08-16 12:23:29 +00:00
lat_sw = models.FloatField(default=0)
lng_sw = models.FloatField(default=0)
lat_ne = models.FloatField(default=0)
lng_ne = models.FloatField(default=0)
lat_center = models.FloatField(default=0)
lng_center = models.FloatField(default=0)
area = models.FloatField(default=-1)
2009-06-08 16:08:59 +00:00
class Meta:
ordering = ('name', )
def __unicode__(self):
return self.name
def json(self):
return self.name
class ReviewWhitelist(models.Model):
name = models.CharField(max_length=255, unique=True)
url = models.CharField(max_length=255, unique=True)
class List(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User)
name = models.CharField(max_length=255, unique=True)
public = models.BooleanField(default=False)
movies = models.ManyToManyField(Movie, related_name='lists', through='ListItem')
def add(self, movie):
q = self.movies.filter(id=movie.id)
if q.count() == 0:
l = ListItem()
l.list = self
l.movie = movie
l.save()
def remove(self, movie):
self.ListItem.objects.all().filter(movie=movie, list=self).delete()
def __unicode__(self):
return u'%s (%s)' % (self.title, unicode(self.user))
def editable(self, user):
#FIXME: make permissions work
2010-02-06 08:24:39 +00:00
if self.user == user or user.has_perm('Ox.admin'):
return True
return False
class ListItem(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
list = models.ForeignKey(List)
movie = models.ForeignKey(Movie)
def __unicode__(self):
return u'%s in %s' % (unicode(self.movie), unicode(self.list))
class Layer(models.Model):
2010-07-13 22:20:14 +00:00
#FIXME: here having a movie,start index would be good
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User)
movie = models.ForeignKey(Movie)
#seconds
2010-07-13 22:20:14 +00:00
start = models.FloatField(default=-1)
stop = models.FloatField(default=-1)
type = models.CharField(blank=True, max_length=255)
value = models.TextField()
#FIXME: relational layers, Locations, clips etc
#location = models.ForeignKey('Location', default=None)
def editable(self, user):
2010-02-06 08:24:39 +00:00
if user.is_authenticated():
if obj.user == user.id or user.has_perm('0x.admin'):
return True
if user.groups.filter(id__in=obj.groups.all()).count() > 0:
return True
return False
2009-08-01 14:14:54 +00:00
2010-02-03 11:59:11 +00:00
class Collection(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
2010-02-06 08:24:39 +00:00
users = models.ManyToManyField(User, related_name='collections')
2010-02-03 11:59:11 +00:00
name = models.CharField(blank=True, max_length=2048)
subdomain = models.CharField(unique=True, max_length=2048)
movies = models.ForeignKey(Movie)
2010-02-06 08:24:39 +00:00
def editable(self, user):
return self.users.filter(id=user.id).count() > 0