Some dictionary filtering features.
[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 Note(models.Model):
16     """Represents a single annotation from a book."""
17     html = models.TextField()
18     sort_key = models.CharField(max_length=128, db_index=True)
19     fn_type = models.CharField(max_length=10, db_index=True)
20     qualifier = models.CharField(max_length=128, db_index=True, blank=True)
21     language = models.CharField(max_length=10, db_index=True)
22
23     class Meta:
24         ordering = ['sort_key']
25
26
27 class NoteSource(models.Model):
28     """Represents a single annotation from a book."""
29     note = models.ForeignKey(Note)
30     book = models.ForeignKey(Book)
31     anchor = models.CharField(max_length=64)
32
33     class Meta:
34         ordering = ['book']
35
36
37 @task(ignore_result=True)
38 def build_notes(book):
39     task_logger.info(book.slug)
40     with transaction.atomic():
41         book.notesource_set.all().delete()
42         if book.html_file:
43             from librarian import html
44             for anchor, fn_type, qualifier, text_str, html_str in \
45                     html.extract_annotations(book.html_file.path):
46                 sort_key = sortify(text_str).strip()[:128]
47                 qualifier = (qualifier or '')[:128]
48                 language = book.language
49                 note = None
50                 notes = Note.objects.filter(sort_key=sort_key,
51                     qualifier=qualifier, fn_type=fn_type,
52                     language=language, html=html_str)
53                 if notes:
54                     note = notes[0]
55                 else:
56                     note = Note.objects.create(
57                         sort_key=sort_key,
58                         qualifier=qualifier,
59                         html=html_str,
60                         fn_type=fn_type,
61                         language=language
62                         )
63                 note.notesource_set.create(book=book, anchor=anchor)
64
65         Note.objects.filter(notesource=None).delete()
66
67
68 def notes_from_book(sender, instance, **kwargs):
69     build_notes.delay(instance)
70 Book.html_built.connect(notes_from_book)