# -*- coding: utf-8 -*-
from django import forms
from django.core.validators import RegexValidator
from django.utils.safestring import mark_safe
class SearchForm(forms.Form):
defaults = {
'content_type': 'all',
}
query = forms.CharField(label='Search', required=False)
content_type = forms.ChoiceField(choices=[
('all', 'All'),
('book', 'Books'),
('reference', 'References'),
('intervention', 'Interventions'),
('outwork', 'Outwork'),
], required=False, initial=defaults['content_type'])
class FacetChoiceField(forms.MultipleChoiceField):
# customize multiple choice field for use with facets
# - turn of choice validation (shouldn't fail if facets don't get loaded)
# - default to not required
# - use checkbox select multiple as default widget
widget = forms.CheckboxSelectMultiple
def __init__(self, *args, **kwargs):
if 'required' not in kwargs:
kwargs['required'] = False
super(FacetChoiceField, self).__init__(*args, **kwargs)
def valid_value(self, value):
return True
class RangeWidget(forms.MultiWidget):
# widget separator (regular dash for now; could use en dash?)
sep = '-'
def __init__(self, *args, **kwargs):
widgets = [
forms.NumberInput(),
forms.NumberInput()
]
super(RangeWidget, self).__init__(widgets, *args, **kwargs)
def decompress(self, value):
if value:
return [int(val) for val in value.split(self.sep)]
return [None, None]
class RangeField(forms.MultiValueField):
widget = RangeWidget
def __init__(self, *args, **kwargs):
fields = (
forms.IntegerField(
error_messages={'invalid': 'Enter a number'},
validators=[
RegexValidator(r'^[0-9]*$', 'Enter a valid number.'),
],
required=False
),
forms.IntegerField(
error_messages={'invalid': 'Enter a number'},
validators=[
RegexValidator(r'^[0-9]*$', 'Enter a valid number.'),
],
required=False
),
)
kwargs['fields'] = fields
super(RangeField, self).__init__( #fields=fields,
require_all_fields=False, *args, **kwargs
)
def compress(self, data_list):
return self.widget.sep.join(['%d' % val if val else '' for val in data_list])
class InstanceSearchForm(forms.Form):
defaults = {
'order_by': 'author',
'is_extant': True
# NOTE: restricting here hides a couple of volumes;
# is this a data error or something else?
# 'cited_in': ['De la grammatologie']
}
query = forms.CharField(label='Search', required=False)
is_extant = forms.BooleanField(label="Extant in Derrida's Library",
required=False)
is_annotated = forms.BooleanField(label='Containing annotations',
required=False)
order_by = forms.ChoiceField(choices=[
('author', 'Author'),
('title', 'Title'),
('oldest', 'Publication date: oldest to newest'),
('newest', 'Publication date: newest to oldest'),
], required=False, initial=defaults['order_by'],
widget=forms.RadioSelect)
#: order options and corresponding solr field
sort_fields = {
'author': 'author_isort',
'title': 'display_title_isort',
'oldest': 'year',
'newest': '-year'
}
# solr facet fields
facet_fields = ['author', 'subject', 'item_type', 'pub_place', 'language',
'work_language', 'cited_in']
# input fields that wrap a solr facet
facet_inputs = ['author', 'subject', 'language', 'work_language',
'pub_place', 'cited_in']
author = FacetChoiceField()
subject = FacetChoiceField()
language = FacetChoiceField(label='Language of Publication')
work_language = FacetChoiceField(label='Original Language')
pub_place = FacetChoiceField(label='Place of Publication')
# NOTE: skipping publication type because library is currently
# restricted to books only
# item_type = FacetChoiceField(label='Publication Type')
cited_in = FacetChoiceField()
# range facets
range_facets = ['work_year', 'copyright_year', 'print_year']
work_year = RangeField(label='Original Publication Year',
required=False)
copyright_year = RangeField(label='Edition Year', required=False)
print_year = RangeField(label='Printing Year', required=False)
def set_choices_from_facets(self, facets):
# configure field choices based on facets returned from Solr
if not facets:
return
for facet, counts in facets.items():
if facet in self.fields:
self.fields[facet].choices = [
(val, mark_safe('%s <span>%d</span>' % (val, count)))
for val, count in counts]
def solr_field(self, field):
'''Return corresponding solr field for search facet or order
input for this form.'''
# sort fields
if field in self.sort_fields:
return self.sort_fields[field]
# facets
# (currently all input names match facets)
if field in self.facet_fields:
return field
class ReferenceSearchForm(forms.Form):
defaults = {
'order_by': 'dw_page',
'derridawork': ['De la grammatologie']
}
query = forms.CharField(label='Search', required=False)
order_by = forms.ChoiceField(choices=[
('dw_page', 'Page order in Derrida work'),
('cited_author', 'Author of cited work'),
('cited_title', 'Title of cited work'),
], required=False, initial=defaults['order_by'],
widget=forms.RadioSelect)
#: order options and corresponding solr field
sort_fields = {
'dw_page': 'derridawork_page',
'cited_author': 'instance_author_isort',
'cited_title': 'instance_title_isort',
}
# fields to request facets from solr
facet_fields = ['derridawork', 'reference_type', 'instance_author',
'instance_subject', 'instance_language', 'original_language',
'instance_pub_place']
#'pub_language', 'orig_language']. # range facets TODO
# map solr facet field to corresponding form input
solr_facet_fields = {
'instance_author': 'author',
'instance_subject': 'subject',
'instance_language': 'language',
'instance_pub_place': 'pub_place',
}
# input fields that wrap a solr facet
facet_inputs = ['derridawork', 'reference_type', 'author', 'subject',
'language', 'original_language', 'pub_place']
is_extant = forms.BooleanField(label="Extant in Derrida's Library",
required=False)
is_annotated = forms.BooleanField(label='Containing annotations',
required=False)
corresponding_intervention = forms.BooleanField(label='With corresponding annotation',
required=False)
author = FacetChoiceField(label='Author')
subject = FacetChoiceField(label='Subject')
language = FacetChoiceField(label='Language of Publication')
original_language = FacetChoiceField(label='Original Language')
pub_place = FacetChoiceField(label='Place of Publication')
# TODO: original pub year, edition year, print year
reference_type = FacetChoiceField(label='Reference Type', required=False)
derridawork = FacetChoiceField(label='Cited by Derrida in', required=False)
# range facets
range_facets = ['instance_work_year', 'instance_copyright_year',
'instance_print_year']
instance_work_year = RangeField(label='Original Publication Year',
required=False)
instance_copyright_year = RangeField(label='Edition Year', required=False)
instance_print_year = RangeField(label='Printing Year', required=False)
def set_choices_from_facets(self, facets):
# configure field choices based on facets returned from Solr
# TODO: Generalize this for a sublcass of forms.Form?
for facet, counts in facets.items():
formfield = self.solr_facet_fields.get(facet, facet)
if formfield in self.fields:
self.fields[formfield].choices = [
(val, mark_safe('%s <span>%d</span>' % (val, count)))
for val, count in counts]
def solr_field(self, field):
'''Return corresponding solr field for search facet or order
input for this form.'''
# sort fields
if field in self.sort_fields:
return self.sort_fields[field]
# facets
if field in self.facet_fields:
return field
if field in self.solr_facet_fields.values():
# currently all are instance_field, but generate
# based on the dictionary in case that changes
for key, value in self.solr_facet_fields.items():
if value == field:
return key
class SuppressImageForm(forms.Form):
'''Simple form for admin request to suppress a single
canvas image or all annotated pages from a volume.'''
suppress = forms.ChoiceField(choices=[
('current', 'this page'),
('all', 'all annotated pages in this volume'),
], initial='current', widget=forms.RadioSelect)
canvas_id = forms.CharField(widget=forms.HiddenInput)