X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/08f83172c482208d35cd75c704cebd1d70a73af2..531ad4bc4cab82f8c5dc3569c3835328df892a83:/apps/catalogue/models/book.py diff --git a/apps/catalogue/models/book.py b/apps/catalogue/models/book.py index cdafedff9..d3df67e6f 100644 --- a/apps/catalogue/models/book.py +++ b/apps/catalogue/models/book.py @@ -269,20 +269,20 @@ class Book(models.Model): paths = map(lambda bm: (None, bm.file.path), bm) return create_zip(paths, "%s_%s" % (self.slug, format_)) - def search_index(self, book_info=None, reuse_index=False, index_tags=True): + def search_index(self, book_info=None, index=None, index_tags=True, commit=True): import search - if reuse_index: - idx = search.ReusableIndex() - else: - idx = search.Index() - - idx.open() + if index is None: + index = search.Index() try: - idx.index_book(self, book_info) + index.index_book(self, book_info) if index_tags: idx.index_tags() - finally: - idx.close() + if commit: + index.index.commit() + except Exception, e: + index.index.rollback() + raise e + @classmethod def from_xml_file(cls, xml_file, **kwargs): @@ -303,7 +303,7 @@ class Book(models.Model): @classmethod def from_text_and_meta(cls, raw_file, book_info, overwrite=False, build_epub=True, build_txt=True, build_pdf=True, build_mobi=True, build_fb2=True, - search_index=True, search_index_tags=True, search_index_reuse=False): + search_index=True, search_index_tags=True): # check for parts before we do anything children = [] @@ -344,12 +344,17 @@ class Book(models.Model): book.tags = set(meta_tags + book_shelves) - book_tag = book.book_tag() - + obsolete_children = set(b for b in book.children.all() if b not in children) for n, child_book in enumerate(children): child_book.parent = book child_book.parent_number = n child_book.save() + # Disown unfaithful children and let them cope on their own. + for child in obsolete_children: + child.parent = None + child.parent_number = 0 + child.save() + tasks.fix_tree_tags.delay(child) # Save XML and HTML files book.xml_file.save('%s.xml' % book.slug, raw_file, save=False) @@ -376,31 +381,49 @@ class Book(models.Model): book.build_fb2() if not settings.NO_SEARCH_INDEX and search_index: - book.search_index(index_tags=search_index_tags, reuse_index=search_index_reuse) - #index_book.delay(book.id, book_info) - - book_descendants = list(book.children.all()) - descendants_tags = set() - # add l-tag to descendants and their fragments - while len(book_descendants) > 0: - child_book = book_descendants.pop(0) - descendants_tags.update(child_book.tags) - child_book.tags = list(child_book.tags) + [book_tag] - child_book.save() - for fragment in child_book.fragments.all().iterator(): - fragment.tags = set(list(fragment.tags) + [book_tag]) - book_descendants += list(child_book.children.all()) - - for tag in descendants_tags: - tasks.touch_tag(tag) - - # refresh cache - book.reset_tag_counter() - book.reset_theme_counter() + tasks.index_book.delay(book.id, book_info=book_info, index_tags=search_index_tags) + tasks.fix_tree_tags.delay(book) cls.published.send(sender=book) return book + def fix_tree_tags(self): + """Fixes the l-tags on the book's subtree. + + Makes sure that: + * the book has its parents book-tags, + * its fragments have the book's and its parents book-tags, + * runs those for every child book too, + * touches all relevant tags, + * resets tag and theme counter on the book and its ancestry. + """ + def fix_subtree(book, parent_tags): + affected_tags = set(book.tags) + book.tags = list(book.tags.exclude(category='book')) + parent_tags + sub_parent_tags = parent_tags + [book.book_tag()] + for frag in book.fragments.all(): + affected_tags.update(frag.tags) + frag.tags = list(frag.tags.exclude(category='book')) + sub_parent_tags + for child in book.children.all(): + affected_tags.update(fix_subtree(child, sub_parent_tags)) + return affected_tags + + parent_tags = [] + parent = self.parent + while parent is not None: + parent_tags.append(parent.book_tag()) + parent = parent.parent + + affected_tags = fix_subtree(self, parent_tags) + for tag in affected_tags: + tasks.touch_tag(tag) + + book = self + while book is not None: + book.reset_tag_counter() + book.reset_theme_counter() + book = book.parent + def related_info(self): """Keeps info about related objects (tags, media) in cache field.""" if self._related_info is not None: