This commit is contained in:
rolux 2011-11-03 12:58:55 +00:00
commit 0225370985
20 changed files with 80 additions and 99 deletions

61
README
View file

@ -1,14 +1,16 @@
pan.do/ra - open media archive pan.do/ra - open media archive
== DEVELOPMENT == == SETUP ==
To setup a development instance of pan.do/ra, To setup pan.do/ra, you need
you need python, bazaar, pip and virtualenv and several other python modules: python, bazaar, pip and virtualenv and several other python modules:
* Packages * Packages
apt-get install bzr git subversion mercurial \ apt-get install bzr git subversion mercurial \
python-setuptools python-pip python-virtualenv ipython \ python-setuptools python-pip python-virtualenv ipython \
python-dev python-imaging python-numpy python-psycopg2 python-dev python-imaging python-numpy python-psycopg2
* Pan.do/ra
Get code from bazzar
bzr branch http://code.0x2620.org/pandora pandora bzr branch http://code.0x2620.org/pandora pandora
cd pandora cd pandora
virtualenv . virtualenv .
@ -17,6 +19,18 @@ you need python, bazaar, pip and virtualenv and several other python modules:
cd static cd static
bzr branch http://code.0x2620.org/oxjs bzr branch http://code.0x2620.org/oxjs
create settings_local.py and create site.jsonc
(use settings.py / 0xdb.jsonc / padma.jsonc as example)
create db
./manage.py syncdb
create / update static files
./manage.py update_static
./manage.py compile_pyc
* Additional pandora tools: * Additional pandora tools:
You need current versions of oxframe, oxtimeline installed. You need current versions of oxframe, oxtimeline installed.
For Ubuntu we provide these packages in a ppa: For Ubuntu we provide these packages in a ppa:
@ -30,11 +44,12 @@ you need python, bazaar, pip and virtualenv and several other python modules:
(make sure you have the python bindings installed). (make sure you have the python bindings installed).
create a postgresql database and adjust settings in local_settings.py create a postgresql database and adjust settings in local_settings.py
and run ./manage.py syncdb to populate the database and run ./manage.py syncdb to populate the database.
you might want to load example configurations from fixutes.
createdb -T template0 --locale=C --encoding=UTF8 -O pandora pandora createdb -T template0 --locale=C --encoding=UTF8 -O pandora pandora
(setting locale to C is required to fix a bug in sort if set to UTF8)
* RabbitMQ * RabbitMQ
For background tasks we use RabbitMQ, to install rabbitmq: For background tasks we use RabbitMQ, to install rabbitmq:
sudo apt-get install rabbitmq-server sudo apt-get install rabbitmq-server
@ -48,7 +63,7 @@ you need python, bazaar, pip and virtualenv and several other python modules:
* H264 * H264
to support h264 videos, install ffmpeg with x264 enabled, to support h264 videos, install ffmpeg with x264 enabled,
install qt-faststart from (ffmpeg/tools) install qt-faststart from (ffmpeg/tools)
set VIDEO_H264 = True in local_settings.py to enable add "mp4" to video.formats in your config.jsonc
Running developer environment: Running developer environment:
in one terminal: in one terminal:
@ -56,24 +71,36 @@ Running developer environment:
and in another one: and in another one:
./manage.py celeryd -Q default,encoding -B ./manage.py celeryd -Q default,encoding -B
Updating database: === Updating ===
right now database updates are not managed, each time you update to current bzr To update a pandora installation get the latest version from bzr by running
you might have to update db tables too. ./update.sh
Use this will pull pandora/oxjs/python-ox and list possible upgrades to the db
./manage.py sqldiff appname
to check if changes exist and to update your database tables, use
./manage.py sqldiff appname | ./manage.py dbshell ./manage.py sqldiff -a
to apply them. to check if there are changes and
This has to be done for all installed apps ./manage.py sqldiff -a | ./manage.py dbshell
to apply them.
== DEPLOYMENT == == DEPLOYMENT ==
* Install upstart scripts
check etc/init for upstart scripts, adjust path and user and put into /etc/init
To run pan.do/ra in production, we use nginx, using apache2 is also possible. To run pan.do/ra in production, we use nginx, using apache2 is also possible.
* nginx setup * nginx setup
sudo apt-get install nginx sudo apt-get install nginx
add this to local_settings.py:
XACCELREDIRECT = True
setup nginx according to etc/nginx/vhost.in
* apache2 setup * apache2 setup
sudo apt-get install apache2-mpm-prefork apt-get install apache2-mpm-prefork libapache2-mod-xsendfile
sudo apt-get install libapache2-mod-xsendfile
add this to local_settings.py:
XSENDFILE = True
setup apache according to etc/apache2/vhost.in

View file

