Merge pull request 'Cache annotations in Text model' (#13) from cache-annotations into main

Reviewed-on: 0x2620/aab21#13
This commit is contained in:
j 2021-10-23 13:22:03 +00:00
commit 5c356abdaa
4 changed files with 109 additions and 2 deletions

View file

@ -144,6 +144,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
TIMELINE_PREFIX = "https://aab21.pad.ma/" TIMELINE_PREFIX = "https://aab21.pad.ma/"
DEFAULT_PANDORA_API = "https://pad.ma/api/"
URL_PREFIX = 'polis+' URL_PREFIX = 'polis+'
try: try:

View file

@ -0,0 +1,18 @@
# Generated by Django 3.2.7 on 2021-10-23 09:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('text', '0006_text_position'),
]
operations = [
migrations.AddField(
model_name='text',
name='annotations',
field=models.JSONField(default=dict),
),
]

View file

@ -4,10 +4,13 @@ import json
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db import models from django.db import models
import ox
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
User = get_user_model() User = get_user_model()
DEFAULT_LAYER = 'descriptions'
class Page(models.Model): class Page(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)
@ -42,6 +45,7 @@ class Text(models.Model):
body = models.TextField(default="", blank=True) body = models.TextField(default="", blank=True)
data = models.JSONField(default=dict) data = models.JSONField(default=dict)
annotations = models.JSONField(default=dict, blank=True, editable=False)
def __str__(self): def __str__(self):
return self.title return self.title
@ -49,10 +53,93 @@ class Text(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return '/' + settings.URL_PREFIX + 'assemblies/' + self.slug return '/' + settings.URL_PREFIX + 'assemblies/' + self.slug
def get_annotations(self):
api = ox.api.signin(settings.DEFAULT_PANDORA_API)
if 'item' in self.data:
return self.get_item_annotations(api)
elif 'edit' in self.data:
return self.get_edit_annotations(api)
else:
raise Exception('Text does not have item or edit.')
def get_item_annotations(self, api):
query = {
'id': self.data['item'],
'keys': [
'layers'
]
}
layer = self.data.get('layer', None) or DEFAULT_LAYER
annotations = api.get(**query)['data']['layers'][layer]
user = self.data.get('user', None)
if user:
annotations = list(filter(lambda annot: annot['user'] == user, annotations))
return self.get_clips(api, annotations)
def get_edit_annotations(self, api):
query = {
'id': self.data['edit'],
'keys': []
}
clips = api.getEdit(**query)['data']['clips']
annotations = []
layer = self.data.get('layer', None) or DEFAULT_LAYER
for clip in clips:
for annotation in clip['layers'][layer]:
if 'user' in self.data and annotation['user'] == self.data['user']:
continue
annotation['title'] = clip['title']
annotations.append(annotation)
return self.get_clips(api, annotations)
def get_clips(self, api, annotations):
item_ids = [annot['id'].split('/')[0] for annot in annotations]
query = {
'itemsQuery': {
'conditions': [{
'key': 'id',
'operator': '&',
'value': item_ids
}]
},
'range': [0, 10000],
'keys': [
'id',
'hue',
'saturation',
'lightness'
]
}
items = api.findClips(**query)['data']['items']
colors = {}
for item in items:
colors[item['id']] = item
previous = None
for annot in annotations:
annot_id = annot['id'].split('/')[0]
annot_in = '{:.3f}'.format(annot['in'])
annot_out = '{:.3f}'.format(annot['out'])
clip_id = f'{annot_id}/{annot_in}-{annot_out}'
annot['color1'] = colors[clip_id]
if previous:
previous['color2'] = annot['color1']
previous = annot
if len(annotations) > 0:
annotations[len(annotations) - 1]['color2'] = annotations[0]['color1']
return annotations
def save(self, *args, **kwargs):
annotations = self.get_annotations()
self.annotations = annotations
super().save(*args, **kwargs)
def json(self): def json(self):
data = {} data = {}
data['title'] = self.title data['title'] = self.title
data['byline'] = self.byline data['byline'] = self.byline
data['body'] = self.body data['body'] = self.body
if isinstance(self.annotations, list) and len(self.annotations) > 0:
data['annotations'] = self.annotations
data.update(self.data) data.update(self.data)
return json.dumps(data) return json.dumps(data)

View file

@ -1,5 +1,5 @@
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.conf import settings
import ox import ox
from ... import models from ... import models
@ -7,7 +7,7 @@ class Command(BaseCommand):
help = 'import titles from pan.do/ra' help = 'import titles from pan.do/ra'
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument("--api", dest="api", type=str, default='https://pad.ma/api/'), parser.add_argument("--api", dest="api", type=str, default=settings.DEFAULT_PANDORA_API),
parser.add_argument("--group", dest="group", type=str, default='Asian Art Biennial 2021'), parser.add_argument("--group", dest="group", type=str, default='Asian Art Biennial 2021'),
def handle(self, *args, **options): def handle(self, *args, **options):