From 47685b87fe593a10ac8c66a383831174dcf03983 Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Wed, 2 Nov 2011 12:57:10 +0100 Subject: [PATCH 1/3] add layer flags to clips to avoid slow join with annotation/layer tables --- pandora/clip/managers.py | 8 ++--- pandora/clip/models.py | 73 ++++++++++++++++++++++------------------ pandora/clip/views.py | 20 ++++++----- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/pandora/clip/managers.py b/pandora/clip/managers.py index e06bb4f68..4c2a9ae52 100644 --- a/pandora/clip/managers.py +++ b/pandora/clip/managers.py @@ -165,10 +165,6 @@ class ClipManager(Manager): if conditions: qs = qs.filter(conditions) if 'keys' in data: - public_layers = [l['id'] - for l in filter(lambda l: not l.get('private', False), - settings.CONFIG['layers'])] - filter_layers = filter(lambda k: k in public_layers, data['keys']) - if filter_layers: - qs = qs.filter(annotations__layer__name__in=filter_layers) + for l in filter(lambda k: k in self.model.layers, data['keys']): + qs = qs.filter(**{l: True}) return qs diff --git a/pandora/clip/models.py b/pandora/clip/models.py index 4dfe35f38..e2fc055f7 100644 --- a/pandora/clip/models.py +++ b/pandora/clip/models.py @@ -9,37 +9,7 @@ from archive import extract import managers -class Clip(models.Model): - ''' - CREATE INDEX clip_clip_title_idx ON clip_clip (title ASC NULLS LAST); - CREATE INDEX clip_clip_director_idx ON clip_clip (director ASC NULLS LAST); - ''' - class Meta: - unique_together = ("item", "start", "end") - - objects = managers.ClipManager() - - created = models.DateTimeField(auto_now_add=True) - modified = models.DateTimeField(auto_now=True) - public_id = models.CharField(max_length=128, unique=True) - aspect_ratio = models.FloatField(default=0) - - item = models.ForeignKey('item.Item', related_name='clips') - - #seconds - start = models.FloatField(default=-1, db_index=True) - end = models.FloatField(default=-1) - duration = models.FloatField(default=0, db_index=True) - - #get from annotation - hue = models.FloatField(default=0, db_index=True) - saturation = models.FloatField(default=0, db_index=True) - lightness = models.FloatField(default=0, db_index=True) - volume = models.FloatField(default=0, null=True, db_index=True) - - director = models.CharField(max_length=1000, db_index=True) - title = models.CharField(max_length=1000, db_index=True) - +class MetaClip: def update_calculated_values(self): self.duration = self.end - self.start if self.duration > 0: @@ -60,7 +30,9 @@ class Clip(models.Model): streams = self.item.streams() if streams: self.aspect_ratio = streams[0].aspect_ratio - super(Clip, self).save(*args, **kwargs) + for l in self.layers: + setattr(self, l, self.annotations.filter(layer__name=l).count()>0) + models.Model.save(self, *args, **kwargs) def json(self, keys=None): j = {} @@ -104,3 +76,40 @@ class Clip(models.Model): def __unicode__(self): return self.public_id +class Meta: + unique_together = ("item", "start", "end") + +attrs = { + '__module__': 'clip.models', + 'Meta': Meta, + 'objects': managers.ClipManager(), + 'created': models.DateTimeField(auto_now_add=True), + 'modified': models.DateTimeField(auto_now=True), + 'public_id': models.CharField(max_length=128, unique=True), + 'aspect_ratio': models.FloatField(default=0), + + 'item': models.ForeignKey('item.Item', related_name='clips'), + + #seconds + 'start': models.FloatField(default=-1, db_index=True), + 'end': models.FloatField(default=-1), + 'duration': models.FloatField(default=0, db_index=True), + + #get from annotation + 'hue': models.FloatField(default=0, db_index=True), + 'saturation': models.FloatField(default=0, db_index=True), + 'lightness': models.FloatField(default=0, db_index=True), + 'volume': models.FloatField(default=0, null=True, db_index=True), + + 'director': models.CharField(max_length=1000, db_index=True), + 'title': models.CharField(max_length=1000, db_index=True), +} +public_layers = [l['id'] + for l in filter(lambda l: not l.get('private', False), + settings.CONFIG['layers'])] +for name in public_layers: + attrs[name] = models.BooleanField(default=False, db_index=True) + +Clip = type('Clip', (MetaClip,models.Model), attrs) +Clip.layers = public_layers + diff --git a/pandora/clip/views.py b/pandora/clip/views.py index 945055841..3b012539f 100644 --- a/pandora/clip/views.py +++ b/pandora/clip/views.py @@ -82,19 +82,21 @@ def findClips(request): if 'keys' in data: qs = order_query(qs, query['sort']) qs = qs[query['range'][0]:query['range'][1]] - qs = qs.select_related('item__sort') - response['data']['items'] = [p.json(keys=data['keys']) for p in qs] + #qs = qs.select_related('item__sort') + ids = [] + keys = filter(lambda k: k not in models.Clip.layers, data['keys']) + def add(p): + ids.append(p.id) + return p.json(keys=keys) + response['data']['items'] = [add(p) for p in qs] keys = data['keys'] - public_layers = [l['id'] - for l in filter(lambda l: not l.get('private', False), - settings.CONFIG['layers'])] def add_annotations(layer, qs): for a in qs.values('public_id', 'value', 'clip__public_id'): for i in response['data']['items']: if i['id'] == a['clip__public_id']: - if not i[layer]: + if not layer in i: i[layer] = [] i[layer].append({ 'id': a['public_id'], @@ -103,10 +105,10 @@ def findClips(request): if response['data']['items']: if 'annotations' in keys: add_annotations('annotations', - Annotation.objects.filter(layer__name__in=public_layers, clip__in=qs)) - for layer in filter(lambda l: l in keys, public_layers): + Annotation.objects.filter(layer__name__in=models.Clip.layers, clip__in=ids)) + for layer in filter(lambda l: l in keys, models.Clip.layers): add_annotations(layer, - Annotation.objects.filter(layer__name=layer, clip__in=qs)) + Annotation.objects.filter(layer__name=layer, clip__in=ids)) elif 'position' in query: qs = order_query(qs, query['sort']) ids = [i.public_id for i in qs] From 40beeacf3f0d20026b03f90a108ebf55c87d335d Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Wed, 2 Nov 2011 14:05:30 +0100 Subject: [PATCH 2/3] refine contact api --- pandora/user/templates/contact_email.txt | 7 +++--- pandora/user/views.py | 29 +++++++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/pandora/user/templates/contact_email.txt b/pandora/user/templates/contact_email.txt index 43243d03a..b300f1ba1 100644 --- a/pandora/user/templates/contact_email.txt +++ b/pandora/user/templates/contact_email.txt @@ -1,4 +1,5 @@ -Hi {{sitename}} admin, - -someone sent you a message: +{{name}} <{{email}}> sent a contact message: {{message}} + +-- +{{sitename}} diff --git a/pandora/user/views.py b/pandora/user/views.py index faf3c2466..bd46968da 100644 --- a/pandora/user/views.py +++ b/pandora/user/views.py @@ -534,21 +534,38 @@ def contact(request): } ''' data = json.loads(request.POST['data']) - if 'email' in data and 'message' in data: - email = data['email'] + name = data.get('name', '') + email = data.get('email', '') + if request.user.is_authenticated(): + if not name: + name = request.user.username + if not email: + email = request.user.email + if 'message' in data and data['message'].strip(): + email_from = settings.CONFIG['site']['email']['system'] + email_to = [settings.CONFIG['site']['email']['contact'], ] template = loader.get_template('contact_email.txt') context = RequestContext(request, { - 'sitename': settings.SITENAME, 'email': email, - 'message': data['message'], + 'message': data['message'].strip(), + 'name': name, + 'sitename': settings.SITENAME, }) message = template.render(context) - subject = '%s contact: %s' % (settings.SITENAME, data['subject']) + subject = (u'[%s Contact] %s' % (settings.SITENAME, data.get('subject', ''))).strip() response = json_response(text='message sent') try: - send_mail(subject, message, email, [settings.DEFAULT_FROM_EMAIL, ]) + send_mail(subject.strip(), message, email_from, email_to) except BadHeaderError: response = json_response(status=400, text='invalid data') + if request.user.is_authenticated() \ + and 'receipt' in data \ + and data['receipt']: + message = data['message'].strip() + try: + send_mail(subject.strip(), message, email_from, [email]) + except: + pass else: response = json_response(status=400, text='invalid data') return render_to_json_response(response) From 79e76ca0b0926c53f64ba6db1f9d0e8fd4002269 Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Wed, 2 Nov 2011 14:26:38 +0100 Subject: [PATCH 3/3] update clip layer flag --- pandora/annotation/models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandora/annotation/models.py b/pandora/annotation/models.py index 0322057d4..00f7e84d9 100644 --- a/pandora/annotation/models.py +++ b/pandora/annotation/models.py @@ -126,6 +126,12 @@ class Annotation(models.Model): super(Annotation, self).save(*args, **kwargs) if set_public_id: self.set_public_id() + + Clip.objects.filter(**{ + 'id': self.clip.id, + self.layer.name: False + }).update(**{self.layer.name: True}) + #how expensive is this? #update_matching_events.delay(self.value) #update_matching_places.delay(self.value)