itemKey, use SITE_CONFIG to define json config
This commit is contained in:
parent
19cbce7c92
commit
8142335a8c
7 changed files with 427 additions and 82 deletions
|
@ -31,6 +31,333 @@
|
||||||
{"id": "actor", "title": "Actor"},
|
{"id": "actor", "title": "Actor"},
|
||||||
{"id": "keyword", "title": "Keyword"}
|
{"id": "keyword", "title": "Keyword"}
|
||||||
],
|
],
|
||||||
|
"itemKeys": [
|
||||||
|
{
|
||||||
|
"id": "title",
|
||||||
|
"title": "Title",
|
||||||
|
"type": "string",
|
||||||
|
"find": {"autocomplete": true, "autocompleteSortKey": "votes"},
|
||||||
|
"sort": {"removable": false, "type": "title", "width": 180}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "director",
|
||||||
|
"title": "Director",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"removable": false, "type": "person", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "country",
|
||||||
|
"title": "Country",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "string", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "year",
|
||||||
|
"title": "Year",
|
||||||
|
"type": "year",
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "year", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "language",
|
||||||
|
"title": "Language",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "string", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "writer",
|
||||||
|
"title": "Writer",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "person", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":
|
||||||
|
"producer",
|
||||||
|
"type": ["string"],
|
||||||
|
"title": "Producer",
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "person", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cinematographer",
|
||||||
|
"title": "Cinematographer",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "person", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "editor",
|
||||||
|
"title": "Editor",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "person", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "actor",
|
||||||
|
"title": "Actor",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "character",
|
||||||
|
"title": "Character",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "name",
|
||||||
|
"title": "Name",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "numberofactors",
|
||||||
|
"title": "Number of Actors",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"value": {"key": "actor", "type": "length"},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "genre",
|
||||||
|
"title": "Genre",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"sort": {"type": "string", "width": 180},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "keyword",
|
||||||
|
"title": "Keyword",
|
||||||
|
"type": ["string"],
|
||||||
|
"find": {"autocomplete": true},
|
||||||
|
"group": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "numberofkeywords",
|
||||||
|
"title": "Number of Keyword",
|
||||||
|
"type": "integer",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"value": {"key": "keyword", "type": "length"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "runtime",
|
||||||
|
"title": "Runtime",
|
||||||
|
"type": "integer",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"format": {"type": "duration", "args": [0, "medium"]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "summary",
|
||||||
|
"title": "Summary",
|
||||||
|
"type": "text",
|
||||||
|
"group": false,
|
||||||
|
"find": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dialog",
|
||||||
|
"title": "Dialog",
|
||||||
|
"type": "text",
|
||||||
|
"group": false,
|
||||||
|
"find": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wordsinsummary",
|
||||||
|
"title": "Words in Summary",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer",
|
||||||
|
"value": {"key": "summary", "type": "words"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wordsintrivia",
|
||||||
|
"title": "Words in Trivia",
|
||||||
|
"type": "integer",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"value": {"key": "trivia", "type": "words"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "releasedate",
|
||||||
|
"title": "Release Date",
|
||||||
|
"sort": {"type": "date", "width": 120},
|
||||||
|
"type": "date",
|
||||||
|
"format": {"type": "date", "args": ["%a, %b %e, %Y"]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "budget",
|
||||||
|
"title": "Budget",
|
||||||
|
"sort": {"type": "integer", "width": 90},
|
||||||
|
"type": "integer",
|
||||||
|
"format": {"type": "currency", "args": ["$", 0]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gross",
|
||||||
|
"title": "Gross",
|
||||||
|
"sort": {"type": "integer", "width": 90},
|
||||||
|
"type": "integer",
|
||||||
|
"format": {"type": "currency", "args": ["$", 0]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "profit",
|
||||||
|
"title": "Profit",
|
||||||
|
"sort": {"type": "integer", "width": 90},
|
||||||
|
"type": "integer",
|
||||||
|
"format": {"type": "currency", "args": ["$", 0]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rating",
|
||||||
|
"title": "Rating",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float",
|
||||||
|
"format": {"type": "percent", "args": [10, 2]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "votes",
|
||||||
|
"title": "Votes",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer",
|
||||||
|
"format": {"type": "percent", "args": [403824, 2]}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "id",
|
||||||
|
"title": "ID",
|
||||||
|
"sort": {"type": "string", "width": 90},
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aspectratio",
|
||||||
|
"title": "Aspect Ratio",
|
||||||
|
"sort": {"type": "float", "width": 90},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "duration",
|
||||||
|
"title": "Duration",
|
||||||
|
"sort": {"type": "float", "width": 90},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "color",
|
||||||
|
"title": "Color",
|
||||||
|
"sort": {"type": "float", "width": 90},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "saturation",
|
||||||
|
"title": "Saturation",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "brightness",
|
||||||
|
"title": "Brightness",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "volume",
|
||||||
|
"title": "Volume",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "clips",
|
||||||
|
"title": "Clips",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cuts",
|
||||||
|
"title": "Cuts",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cutsperminute",
|
||||||
|
"title": "Cuts per Minute",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "words",
|
||||||
|
"title": "Words",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wordsperminute",
|
||||||
|
"title": "Words per Minute",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "resolution",
|
||||||
|
"title": "Resolution",
|
||||||
|
"sort": {"type": "integer", "width": 90},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pixels",
|
||||||
|
"title": "Pixels",
|
||||||
|
"type": "integer",
|
||||||
|
"group": false,
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"auto": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "size",
|
||||||
|
"title": "Size",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bitrate",
|
||||||
|
"title": "Bitrate",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "files",
|
||||||
|
"title": "Files",
|
||||||
|
"sort": {"type": "integer", "width": 60},
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "filename",
|
||||||
|
"title": "Filename",
|
||||||
|
"sort": {"type": "string", "width": 180},
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "published",
|
||||||
|
"title": "Date Published",
|
||||||
|
"sort": {"type": "date", "width": 90},
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "modified",
|
||||||
|
"title": "Date Modified",
|
||||||
|
"sort": {"type": "date", "width": 90},
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "popularity",
|
||||||
|
"title": "Popularity",
|
||||||
|
"sort": {"type": "float", "width": 60},
|
||||||
|
"type": "float"
|
||||||
|
}
|
||||||
|
],
|
||||||
"itemName": {
|
"itemName": {
|
||||||
"singular": "Movie",
|
"singular": "Movie",
|
||||||
"plural": "Movies"
|
"plural": "Movies"
|
|
@ -58,7 +58,7 @@ def init(request):
|
||||||
response['data']['user'] = {'name': 'Guest',
|
response['data']['user'] = {'name': 'Guest',
|
||||||
'group': 'guest',
|
'group': 'guest',
|
||||||
'preferences': {}}
|
'preferences': {}}
|
||||||
with open(os.path.join(settings.PROJECT_ROOT, 'templates', 'site.json')) as f:
|
with open(settings.SITE_CONFIG) as f:
|
||||||
response['data']['config'] = json.load(f)
|
response['data']['config'] = json.load(f)
|
||||||
response['data']['config']['site']['id'] = settings.SITEID
|
response['data']['config']['site']['id'] = settings.SITEID
|
||||||
response['data']['config']['site']['name'] = settings.SITENAME
|
response['data']['config']['site']['name'] = settings.SITENAME
|
||||||
|
|
|
@ -25,10 +25,10 @@ class SiteSettings(models.Model):
|
||||||
return self.key
|
return self.key
|
||||||
|
|
||||||
def site_config():
|
def site_config():
|
||||||
with open(os.path.join(settings.PROJECT_ROOT, 'templates', 'site.json')) as f:
|
with open(settings.SITE_CONFIG) as f:
|
||||||
site_config = json.load(f)
|
site_config = json.load(f)
|
||||||
site_config['keys'] = {}
|
site_config['keys'] = {}
|
||||||
for key in site_config['sortKeys']:
|
for key in site_config['itemKeys']:
|
||||||
site_config['keys'][key['id']] = key
|
site_config['keys'][key['id']] = key
|
||||||
site_config['_findKeys'] = {}
|
site_config['_findKeys'] = {}
|
||||||
for key in site_config['findKeys']:
|
for key in site_config['findKeys']:
|
||||||
|
|
|
@ -35,6 +35,8 @@ def parseCondition(condition):
|
||||||
exclude = False
|
exclude = False
|
||||||
|
|
||||||
key_type = models.site_config()['keys'].get(k, {'type':'string'}).get('type')
|
key_type = models.site_config()['keys'].get(k, {'type':'string'}).get('type')
|
||||||
|
if isinstance(key_type, list):
|
||||||
|
key_type = key_type[0]
|
||||||
key_type = {
|
key_type = {
|
||||||
'title': 'string',
|
'title': 'string',
|
||||||
'person': 'string',
|
'person': 'string',
|
||||||
|
@ -71,12 +73,16 @@ def parseCondition(condition):
|
||||||
value_key = 'find__value__icontains'
|
value_key = 'find__value__icontains'
|
||||||
k = str(k)
|
k = str(k)
|
||||||
if exclude:
|
if exclude:
|
||||||
if in_find and not k.startswith('itemId'):
|
if k == 'all':
|
||||||
|
q = ~Q(**{value_key: v})
|
||||||
|
elif in_find and not k.startswith('itemId'):
|
||||||
q = ~Q(**{'find__key': k, value_key: v})
|
q = ~Q(**{'find__key': k, value_key: v})
|
||||||
else:
|
else:
|
||||||
q = ~Q(**{k: v})
|
q = ~Q(**{k: v})
|
||||||
else:
|
else:
|
||||||
if in_find and not k.startswith('itemId'):
|
if k == 'all':
|
||||||
|
q = Q(**{value_key: v})
|
||||||
|
elif in_find and not k.startswith('itemId'):
|
||||||
q = Q(**{'find__key': k, value_key: v})
|
q = Q(**{'find__key': k, value_key: v})
|
||||||
else:
|
else:
|
||||||
q = Q(**{k: v})
|
q = Q(**{k: v})
|
||||||
|
@ -239,7 +245,7 @@ class ItemManager(Manager):
|
||||||
qs = qs.filter(available=True)
|
qs = qs.filter(available=True)
|
||||||
conditions = parseConditions(data['query'].get('conditions', []),
|
conditions = parseConditions(data['query'].get('conditions', []),
|
||||||
data['query'].get('operator', '&'))
|
data['query'].get('operator', '&'))
|
||||||
qs = qs.filter(conditions)
|
qs = qs.filter(conditions).distinct()
|
||||||
|
|
||||||
#anonymous can only see public items
|
#anonymous can only see public items
|
||||||
if user.is_anonymous():
|
if user.is_anonymous():
|
||||||
|
|
|
@ -327,13 +327,14 @@ class Item(models.Model):
|
||||||
return layers
|
return layers
|
||||||
|
|
||||||
def get_json(self, fields=None):
|
def get_json(self, fields=None):
|
||||||
item = {
|
i = {
|
||||||
'id': self.itemId
|
'id': self.itemId
|
||||||
}
|
}
|
||||||
item.update(self.external_data)
|
i.update(self.external_data)
|
||||||
item.update(self.data)
|
i.update(self.data)
|
||||||
for key in site_config()['keys'].keys():
|
for k in site_config()['itemKeys']:
|
||||||
if key not in item:
|
key = k['id']
|
||||||
|
if key not in i:
|
||||||
value = self.get(key)
|
value = self.get(key)
|
||||||
#also get values from sort table, i.e. numberof values
|
#also get values from sort table, i.e. numberof values
|
||||||
if not value and self.sort and hasattr(self.sort, key):
|
if not value and self.sort and hasattr(self.sort, key):
|
||||||
|
@ -343,18 +344,18 @@ class Item(models.Model):
|
||||||
else:
|
else:
|
||||||
value = getattr(self.sort, key)
|
value = getattr(self.sort, key)
|
||||||
if value:
|
if value:
|
||||||
item[key] = value
|
i[key] = value
|
||||||
|
|
||||||
#format datetime values
|
#format datetime values
|
||||||
for key in item:
|
for key in i:
|
||||||
if isinstance(item[key], datetime):
|
if isinstance(i[key], datetime):
|
||||||
item[key] = item[key].strftime('%Y-%m-%dT%H:%M:%SZ')
|
i[key] = i[key].strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
if not fields:
|
if not fields:
|
||||||
item['stream'] = self.get_stream()
|
i['stream'] = self.get_stream()
|
||||||
item['poster'] = self.get_poster()
|
i['poster'] = self.get_poster()
|
||||||
item['posters'] = self.get_posters()
|
i['posters'] = self.get_posters()
|
||||||
return item
|
return i
|
||||||
|
|
||||||
|
|
||||||
def oxdb_id(self):
|
def oxdb_id(self):
|
||||||
|
@ -370,7 +371,7 @@ class Item(models.Model):
|
||||||
|
|
||||||
def save(key, value):
|
def save(key, value):
|
||||||
f, created = ItemFind.objects.get_or_create(item=self, key=key)
|
f, created = ItemFind.objects.get_or_create(item=self, key=key)
|
||||||
if value not in ('', '||'):
|
if value not in (''):
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, basestring):
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
f.value = value
|
f.value = value
|
||||||
|
@ -392,22 +393,16 @@ class Item(models.Model):
|
||||||
else:
|
else:
|
||||||
values = self.get(key, '')
|
values = self.get(key, '')
|
||||||
if isinstance(values, list):
|
if isinstance(values, list):
|
||||||
save(key, '|%s|'%'|'.join(values))
|
save(key, '\n'.join(values))
|
||||||
else:
|
else:
|
||||||
save(key, values)
|
save(key, values)
|
||||||
|
|
||||||
save('summary', self.get('summary', '') + self.get('plot', '') + self.get('plot_outline', ''))
|
save('summary', self.get('summary', ''))
|
||||||
save('trivia', ' '.join(self.get('trivia', [])))
|
save('trivia', ' '.join(self.get('trivia', [])))
|
||||||
save('location', '|%s|'%'|'.join(self.get('filming_locations', [])))
|
|
||||||
|
|
||||||
#FIXME:
|
#FIXME:
|
||||||
#f.dialog = 'fixme'
|
qs = Annotation.objects.filter(layer__type='subtitle', item=self).order_by('start')
|
||||||
save('dialog', '\n'.join([l.value for l in Annotation.objects.filter(layer__type='subtitle', item=self).order_by('start')]))
|
save('dialog', '\n'.join([l.value for l in qs]))
|
||||||
|
|
||||||
#FIXME: collate filenames
|
|
||||||
#f.filename = self.filename
|
|
||||||
all_find = ' '.join([f.value for f in ItemFind.objects.filter(item=self).exclude(key='all')])
|
|
||||||
save('all', all_find)
|
|
||||||
|
|
||||||
def update_sort(self):
|
def update_sort(self):
|
||||||
try:
|
try:
|
||||||
|
@ -446,28 +441,32 @@ class Item(models.Model):
|
||||||
'modified',
|
'modified',
|
||||||
'popularity'
|
'popularity'
|
||||||
)
|
)
|
||||||
for key in site_config()['sortKeys']:
|
|
||||||
name = key['id']
|
|
||||||
source = key.get('key', name)
|
|
||||||
field_type = key['type']
|
|
||||||
max_int = 9223372036854775807L
|
max_int = 9223372036854775807L
|
||||||
|
|
||||||
|
for key in filter(lambda k: 'sort' in k, config['itemKeys']):
|
||||||
|
name = key['id']
|
||||||
|
source = name
|
||||||
|
sort_type = key['sort'].get('type', key['type'])
|
||||||
|
if 'value' in key:
|
||||||
|
source = key['value']['key']
|
||||||
|
sort_type = key['value'].get('type', sort_type)
|
||||||
|
|
||||||
if name not in base_keys:
|
if name not in base_keys:
|
||||||
if field_type == 'title':
|
if sort_type == 'title':
|
||||||
value = utils.sort_title(canonicalTitle(self.get(source)))
|
value = utils.sort_title(canonicalTitle(self.get(source)))
|
||||||
value = utils.sort_string(value)
|
value = utils.sort_string(value)
|
||||||
setattr(s, '%s_desc'%name, value)
|
setattr(s, '%s_desc'%name, value)
|
||||||
if not value:
|
if not value:
|
||||||
value = 'zzzzzzzzzzzzzzzzzzzzzzzzz'
|
value = 'zzzzzzzzzzzzzzzzzzzzzzzzz'
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'person':
|
elif sort_type == 'person':
|
||||||
value = sortNames(self.get(source, []))
|
value = sortNames(self.get(source, []))
|
||||||
value = utils.sort_string(value)[:955]
|
value = utils.sort_string(value)[:955]
|
||||||
setattr(s, '%s_desc'%name, value)
|
setattr(s, '%s_desc'%name, value)
|
||||||
if not value:
|
if not value:
|
||||||
value = 'zzzzzzzzzzzzzzzzzzzzzzzzz'
|
value = 'zzzzzzzzzzzzzzzzzzzzzzzzz'
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'string':
|
elif sort_type == 'string':
|
||||||
value = self.get(source, u'')
|
value = self.get(source, u'')
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
value = u','.join(value)
|
value = u','.join(value)
|
||||||
|
@ -476,7 +475,7 @@ class Item(models.Model):
|
||||||
if not value:
|
if not value:
|
||||||
value = 'zzzzzzzzzzzzzzzzzzzzzzzzz'
|
value = 'zzzzzzzzzzzzzzzzzzzzzzzzz'
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'length':
|
elif sort_type == 'length':
|
||||||
#can be length of strings or length of arrays, i.e. keywords
|
#can be length of strings or length of arrays, i.e. keywords
|
||||||
value = self.get(source, None)
|
value = self.get(source, None)
|
||||||
if not value:
|
if not value:
|
||||||
|
@ -487,7 +486,7 @@ class Item(models.Model):
|
||||||
if value == -max_int:
|
if value == -max_int:
|
||||||
value = max_int
|
value = max_int
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'integer':
|
elif sort_type == 'integer':
|
||||||
value = self.get(source, -max_int)
|
value = self.get(source, -max_int)
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
value = len(value)
|
value = len(value)
|
||||||
|
@ -495,7 +494,7 @@ class Item(models.Model):
|
||||||
if value == -max_int:
|
if value == -max_int:
|
||||||
value = max_int
|
value = max_int
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'float':
|
elif sort_type == 'float':
|
||||||
max_float = 9223372036854775807L
|
max_float = 9223372036854775807L
|
||||||
value = self.get(source, -max_float)
|
value = self.get(source, -max_float)
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
|
@ -504,7 +503,7 @@ class Item(models.Model):
|
||||||
if value == -max_float:
|
if value == -max_float:
|
||||||
value = max_float
|
value = max_float
|
||||||
setattr(s, '%s_desc'%name, value)
|
setattr(s, '%s_desc'%name, value)
|
||||||
elif field_type == 'words':
|
elif sort_type == 'words':
|
||||||
value = self.get(source, '')
|
value = self.get(source, '')
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
value = '\n'.join(value)
|
value = '\n'.join(value)
|
||||||
|
@ -513,13 +512,13 @@ class Item(models.Model):
|
||||||
else:
|
else:
|
||||||
value = 0
|
value = 0
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'year':
|
elif sort_type == 'year':
|
||||||
value = self.get(source, '')
|
value = self.get(source, '')
|
||||||
setattr(s, '%s_desc'%name, value)
|
setattr(s, '%s_desc'%name, value)
|
||||||
if not value:
|
if not value:
|
||||||
value = '9999'
|
value = '9999'
|
||||||
setattr(s, name, value)
|
setattr(s, name, value)
|
||||||
elif field_type == 'date':
|
elif sort_type == 'date':
|
||||||
value = self.get(source, None)
|
value = self.get(source, None)
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, basestring):
|
||||||
value = datetime.strptime(value, '%Y-%m-%d')
|
value = datetime.strptime(value, '%Y-%m-%d')
|
||||||
|
@ -597,7 +596,8 @@ class Item(models.Model):
|
||||||
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, item=self)
|
f, created = Facet.objects.get_or_create(key='year', value=year,
|
||||||
|
value_sort=year, item=self)
|
||||||
else:
|
else:
|
||||||
Facet.objects.filter(item=self, key='year').delete()
|
Facet.objects.filter(item=self, key='year').delete()
|
||||||
|
|
||||||
|
@ -611,7 +611,8 @@ class Item(models.Model):
|
||||||
|
|
||||||
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, self.path(), 'frames', "%d"%width, "%s.jpg"%position)
|
path = os.path.join(settings.MEDIA_ROOT, self.path(),
|
||||||
|
'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
|
||||||
|
@ -621,7 +622,8 @@ class Item(models.Model):
|
||||||
return os.path.join(settings.MEDIA_ROOT, self.path(), 'timeline')
|
return os.path.join(settings.MEDIA_ROOT, self.path(), 'timeline')
|
||||||
|
|
||||||
def main_videos(self):
|
def main_videos(self):
|
||||||
#FIXME: needs to check if more than one user has main files and only take from "higher" user
|
#FIXME: needs to check if more than one user has main files and only
|
||||||
|
# take from "higher" user
|
||||||
videos = self.files.filter(is_main=True, is_video=True, available=True)
|
videos = self.files.filter(is_main=True, is_video=True, available=True)
|
||||||
if videos.count()>0:
|
if videos.count()>0:
|
||||||
first = videos[0]
|
first = videos[0]
|
||||||
|
@ -642,7 +644,8 @@ class Item(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(item=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.video.name = stream.path()
|
||||||
cmd = []
|
cmd = []
|
||||||
if os.path.exists(stream.video.path):
|
if os.path.exists(stream.video.path):
|
||||||
|
@ -655,7 +658,8 @@ class Item(models.Model):
|
||||||
cmd.append(files[f])
|
cmd.append(files[f])
|
||||||
cmd = [ 'mkvmerge', '-o', stream.video.path ] + cmd[1:]
|
cmd = [ 'mkvmerge', '-o', stream.video.path ] + cmd[1:]
|
||||||
#print cmd
|
#print cmd
|
||||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
#p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
#p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
||||||
p.wait()
|
p.wait()
|
||||||
else:
|
else:
|
||||||
|
@ -663,8 +667,9 @@ class Item(models.Model):
|
||||||
stream.save()
|
stream.save()
|
||||||
|
|
||||||
if 'video' in stream.info:
|
if 'video' in stream.info:
|
||||||
|
v = stream.info['video'][0]
|
||||||
extract.timeline(stream.video.path, self.timeline_prefix)
|
extract.timeline(stream.video.path, self.timeline_prefix)
|
||||||
self.stream_aspect = stream.info['video'][0]['width']/stream.info['video'][0]['height']
|
self.stream_aspect = v['width']/v['height']
|
||||||
self.data['cuts'] = extract.cuts(self.timeline_prefix)
|
self.data['cuts'] = extract.cuts(self.timeline_prefix)
|
||||||
self.data['color'] = extract.average_color(self.timeline_prefix)
|
self.data['color'] = extract.average_color(self.timeline_prefix)
|
||||||
#extract.timeline_strip(self, self.data['cuts'], stream.info, self.timeline_prefix[:-8])
|
#extract.timeline_strip(self, self.data['cuts'], stream.info, self.timeline_prefix[:-8])
|
||||||
|
@ -804,15 +809,18 @@ class Item(models.Model):
|
||||||
return icon
|
return icon
|
||||||
return None
|
return None
|
||||||
|
|
||||||
Item.facet_keys = []
|
|
||||||
Item.person_keys = []
|
|
||||||
config = site_config()
|
config = site_config()
|
||||||
for key in config['findKeys']:
|
|
||||||
name = key['id']
|
Item.facet_keys = []
|
||||||
if key.get('autocomplete', False) and not config['keys'].get(name, {'type': None})['type'] == 'title':
|
for key in filter(lambda k: 'find' in k, config['itemKeys']):
|
||||||
Item.facet_keys.append(name)
|
if 'autocomplete' in key['find'] and not 'autokompleteSortKey' in key['find']:
|
||||||
if name in config['keys'] and config['keys'][name]['type'] == 'person':
|
Item.facet_keys.append(key['id'])
|
||||||
Item.person_keys.append(name)
|
|
||||||
|
Item.person_keys = []
|
||||||
|
for key in filter(lambda k: 'sort' in k, config['itemKeys']):
|
||||||
|
if key['sort'].get('type', '') == 'person':
|
||||||
|
Item.person_keys.append(key['id'])
|
||||||
|
|
||||||
class ItemFind(models.Model):
|
class ItemFind(models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -832,38 +840,39 @@ class ItemFind(models.Model):
|
||||||
return u"%s=%s" % (self.key, self.value)
|
return u"%s=%s" % (self.key, self.value)
|
||||||
'''
|
'''
|
||||||
ItemSort
|
ItemSort
|
||||||
table constructed based on info in site_config['sortKeys']
|
table constructed based on info in site_config['itemKeys']
|
||||||
'''
|
'''
|
||||||
attrs = {
|
attrs = {
|
||||||
'__module__': 'item.models',
|
'__module__': 'item.models',
|
||||||
'item': models.OneToOneField('Item', related_name='sort', primary_key=True),
|
'item': models.OneToOneField('Item', related_name='sort', primary_key=True),
|
||||||
}
|
}
|
||||||
for key in config['sortKeys']:
|
for key in filter(lambda k: 'sort' in k, config['itemKeys']):
|
||||||
name = key['id']
|
name = key['id']
|
||||||
name = {'id': 'itemId'}.get(name, name)
|
name = {'id': 'itemId'}.get(name, name)
|
||||||
field_type = key['type']
|
sort_type = key['sort'].get('type', key['type'])
|
||||||
if field_type in ('string', 'title', 'person'):
|
model = {
|
||||||
attrs[name] = models.CharField(max_length=1000, db_index=True)
|
'char': (models.CharField, dict(max_length=1000, db_index=True)),
|
||||||
attrs['%s_desc'%name] = models.CharField(max_length=1000, db_index=True)
|
'year': (models.CharField, dict(max_length=4, db_index=True)),
|
||||||
elif field_type == 'year':
|
'integer': (models.BigIntegerField, dict(blank=True, db_index=True)),
|
||||||
attrs[name] = models.CharField(max_length=4, db_index=True)
|
'float': (models.FloatField, dict(blank=True, db_index=True)),
|
||||||
attrs['%s_desc'%name] = models.CharField(max_length=4, db_index=True)
|
'date': (models.DateTimeField, dict(blank=True, db_index=True))
|
||||||
elif field_type in ('integer', 'words', 'length'):
|
}[{
|
||||||
attrs[name] = models.BigIntegerField(blank=True, db_index=True)
|
'string': 'char',
|
||||||
attrs['%s_desc'%name] = models.BigIntegerField(blank=True, db_index=True)
|
'title': 'char',
|
||||||
elif field_type == 'float':
|
'person': 'char',
|
||||||
attrs[name] = models.FloatField(blank=True, db_index=True)
|
'year': 'year',
|
||||||
attrs['%s_desc'%name] = models.FloatField(blank=True, db_index=True)
|
'words': 'integer',
|
||||||
elif field_type == 'date':
|
'length': 'integer',
|
||||||
attrs[name] = models.DateTimeField(blank=True, db_index=True)
|
'date': 'date',
|
||||||
attrs['%s_desc'%name] = models.DateTimeField(blank=True, db_index=True)
|
}.get(sort_type, sort_type)]
|
||||||
else:
|
attrs[name] = model[0](**model[1])
|
||||||
print field_type
|
attrs['%s_desc'%name] = model[0](**model[1])
|
||||||
print key
|
|
||||||
|
|
||||||
ItemSort = type('ItemSort', (models.Model,), attrs)
|
ItemSort = type('ItemSort', (models.Model,), attrs)
|
||||||
ItemSort.fields = filter(lambda x: not x.endswith('_desc'), [f.name for f in ItemSort._meta.fields])
|
ItemSort.fields = filter(lambda x: not x.endswith('_desc'),
|
||||||
ItemSort.descending_fields = filter(lambda x: x.endswith('_desc'), [f.name for f in ItemSort._meta.fields])
|
[f.name for f in ItemSort._meta.fields])
|
||||||
|
ItemSort.descending_fields = filter(lambda x: x.endswith('_desc'),
|
||||||
|
[f.name for f in ItemSort._meta.fields])
|
||||||
|
|
||||||
|
|
||||||
class Facet(models.Model):
|
class Facet(models.Model):
|
||||||
|
|
|
@ -239,12 +239,14 @@ def autocomplete(request):
|
||||||
op = data.get('operator', '')
|
op = data.get('operator', '')
|
||||||
|
|
||||||
site_config = models.site_config()
|
site_config = models.site_config()
|
||||||
order_by = site_config['_findKeys'].get(data['key'], {}).get('autocompleteSortKey', False)
|
key = site_config['keys'][data['key']]
|
||||||
|
order_by = key.get('find', {}).get('autocompleteSortKey', False)
|
||||||
if order_by:
|
if order_by:
|
||||||
order_by = '-sort__%s_desc' % order_by
|
order_by = '-sort__%s_desc' % order_by
|
||||||
else:
|
else:
|
||||||
order_by = '-items'
|
order_by = '-items'
|
||||||
if site_config['keys'][data['key']]['type'] == 'title':
|
sort_type = key.get('sort', {}).get('type', 'string')
|
||||||
|
if sort_type == 'title':
|
||||||
qs = _parse_query({'query': data.get('query', {})}, request.user)['qs']
|
qs = _parse_query({'query': data.get('query', {})}, request.user)['qs']
|
||||||
if data['value']:
|
if data['value']:
|
||||||
if op == '':
|
if op == '':
|
||||||
|
|
|
@ -139,6 +139,7 @@ AUTH_PROFILE_MODULE = 'user.UserProfile'
|
||||||
#Video encoding settings
|
#Video encoding settings
|
||||||
#available profiles: 96p, 270p, 360p, 480p, 720p, 1080p
|
#available profiles: 96p, 270p, 360p, 480p, 720p, 1080p
|
||||||
|
|
||||||
|
SITE_CONFIG = join(PROJECT_ROOT, '0xdb.json')
|
||||||
DEFAULT_SORT = [{"key": "director", "operator": ""}]
|
DEFAULT_SORT = [{"key": "director", "operator": ""}]
|
||||||
DEFAULT_THEME = "classic"
|
DEFAULT_THEME = "classic"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue