Permalink
Browse files

add base of search view

  • Loading branch information...
1 parent 3bb1c13 commit ea5e74fd55393e5be35aa9166314eb2165de3637 unknown committed Jul 7, 2010
@@ -0,0 +1,28 @@
+import os
+import subprocess
+from django.core.management.base import BaseCommand, CommandError
+from django.conf import settings
+from django.core.management import call_command
+
+SOLR_ROOT = settings.SOLR_ROOT
+
+class Command(BaseCommand):
+ def handle(self, **options):
+ # Make sure the `SOLR_ROOT` and `start.jar` exist.
+ if not SOLR_ROOT:
+ raise CommandError("SOLR_ROOT is not specified")
+ start_jar_path = os.path.join(SOLR_ROOT, 'start.jar')
+ if not os.path.exists(start_jar_path):
+ raise CommandError("No Solr start.jar found at %s" % start_jar_path)
+
+ # Start Solr subprocess
+ print "Updating schema.xml"
+ call_command('solr_schema')
+ print "Starting Solr process. CTL-C to exit."
+ os.chdir(SOLR_ROOT)
+ try:
+ subprocess.call(["java", "-jar", "start.jar"])
+ except KeyboardInterrupt:
+ # Throws nasty errors if we don't catch the keyboard interrupt.
+ pass
+ print "Solr process has been interrupted"
@@ -0,0 +1,37 @@
+import sys, os
+from django.core.management.base import NoArgsCommand
+from django.template import loader, Context
+from django.conf import settings
+from haystack.constants import DEFAULT_OPERATOR
+
+SOLR_ROOT = settings.SOLR_ROOT
+
+
+class Command(NoArgsCommand):
+ help = "Generates a Solr schema and applies to SOLR_ROOT instance of solr."
+
+ def handle_noargs(self, **options):
+ """Generates a Solr schema that reflects the indexes."""
+ # Cause the default site to load.
+ from django.conf import settings
+ from haystack import backend, site
+
+ default_operator = getattr(settings, 'HAYSTACK_DEFAULT_OPERATOR', DEFAULT_OPERATOR)
+ content_field_name, fields = backend.SearchBackend().build_schema(site.all_searchfields())
+
+ t = loader.get_template('search/configuration/solr.xml')
+ c = Context({
+ 'content_field_name': content_field_name,
+ 'fields': fields,
+ 'default_operator': default_operator,
+ })
+ schema_xml = t.render(c)
+ schema_path = os.path.join(SOLR_ROOT, 'solr/conf/schema.xml')
+ file = open(schema_path, 'w')
+ file.write(schema_xml)
+ file.close()
+ sys.stderr.write("\n")
+ sys.stderr.write("Saved to %s\n" % schema_path)
+ sys.stderr.write("You may need to reindex your data\n")
+ sys.stderr.write("--------------------------------------------------------------------------------------------\n")
+ sys.stderr.write("\n")
@@ -0,0 +1,28 @@
+from haystack.indexes import *
+from haystack import site
+from models import Video, TranslationLanguage
+
+class VideoIndex(SearchIndex):
+ text = CharField(document=True, use_template=True)
+ title = CharField()
+ language = CharField()
+
+ def prepare(self, obj):
+ self.prepared_data = super(VideoIndex, self).prepare(obj)
+ self.prepared_data['title'] = obj.__unicode__()
+ self.prepared_data['language'] = 'Original'
+ return self.prepared_data
+
+class TranslationLanguageIndex(SearchIndex):
+ text = CharField(document=True, use_template=True)
+ title = CharField()
+ language = CharField()
+
+ def prepare(self, obj):
+ self.prepared_data = super(TranslationLanguageIndex, self).prepare(obj)
+ self.prepared_data['title'] = obj.video.__unicode__()
+ self.prepared_data['language'] = obj.get_language_display()
+ return self.prepared_data
+
+site.register(Video, VideoIndex)
+site.register(TranslationLanguage, TranslationLanguageIndex)
@@ -112,19 +112,23 @@ def ordered_paginator(context, adjacent_pages=2):
@register.tag
def ordered_column(parser, token):
try:
- tag_name, field_name, title = token.split_contents()
+ tokens = token.split_contents()
+ field_name = tokens[1]
+ title = tokens[2]
+ get_params = tokens[3:]
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
- return OrderedColumnNode(field_name[1:-1], title[1:-1])
+ return OrderedColumnNode(field_name[1:-1], title[1:-1], get_params)
class OrderedColumnNode(template.Node):
- def __init__(self, field_name, title):
+ def __init__(self, field_name, title, get_params):
self.field_name = field_name
self.title = title
self.page = template.Variable('page')
self.order_type = template.Variable('order_type')
self.ordering = template.Variable('ordering')
+ self.get_params = get_params
def render(self, context):
if context.has_key(self.page.var):
@@ -141,10 +145,18 @@ def render(self, context):
order_type = self.order_type.resolve(context)
else:
order_type = None
+
+ extra_params = []
+ for item in self.get_params:
+ items = item.split('=')
+ variable = template.Variable(items[1])
+ extra_params.append('&%s=%s' % (items[0], variable.resolve(context)))
+
+ extra_params = ''.join(extra_params)
ot = (ordering == self.field_name and order_type == 'asc') and 'desc' or 'asc'
if page:
- link = '?o=%s&ot=%s&page=%s' % (self.field_name, ot, page)
+ link = '?o=%s&ot=%s&page=%s%s' % (self.field_name, ot, page, extra_params)
else:
- link = '?o=%s&ot=%s' % (self.field_name, ot)
+ link = '?o=%s&ot=%s%s' % (self.field_name, ot, extra_params)
return '<a href="%s">%s</a>' % (link, self.title)
View
@@ -32,6 +32,7 @@
from django.contrib import messages
from django.db.models import Q
from widget.views import base_widget_params
+from haystack.query import SearchQuerySet
def create(request):
if request.method == 'POST':
@@ -369,21 +370,24 @@ def test_form_page(request):
def search(request):
q = request.REQUEST.get('q')
-
+ print q
try:
page = int(request.GET['page'])
except (ValueError, TypeError, KeyError):
page = 1
if q:
- qs = TranslationLanguage.objects.filter(Q(video__video_url__icontains=q)|Q(video__youtube_name__icontains=q))
+ qs = SearchQuerySet().auto_query(q).highlight()
else:
qs = TranslationLanguage.objects.none()
- context = {}
+ context = {
+ 'query': q
+ }
ordering, order_type = request.GET.get('o'), request.GET.get('ot')
order_fields = {
- 'name': 'video__youtube_name'
+ 'title': 'title',
+ 'language': 'language'
}
if ordering in order_fields and order_type in ['asc', 'desc']:
qs = qs.order_by(('-' if order_type == 'desc' else '')+order_fields[ordering])
@@ -18,3 +18,5 @@ vendor/python-openid-2.2.5.tar.gz
vendor/python-yadis-1.1.0.tar.gz
simplejson==2.1.1
-e hg+http://sorl-thumbnail.googlecode.com/hg/@caf69b5206329d89282b4b8246a72e5aa77cb578#egg=sorl_thumbnail-tip
+django-haystack==1.0
+pysolr
View
@@ -0,0 +1,2 @@
+import haystack
+haystack.autodiscover()
View
@@ -197,9 +197,17 @@ def rel(*x):
'sorl.thumbnail',
'videos',
'widget',
- 'south'
+ 'south',
+ 'haystack',
)
+#Haystack configuration
+HAYSTACK_SITECONF = 'search_site'
+HAYSTACK_SEARCH_ENGINE = 'solr'
+HAYSTACK_SOLR_URL = 'http://127.0.0.1:8983/solr'
+HAYSTACK_SEARCH_RESULTS_PER_PAGE = 20
+SOLR_ROOT = rel('..', 'buildout', 'parts', 'solr', 'example')
+
# socialauth-related
OPENID_REDIRECT_NEXT = '/socialauth/openid/done/'
@@ -0,0 +1,102 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<schema name="default" version="1.1">
+ <types>
+ <fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
+
+ <!-- Numeric field types that manipulate the value into
+ a string value that isn't human-readable in its internal form,
+ but with a lexicographic ordering the same as the numeric ordering,
+ so that range queries work correctly. -->
+ <fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
+
+ <fieldType name="date" class="solr.DateField" sortMissingLast="true" omitNorms="true"/>
+
+ <fieldType name="text" class="solr.TextField" positionIncrementGap="100">
+ <analyzer type="index">
+ <tokenizer class="solr.NGramTokenizerFactory" minGramSize="3" maxGramSize="15" />
+ <!-- <tokenizer class="solr.WhitespaceTokenizerFactory"/> -->
+ <!-- in this example, we will only use synonyms at query time
+ <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+ -->
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+ <filter class="solr.LowerCaseFilterFactory"/>
+ <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+ </analyzer>
+ <analyzer type="query">
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+ <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/>
+ <filter class="solr.LowerCaseFilterFactory"/>
+ <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+ </analyzer>
+ </fieldType>
+
+ <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+ <analyzer>
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+ </analyzer>
+ </fieldType>
+ </types>
+
+ <fields>
+ <!-- general -->
+ <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
+ <field name="type" type="string" indexed="true" stored="true" multiValued="false" />
+ <field name="name" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <dynamicField name="*_i" type="sint" indexed="true" stored="true"/>
+ <dynamicField name="*_s" type="string" indexed="true" stored="true"/>
+ <dynamicField name="*_l" type="slong" indexed="true" stored="true"/>
+ <dynamicField name="*_t" type="text" indexed="true" stored="true"/>
+ <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
+ <dynamicField name="*_f" type="sfloat" indexed="true" stored="true"/>
+ <dynamicField name="*_d" type="sdouble" indexed="true" stored="true"/>
+ <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
+
+ <field name="django_ct" type="string" indexed="true" stored="true" multiValued="false" />
+ <field name="django_id" type="string" indexed="true" stored="true" multiValued="false" />
+
+{% for field in fields %}
+ {% if field.field_name == "title" or field.field_name == "language" %}
+ <field name="{{ field.field_name }}" type="string" indexed="{{ field.indexed }}" stored="true" multiValued="{{ field.multi_valued }}" />
+ {% else %}
+ <field name="{{ field.field_name }}" type="{{ field.type }}" indexed="{{ field.indexed }}" stored="true" multiValued="{{ field.multi_valued }}" />
+ {% endif %}
+{% endfor %}
+ </fields>
+
+ <!-- field to use to determine and enforce document uniqueness. -->
+ <uniqueKey>id</uniqueKey>
+
+ <!-- field for the QueryParser to use when an explicit fieldname is absent -->
+ <defaultSearchField>{{ content_field_name }}</defaultSearchField>
+
+ <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
+ <solrQueryParser defaultOperator="{{ default_operator }}" />
+</schema>
+
@@ -0,0 +1,4 @@
+{{ object.get_language_display }}
+{% for item in object.translations.translation_set.all %}
+ {{ item.translation_text }}
+{% endfor %}
@@ -0,0 +1,4 @@
+{{ object }}
+{% for item in object.captions.videocaption_set.all %}
+ {{ item.caption_text }}
+{% endfor %}
@@ -12,10 +12,10 @@
<div class="left_column">
<ul class="table_head">
<li class="table_most_recent">
- {% ordered_column "name" "URL/title" %}
+ {% ordered_column "title" "URL/title" q=query %}
</li>
<li class="table_user">
- Language
+ {% ordered_column "language" "Language" q=query %}
</li>
</ul>
@@ -24,10 +24,10 @@
<li {% cycle 'class="even"' '' %}>
<ul>
<li class="table_most_recent">
- {{ item.video }}
+ {{ item.title }}
</li>
<li class="table_user">
- {{ item.get_language_display }}
+ {{ item.language }}
</li>
</ul>
</li>

0 comments on commit ea5e74f

Please sign in to comment.