Fix for unclickable cites in admin.
[wolnelektury.git] / apps / dictionary / models.py
1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 #
5 from django.db import models, transaction
6 from celery.task import task
7 from sortify import sortify
8 from celery.utils.log import get_task_logger
9
10 task_logger = get_task_logger(__name__)
11
12 from catalogue.models import Book
13
14
15 class Qualifier(models.Model):
16     qualifier = models.CharField(max_length=128, db_index=True, unique=True)
17     name = models.CharField(max_length=255)
18
19     class Meta:
20         ordering = ['qualifier']
21
22     def __unicode__(self):
23         return self.name or self.qualifier
24
25
26 class Note(models.Model):
27     """Represents a single annotation from a book."""
28     html = models.TextField()
29     sort_key = models.CharField(max_length=128, db_index=True)
30     fn_type = models.CharField(max_length=10, db_index=True)
31     qualifiers = models.ManyToManyField(Qualifier, null=True)
32     language = models.CharField(max_length=10, db_index=True)
33
34     class Meta:
35         ordering = ['sort_key']
36
37
38 class NoteSource(models.Model):
39     """Represents a single annotation from a book."""
40     note = models.ForeignKey(Note)
41     book = models.ForeignKey(Book)
42     anchor = models.CharField(max_length=64)
43
44     class Meta:
45         ordering = ['book']
46
47
48 @task(ignore_result=True)
49 def build_notes(book):
50     task_logger.info(book.slug)
51     with transaction.atomic():
52         book.notesource_set.all().delete()
53         if book.html_file:
54             from librarian import html
55             from librarian.fn_qualifiers import FN_QUALIFIERS
56
57             for anchor, fn_type, qualifiers, text_str, html_str in \
58                     html.extract_annotations(book.html_file.path):
59                 sort_key = sortify(text_str).strip()[:128]
60
61                 language = book.language
62                 note = None
63                 notes = Note.objects.filter(sort_key=sort_key,
64                     fn_type=fn_type,
65                     language=language, html=html_str)
66                 if notes:
67                     note = notes[0]
68                 else:
69                     note = Note.objects.create(
70                         sort_key=sort_key,
71                         html=html_str,
72                         fn_type=fn_type,
73                         language=language
74                         )
75
76                 qualifier_objects = []
77                 for qualifier in qualifiers:
78                     obj, created = Qualifier.objects.get_or_create(
79                         qualifier=qualifier, defaults={
80                             'name': FN_QUALIFIERS.get(qualifier, '')
81                         })
82                     qualifier_objects.append(obj)
83                 note.qualifiers = qualifier_objects
84                 note.notesource_set.create(book=book, anchor=anchor)
85
86         Note.objects.filter(notesource=None).delete()
87
88
89 def notes_from_book(sender, instance, **kwargs):
90     build_notes.delay(instance)
91 Book.html_built.connect(notes_from_book)