forked from 0x2620/pandora
move annotation update_matches logic into models
This commit is contained in:
parent
5d43ed0585
commit
d53659c0c4
2 changed files with 75 additions and 59 deletions
|
@ -40,8 +40,8 @@ def get_matches(obj, model, layer_type, qs=None):
|
||||||
if exact:
|
if exact:
|
||||||
q = Q(value__iexact=obj.name)
|
q = Q(value__iexact=obj.name)
|
||||||
for name in obj.alternativeNames:
|
for name in obj.alternativeNames:
|
||||||
q = q|Q(value__iexact=name)
|
q = q | Q(value__iexact=name)
|
||||||
f = q&Q(layer__in=exact)
|
f = q & Q(layer__in=exact)
|
||||||
else:
|
else:
|
||||||
f = None
|
f = None
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def get_matches(obj, model, layer_type, qs=None):
|
||||||
name = ox.decode_html(name)
|
name = ox.decode_html(name)
|
||||||
name = unicodedata.normalize('NFKD', name).lower()
|
name = unicodedata.normalize('NFKD', name).lower()
|
||||||
q = q | Q(findvalue__contains=" " + name) | Q(findvalue__startswith=name)
|
q = q | Q(findvalue__contains=" " + name) | Q(findvalue__startswith=name)
|
||||||
contains_matches = q&Q(layer__in=contains)
|
contains_matches = q & Q(layer__in=contains)
|
||||||
if f:
|
if f:
|
||||||
f = contains_matches | f
|
f = contains_matches | f
|
||||||
else:
|
else:
|
||||||
|
@ -183,11 +183,73 @@ class Annotation(models.Model):
|
||||||
|
|
||||||
# editAnnotations needs to be in snyc
|
# editAnnotations needs to be in snyc
|
||||||
# load_subtitles can not be in sync
|
# load_subtitles can not be in sync
|
||||||
fn = update_matches.delay if async else update_matches
|
if async:
|
||||||
if layer.get('type') == 'place' or layer.get('hasPlaces'):
|
update_matches.delay(self.id)
|
||||||
fn(self.id, 'place')
|
else:
|
||||||
if layer.get('type') == 'event' or layer.get('hasEvents'):
|
self.update_matches()
|
||||||
fn(self.id, 'event')
|
|
||||||
|
def update_matches(self):
|
||||||
|
from place.models import Place
|
||||||
|
from event.models import Event
|
||||||
|
types = []
|
||||||
|
layer = self.get_layer()
|
||||||
|
if layer.get('type') == 'place' or layer.get('hasPlaces'):
|
||||||
|
types.append('place')
|
||||||
|
if layer.get('type') == 'event' or layer.get('hasEvents'):
|
||||||
|
types.append('event')
|
||||||
|
for type in types:
|
||||||
|
if type == 'place':
|
||||||
|
Model = Place
|
||||||
|
elif type == 'event':
|
||||||
|
Model = Event
|
||||||
|
|
||||||
|
a_matches = getattr(self, type == 'place' and 'places' or 'events')
|
||||||
|
|
||||||
|
# remove undefined matches that only have this annotation
|
||||||
|
for p in a_matches.filter(defined=False).exclude(name=self.value):
|
||||||
|
if p.annotations.exclude(id=id).count() == 0:
|
||||||
|
p.delete()
|
||||||
|
if layer.get('type') == type and a_matches.count() == 0:
|
||||||
|
a_matches.add(Model.get_or_create(self.value))
|
||||||
|
for p in a_matches.all():
|
||||||
|
p.update_matches()
|
||||||
|
|
||||||
|
if self.findvalue:
|
||||||
|
names = {}
|
||||||
|
for n in Model.objects.all().values('id', 'name', 'alternativeNames'):
|
||||||
|
names[n['id']] = [ox.decode_html(x) for x in (n['name'],) + n['alternativeNames']]
|
||||||
|
value = self.findvalue.lower()
|
||||||
|
current = {p.id for p in a_matches.all()}
|
||||||
|
matches = []
|
||||||
|
name_matches = set()
|
||||||
|
new = set()
|
||||||
|
|
||||||
|
for i in names:
|
||||||
|
for name in names[i]:
|
||||||
|
if name.lower() in value:
|
||||||
|
matches.append(i)
|
||||||
|
name_matches.add(name.lower())
|
||||||
|
break
|
||||||
|
for p in Model.objects.filter(id__in=matches):
|
||||||
|
# only add places/events that did not get added as a super match
|
||||||
|
# i.e. only add The Paris Region and not Paris
|
||||||
|
super_match = False
|
||||||
|
for n in p.get_super_matches():
|
||||||
|
if n.lower() in name_matches:
|
||||||
|
super_match = True
|
||||||
|
break
|
||||||
|
if not super_match:
|
||||||
|
new.add(p.id)
|
||||||
|
|
||||||
|
# added or removed items are only in current or only in new
|
||||||
|
update = list(current ^ new)
|
||||||
|
if update:
|
||||||
|
for e in Model.objects.filter(id__in=update):
|
||||||
|
e.update_matches(Annotation.objects.filter(id=self.id))
|
||||||
|
else:
|
||||||
|
# annotation has no value, remove all exisint matches
|
||||||
|
for e in a_matches.all():
|
||||||
|
e.update_matches(Annotation.objects.filter(pk=self.id))
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
@ -238,6 +300,7 @@ class Annotation(models.Model):
|
||||||
'entity', 'event', 'place'
|
'entity', 'event', 'place'
|
||||||
)
|
)
|
||||||
_clip_keys = ('hue', 'lightness', 'saturation', 'volume')
|
_clip_keys = ('hue', 'lightness', 'saturation', 'volume')
|
||||||
|
|
||||||
def json(self, layer=False, keys=None, user=None, entity_cache=None):
|
def json(self, layer=False, keys=None, user=None, entity_cache=None):
|
||||||
j = {
|
j = {
|
||||||
'user': self.user.username,
|
'user': self.user.username,
|
||||||
|
@ -307,7 +370,7 @@ class Annotation(models.Model):
|
||||||
return j
|
return j
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s %s-%s" %(self.public_id, self.start, self.end)
|
return u"%s %s-%s" % (self.public_id, self.start, self.end)
|
||||||
|
|
||||||
def cleanup_related(sender, **kwargs):
|
def cleanup_related(sender, **kwargs):
|
||||||
kwargs['instance'].cleanup_undefined_relations()
|
kwargs['instance'].cleanup_undefined_relations()
|
||||||
|
|
|
@ -13,59 +13,12 @@ from .models import Annotation
|
||||||
|
|
||||||
@task(ignore_results=True, queue='default')
|
@task(ignore_results=True, queue='default')
|
||||||
def update_matches(id, type):
|
def update_matches(id, type):
|
||||||
if type == 'place':
|
|
||||||
from place.models import Place as Model
|
|
||||||
elif type == 'event':
|
|
||||||
from event.models import Event as Model
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
a = Annotation.objects.get(pk=id)
|
a = Annotation.objects.get(pk=id)
|
||||||
except Annotation.DoesNotExist:
|
except Annotation.DoesNotExist:
|
||||||
return
|
a = None
|
||||||
a_matches = getattr(a, type == 'place' and 'places' or 'events')
|
if a:
|
||||||
|
a.update_matches()
|
||||||
# remove undefined matches that only have this annotation
|
|
||||||
for p in a_matches.filter(defined=False).exclude(name=a.value):
|
|
||||||
if p.annotations.exclude(id=id).count() == 0:
|
|
||||||
p.delete()
|
|
||||||
if a.get_layer().get('type') == type and a_matches.count() == 0:
|
|
||||||
a_matches.add(Model.get_or_create(a.value))
|
|
||||||
for p in a_matches.all():
|
|
||||||
p.update_matches()
|
|
||||||
|
|
||||||
if a.findvalue:
|
|
||||||
names = {}
|
|
||||||
for n in Model.objects.all().values('id', 'name', 'alternativeNames'):
|
|
||||||
names[n['id']] = [ox.decode_html(x) for x in (n['name'],) + n['alternativeNames']]
|
|
||||||
value = a.findvalue.lower()
|
|
||||||
|
|
||||||
current = [p.id for p in a_matches.all()]
|
|
||||||
matches = []
|
|
||||||
name_matches = []
|
|
||||||
for i in names:
|
|
||||||
for name in names[i]:
|
|
||||||
if name.lower() in value:
|
|
||||||
matches.append(i)
|
|
||||||
name_matches.append(name.lower())
|
|
||||||
break
|
|
||||||
new = []
|
|
||||||
for i in matches:
|
|
||||||
p = Model.objects.get(pk=i)
|
|
||||||
# only add places/events that did not get added as a super match
|
|
||||||
# i.e. only add The Paris Region and not Paris
|
|
||||||
if not filter(lambda n: n in name_matches,
|
|
||||||
[n.lower() for n in p.get_super_matches()]):
|
|
||||||
new.append(i)
|
|
||||||
removed = set(filter(lambda p: p not in new, current))
|
|
||||||
added = set(filter(lambda p: p not in current, new))
|
|
||||||
update = list(removed | added)
|
|
||||||
if update:
|
|
||||||
for e in Model.objects.filter(id__in=update):
|
|
||||||
e.update_matches(Annotation.objects.filter(pk=a.id))
|
|
||||||
else:
|
|
||||||
# annotation has no value, remove all exisint matches
|
|
||||||
for e in a_matches.all():
|
|
||||||
e.update_matches(Annotation.objects.filter(pk=a.id))
|
|
||||||
|
|
||||||
@task(ignore_results=False, queue='default')
|
@task(ignore_results=False, queue='default')
|
||||||
def add_annotations(data):
|
def add_annotations(data):
|
||||||
|
|
Loading…
Reference in a new issue