Source code for derrida.books.search_indexes

from haystack import indexes
from derrida.books.models import Instance, Reference, DerridaWork
import roman


# Solr index needs to support:
# Browse/search library books cited in DG
# - Display thumbnail, title, author, year and copy
# - Filter by date range, cited/not
# - Sort by author, publication date

[docs]class InstanceIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True, stored=False) #: display title of book; :class:`derrida.books.models.Instance.display_title` display_title = indexes.CharField(model_attr='display_title', faceted=True) #: sortable field for display title display_title_isort = indexes.CharField(model_attr='display_title') #: item type; :class:`derrida.books.models.Instance.item_type` item_type = indexes.CharField(model_attr='item_type', faceted=True) #: copy letter, if any; :class:`derrida.books.models.Instance.copy` copy = indexes.CharField(model_attr='copy', null=True) #: author names in lastname, first for sort/facet; :class:`derrida.books.models.Work.authors` author = indexes.MultiValueField(model_attr='work__authors__authorized_name', faceted=True, null=True) #: non-multifield for first author to allow sorting by author author_isort = indexes.CharField(null=True) #: author in firstname last for display; :class:`derrida.books.models.Work.authors` author_firstname_last = indexes.MultiValueField(model_attr='work__authors__firstname_last', null=True) #: subjects associated with Instance; :class:`derrida.books.models.Work.subjects` subject = indexes.MultiValueField(model_attr='work__subjects__name', faceted=True, null=True) #: languages associated with Instance; :class:`derrida.books.models.Instance.languages` language = indexes.MultiValueField(model_attr='languages__name', faceted=True, null=True) #: place of publication; :class:`derrida.books.models.Instance.pub_place` pub_place = indexes.MultiValueField(model_attr='pub_place__name', faceted=True, null=True) #: original work languages; :class:`derrida.books.models.Work.languages` work_language = indexes.MultiValueField(model_attr='work__languages__name', faceted=True, null=True) #: original work year; :class:`derrida.books.models.Work.year` work_year = indexes.IntegerField(model_attr='work__year', null=True) #: copyright year of Instance; :class:`derrida.books.models.Instance.copyright_year` copyright_year = indexes.IntegerField(model_attr='copyright_year', null=True) #: print year of Instance; :class:`derrida.books.models.Instance.print_year` print_year = indexes.IntegerField(model_attr='print_year', null=True) #: sort/display year: print year if known; otherwise, copyright year. year = indexes.IntegerField(model_attr='year', null=True) #: gives work of Derrida (DerridaWork) in which this Instance is cited cited_in = indexes.MultiValueField(faceted=True, null=True) #: whether the Instance is extant; :class:`derrida.books.models.Instance.is_extant` is_extant = indexes.FacetBooleanField(model_attr='is_extant') #: whether the Instance has annotations by Derrida; :class:`derrida.books.models.Instance.is_annotated` is_annotated = indexes.FacetBooleanField(model_attr='is_annotated') #: whether the Instance is digitized; :class:`derrida.books.models.Instance.digital_edition` digital_edition = indexes.FacetBooleanField(model_attr='digital_edition') #: the instance's url slug; :class:`derrida.books.models.Instance.slug` slug = indexes.CharField(model_attr='slug')
[docs] def get_model(self): return Instance
[docs] def prepare_author_isort(self, instance): '''Return first author for author sort field.''' first_author = instance.work.authors.first() if first_author: return first_author.authorized_name
[docs] def prepare_cited_in(self, instance): '''Return Derridaworks in which this instance is cited.''' # return cited work once only; # check for references to this instance or any book sections # it collects ref_ids = [ref.id for ref in instance.reference_set.all()] ref_ids.extend([ref.id for bksect in instance.collected_set.all() for ref in bksect.reference_set.all()]) # use distinct to avoid needless repetition return [dw.short_title for dw in DerridaWork.objects.filter(reference__in=ref_ids).distinct()]
[docs]class ReferenceIndex(indexes.SearchIndex, indexes.Indexable): '''Search index instance for :class:`derrida.books.models.Reference`''' text = indexes.CharField(document=True, use_template=True, stored=False) #: Short title for search form from :class:`~derrida.books.models.DerridaWork` derridawork = indexes.CharField(model_attr='derridawork__short_title', faceted=True) #: Name value for the :class:`~derrida.books.models.ReferenceType` of citation reference_type = indexes.CharField(model_attr='reference_type__name', faceted=True) #: Page in derrida work; :attr:`derrida.books.models.Reference.derridawork_page` derridawork_page = indexes.IntegerField(model_attr='derridawork_page') #: Page location in derrida work; :attr:`derrida.books.models.Reference.derridawork_pageloc` derridawork_pageloc = indexes.CharField(model_attr='derridawork_pageloc') #: derrida work slug in derrida work; :attr:`derrida.books.models.DerridaWork.slug` derridawork_slug = indexes.CharField(model_attr='derridawork__slug') #: Cited page in referenced work; :attr:`derrida.books.models.Reference.book_page` book_page = indexes.CharField(model_attr='book_page', null=True, faceted=True) #: sort field for reference work page to sort page numbers correctly book_page_sort = indexes.IntegerField() #: anchor text anchor_text = indexes.CharField(model_attr='anchor_text', null=True) #: ids for corresponding intervention interventions = indexes.MultiValueField(model_attr='interventions__id') #: has corresponding intervention corresponding_intervention = indexes.FacetBooleanField() #: canvas id for detail page view, if view available for book page page_canvas_id = indexes.CharField(null=True) # - related instance and work info #: Title of instance to which citation points; :meth:`derrida.books.models.Instance.display_title` instance_title = indexes.CharField(model_attr='instance__display_title', faceted=True) instance_title_isort = indexes.CharField(model_attr='instance__display_title') #: Instance authors for faceted filtering instance_author = indexes.MultiValueField(model_attr='instance__work__authors__authorized_name', faceted=True, null=True) #: Instance authors for display instance_author_firstname_last = indexes.MultiValueField(model_attr='instance__work__authors__firstname_last', null=True) #: non-multifield for instance first author to allow sorting by author instance_author_isort = indexes.CharField(model_attr='instance__work__authors__authorized_name', null=True) #: subjects for associated instance; :attr:`derrida.books.models.Instance.subjects` instance_subject = indexes.MultiValueField(model_attr='instance__work__subjects__name', faceted=True, null=True) #: languages for associated instance; :attr:`derrida.book.models.Instance.languages` instance_language = indexes.MultiValueField(faceted=True, null=True) #: languages for the original work; :attr:`derrida.book.models.Work.languages` original_language = indexes.MultiValueField(model_attr='instance__work__languages__name', faceted=True) instance_pub_place = indexes.MultiValueField(model_attr='book__pub_place__name', faceted=True, null=True) #: work year of the associated instance's work; :attr:`derrida.books.models.Work.year` instance_work_year = indexes.IntegerField(model_attr='instance__work__year', null=True) #: copyright year of associated instance; :attr:`derrida.books.models.Instance.copyright_year` instance_copyright_year = indexes.IntegerField(model_attr='instance__copyright_year', null=True) #: print year of associated instance; :attr:`derrida.books.models.Instance.r_year` instance_print_year = indexes.IntegerField(model_attr='instance__print_year', null=True) #: is instance extant in PU collection?; :attr:`derrida.books.models.Instance.is_extant` instance_is_extant = indexes.FacetBooleanField(model_attr='book__is_extant') #: is instance annotated?; :attr:`derrida.books.models.Instance.is_annotated` instance_is_annotated = indexes.FacetBooleanField(model_attr='book__is_annotated') #: instance slug, for generating urls and filtering by instance instance_slug = indexes.CharField(model_attr='book__slug') #: instance copy, for distinguishing multiple copies of the same edition instance_copy = indexes.CharField(model_attr='book__copy', null=True) #: boolean indicating if instance has digital edition instance_digital_edition = indexes.FacetBooleanField(model_attr='book__digital_edition') #: instance collection title, for references to book sections instance_collection_title = indexes.CharField(model_attr='instance__collected_in__display_title', null=True)
[docs] def get_model(self): return Reference
[docs] def prepare_instance_author_isort(self, reference): '''Return first author for author sort field.''' first_author = reference.instance.work.authors.first() if first_author: return first_author.authorized_name
[docs] def prepare_corresponding_intervention(self, reference): ''' Return whether :class:`derrida.books.models.Reference` has a corresponding :class:`derrida.interventions.models.Intervention`. ''' return bool(reference.interventions.count())
[docs] def prepare_page_canvas_id(self, reference): ''' Return canvas short_id for first associated :class:`derrida.interventions.models.Intervention`. ''' if reference.interventions.exists(): # don't error on intervention without canvas # (probably only exists in test data) if reference.interventions.first().canvas: return reference.interventions.first().canvas.short_id
[docs] def prepare_instance_language(self, reference): ''' Return language of :class:`derrida.books.models.Reference`'s associated :class:`derrida.books.models.Instannce`. ''' # use languages directly on this instance, if available (even if a # book section or article) if reference.instance.languages.exists(): return [lang.name for lang in reference.instance.languages.all()] # if no languages directly set and part of a collected work, use # collection work languages if reference.instance.collected_in: return [lang.name for lang in reference.instance.collected_in.languages.all()]
[docs] def prepare_book_page_sort(self, reference): ''' Handle integer values and sort in page references, as well as Roman numerals from introductions. ''' # if empty immediately return 0 for no sort if not reference.book_page: return 0 book_page = reference.book_page.lower() # ignore any back references to derridawork citation, e.g. (256a) book_page = book_page.split(')')[-1] # split on '-' if it exists; just get first page of page range book_page = book_page.split('-')[0] # strip any trailing p or s book_page = book_page.strip('ps') # try converting to integer - should work in most cases try: return int(book_page) except ValueError: pass # if that fails, check for a roman numeral try: # return a negative number so front matter pages (up to 500) # will sort before pages with regular numbers. return roman.fromRoman(book_page.upper()) - 500 except roman.InvalidRomanNumeralError: pass # if no conversion succeeded, return zero return 0