@ -1,59 +0,0 @@
[
{
"pk": 1,
"model": "backend.reviewwhitelist",
"fields": {
"url": "://filmcritic.com",
"name": "Filmcritic"
}
},
{
"pk": 2,
"model": "backend.reviewwhitelist",
"fields": {
"url": "villagevoice.com",
"name": "Village Voice"
}
},
{
"pk": 3,
"model": "backend.reviewwhitelist",
"fields": {
"url": "salon.com",
"name": "Salon.com"
}
},
{
"pk": 4,
"model": "backend.reviewwhitelist",
"fields": {
"url": "rottentomatoes.com",
"name": "Rotten Tomatoes"
}
},
{
"pk": 5,
"model": "backend.reviewwhitelist",
"fields": {
"url": "nytimes.com",
"name": "New York Times"
}
},
{
"pk": 6,
"model": "backend.reviewwhitelist",
"fields": {
"url": "metacritic.com",
"name": "Metacritic"
}
},
{
"pk": 7,
"model": "backend.reviewwhitelist",
"fields": {
"url": "sensesofcinema.com",
"name": "Senses of Cinema"
}
}
]

View file

@ -10,7 +10,7 @@ import ox
from archive import extract from archive import extract
from clip.models import Clip from clip.models import Clip
from item.utils import sort_string
import managers import managers
import utils import utils
from tasks import update_matching_events, update_matching_places from tasks import update_matching_events, update_matching_places
@ -34,6 +34,7 @@ class Annotation(models.Model):
layer = models.CharField(max_length=255, db_index=True) layer = models.CharField(max_length=255, db_index=True)
value = models.TextField() value = models.TextField()
sortvalue = models.CharField(max_length=1000, null=True, blank=True, db_index=True)
def editable(self, user): def editable(self, user):
if user.is_authenticated(): if user.is_authenticated():
@ -57,6 +58,15 @@ class Annotation(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
set_public_id = not self.id or not self.public_id set_public_id = not self.id or not self.public_id
if self.value:
sortvalue = ox.stripTags(self.value).strip()
sortvalue = sort_string(sortvalue)
if sortvalue:
self.sortvalue = sortvalue[:1000]
else:
self.sortvalue = None
else:
self.sortvalue = None
#no clip or update clip #no clip or update clip
def get_layer(id): def get_layer(id):

View file

@ -51,6 +51,10 @@ class MetaClip:
for key in j.keys(): for key in j.keys():
if key not in keys: if key not in keys:
del j[key] del j[key]
#needed here to make item find with clips work
if 'annotations' in keys:
j['annotations'] = [a.json(keys=['value', 'id', 'layer'])
for a in self.annotations.filter(layer__in=self.layers)]
for key in keys: for key in keys:
if key not in clip_keys and key not in j: if key not in clip_keys and key not in j:
value = self.item.get(key) value = self.item.get(key)

View file

@ -35,14 +35,14 @@ def order_query(qs, sort):
if operator != '-': if operator != '-':
operator = '' operator = ''
clip_keys = ('public_id', 'start', 'end', 'hue', 'saturation', 'lightness', 'volume', clip_keys = ('public_id', 'start', 'end', 'hue', 'saturation', 'lightness', 'volume',
'annotations__value', 'videoRatio', 'annotations__sortvalue', 'videoRatio',
'director', 'title') 'director', 'title')
key = { key = {
'id': 'public_id', 'id': 'public_id',
'in': 'start', 'in': 'start',
'out': 'end', 'out': 'end',
'position': 'start', 'position': 'start',
'text': 'annotations__value', 'text': 'annotations__sortvalue',
'videoRatio': 'aspect_ratio', 'videoRatio': 'aspect_ratio',
}.get(e['key'], e['key']) }.get(e['key'], e['key'])
if key.startswith('clip:'): if key.startswith('clip:'):

View file

@ -21,7 +21,8 @@ def plural_key(term):
def sort_string(string): def sort_string(string):
string = string.replace(u'Þ', 'Th') string = string.replace(u'Æ', 'AE').replace(u'Ø', 'O').replace(u'Þ', 'Th')
#pad numbered titles #pad numbered titles
string = re.sub('(\d+)', lambda x: '%010d' % int(x.group(0)), string) string = re.sub('(\d+)', lambda x: '%010d' % int(x.group(0)), string)
return unicodedata.normalize('NFKD', string) return unicodedata.normalize('NFKD', string)

View file

@ -48,7 +48,6 @@ class Person(models.Model):
if not self.sortname: if not self.sortname:
self.sortname = ox.get_sort_name(self.name) self.sortname = ox.get_sort_name(self.name)
self.sortname = unicodedata.normalize('NFKD', self.sortname) self.sortname = unicodedata.normalize('NFKD', self.sortname)
self.sortname = self.sortname.replace(u'Æ', 'AE').replace(u'Ø', 'O').replace(u'Þ', 'P')
self.sortsortname = utils.sort_string(self.sortname) self.sortsortname = utils.sort_string(self.sortname)
self.numberofnames = len(self.name.split(' ')) self.numberofnames = len(self.name.split(' '))
super(Person, self).save(*args, **kwargs) super(Person, self).save(*args, **kwargs)

View file

@ -42,7 +42,6 @@ APPEND_SLASH = False
# Example: "/home/media/media.lawrence.com/" # Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = normpath(join(PROJECT_ROOT, '..', 'data')) MEDIA_ROOT = normpath(join(PROJECT_ROOT, '..', 'data'))
STATIC_ROOT = normpath(join(PROJECT_ROOT, '..', 'static')) STATIC_ROOT = normpath(join(PROJECT_ROOT, '..', 'static'))
TESTS_ROOT = join(PROJECT_ROOT, 'tests')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a # URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases). # trailing slash if there is a path component (optional in other cases).
@ -183,11 +182,12 @@ VIDEO_PREFIX=''
#VIDEO_PREFIX='videoPART.example.com' #VIDEO_PREFIX='videoPART.example.com'
#SESSION_COOKIE_DOMAIN=*.example.com" #SESSION_COOKIE_DOMAIN=*.example.com"
SCRIPT_ROOT = normpath(join(PROJECT_ROOT, '..', 'scripts'))
#copy scripts and adjust to customize #copy scripts and adjust to customize
ITEM_POSTER = join('scripts', 'oxdb_poster') ITEM_POSTER = join(SCRIPT_ROOT, 'oxdb_poster')
#ITEM_POSTER = join('scripts', 'padma_poster') #ITEM_POSTER = join(SCRIPT_ROOT, 'padma_poster')
ITEM_ICON = join('scripts', 'item_icon') ITEM_ICON = join(SCRIPT_ROOT, 'item_icon')
LIST_ICON = join('scripts', 'list_icon') LIST_ICON = join(SCRIPT_ROOT, 'list_icon')
#you can ignore things below this line #you can ignore things below this line

View file

@ -30,15 +30,14 @@ urlpatterns = patterns('',
(r'^robots.txt$', serve_static_file, {'location': os.path.join(settings.STATIC_ROOT, 'robots.txt'), 'content_type': 'text/plain'}), (r'^robots.txt$', serve_static_file, {'location': os.path.join(settings.STATIC_ROOT, 'robots.txt'), 'content_type': 'text/plain'}),
(r'^favicon.ico$', serve_static_file, {'location': os.path.join(settings.STATIC_ROOT, 'png/icon.16.png'), 'content_type': 'image/x-icon'}), (r'^favicon.ico$', serve_static_file, {'location': os.path.join(settings.STATIC_ROOT, 'png/icon.16.png'), 'content_type': 'image/x-icon'}),
) )
if settings.DEBUG: #if settings.DEBUG:
urlpatterns += patterns('', #sould this not be enabled by default? nginx should handle those
urlpatterns += patterns('',
(r'^data/(?P<path>.*)$', 'django.views.static.serve', (r'^data/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}), {'document_root': settings.MEDIA_ROOT}),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', (r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}), {'document_root': settings.STATIC_ROOT}),
(r'^tests/(?P<path>.*)$', 'django.views.static.serve', )
{'document_root': settings.TESTS_ROOT}),
)
urlpatterns += patterns('', urlpatterns += patterns('',
(r'^(V[a-z0-9]*)$', 'urlalias.views.padma_video'), (r'^(V[a-z0-9]*)$', 'urlalias.views.padma_video'),

View file

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -4,7 +4,7 @@
from __future__ import division from __future__ import division
import os import os
root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
#using virtualenv's activate_this.py to reorder sys.path #using virtualenv's activate_this.py to reorder sys.path
activate_this = os.path.join(root_dir, 'bin', 'activate_this.py') activate_this = os.path.join(root_dir, 'bin', 'activate_this.py')

View file

@ -4,7 +4,7 @@
from __future__ import division from __future__ import division
import os import os
root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
#using virtualenv's activate_this.py to reorder sys.path #using virtualenv's activate_this.py to reorder sys.path
activate_this = os.path.join(root_dir, 'bin', 'activate_this.py') activate_this = os.path.join(root_dir, 'bin', 'activate_this.py')

View file

@ -4,7 +4,7 @@
from __future__ import division from __future__ import division
import os import os
root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
#using virtualenv's activate_this.py to reorder sys.path #using virtualenv's activate_this.py to reorder sys.path
activate_this = os.path.join(root_dir, 'bin', 'activate_this.py') activate_this = os.path.join(root_dir, 'bin', 'activate_this.py')

View file

@ -4,7 +4,7 @@
from __future__ import division from __future__ import division
import os import os
root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) root_dir = os.path.normpath(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
#using virtualenv's activate_this.py to reorder sys.path #using virtualenv's activate_this.py to reorder sys.path
activate_this = os.path.join(root_dir, 'bin', 'activate_this.py') activate_this = os.path.join(root_dir, 'bin', 'activate_this.py')