Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added initial Haystack integration.

I'm using a throwaway object (Document) since it's the path of least resistance
to getting search working. The basic idea I'm following here is the one Eric
Holscher developed for Read The Docs -- see
http://ericholscher.com/blog/2010/nov/17/using-haystack-index-non-database-content/.
  • Loading branch information...
commit aaa0a6ed1abcb5688c4ecd24cc502441d46357df 1 parent 65e227a
Jacob Kaplan-Moss authored February 01, 2011
1  deploy-requirements.txt
@@ -2,6 +2,7 @@
2 2
 
3 3
 akismet == 0.2.0
4 4
 Django >= 1.2, < 1.3
  5
+django-haystack == 1.1.0
5 6
 django-registration == 0.7
6 7
 docutils >= 0.6, < 0.7
7 8
 FeedParser >= 4.1, < 5.0
41  django_website/docs/migrations/0001_initial.py
... ...
@@ -0,0 +1,41 @@
  1
+# encoding: utf-8
  2
+import datetime
  3
+from south.db import db
  4
+from south.v2 import SchemaMigration
  5
+from django.db import models
  6
+
  7
+class Migration(SchemaMigration):
  8
+
  9
+    def forwards(self, orm):
  10
+        
  11
+        # Adding model 'DocumentRelease'
  12
+        db.create_table('docs_documentrelease', (
  13
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
  14
+            ('lang', self.gf('django.db.models.fields.CharField')(default='en', max_length=2)),
  15
+            ('version', self.gf('django.db.models.fields.CharField')(max_length=20)),
  16
+            ('scm', self.gf('django.db.models.fields.CharField')(max_length=10)),
  17
+            ('scm_url', self.gf('django.db.models.fields.URLField')(max_length=200)),
  18
+            ('is_default', self.gf('django.db.models.fields.BooleanField')(default=False)),
  19
+        ))
  20
+        db.send_create_signal('docs', ['DocumentRelease'])
  21
+
  22
+
  23
+    def backwards(self, orm):
  24
+        
  25
+        # Deleting model 'DocumentRelease'
  26
+        db.delete_table('docs_documentrelease')
  27
+
  28
+
  29
+    models = {
  30
+        'docs.documentrelease': {
  31
+            'Meta': {'object_name': 'DocumentRelease'},
  32
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  33
+            'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  34
+            'lang': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
  35
+            'scm': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
  36
+            'scm_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
  37
+            'version': ('django.db.models.fields.CharField', [], {'max_length': '20'})
  38
+        }
  39
+    }
  40
+
  41
+    complete_apps = ['docs']
48  django_website/docs/migrations/0002_add_document_model.py
... ...
@@ -0,0 +1,48 @@
  1
+# encoding: utf-8
  2
+import datetime
  3
+from south.db import db
  4
+from south.v2 import SchemaMigration
  5
+from django.db import models
  6
+
  7
+class Migration(SchemaMigration):
  8
+
  9
+    def forwards(self, orm):
  10
+        
  11
+        # Adding model 'Document'
  12
+        db.create_table('docs_document', (
  13
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
  14
+            ('release', self.gf('django.db.models.fields.related.ForeignKey')(related_name='documents', to=orm['docs.DocumentRelease'])),
  15
+            ('path', self.gf('django.db.models.fields.CharField')(max_length=500)),
  16
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=500)),
  17
+            ('content', self.gf('django.db.models.fields.TextField')()),
  18
+        ))
  19
+        db.send_create_signal('docs', ['Document'])
  20
+
  21
+
  22
+    def backwards(self, orm):
  23
+        
  24
+        # Deleting model 'Document'
  25
+        db.delete_table('docs_document')
  26
+
  27
+
  28
+    models = {
  29
+        'docs.document': {
  30
+            'Meta': {'object_name': 'Document'},
  31
+            'content': ('django.db.models.fields.TextField', [], {}),
  32
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  33
+            'path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
  34
+            'release': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': "orm['docs.DocumentRelease']"}),
  35
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '500'})
  36
+        },
  37
+        'docs.documentrelease': {
  38
+            'Meta': {'object_name': 'DocumentRelease'},
  39
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  40
+            'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  41
+            'lang': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
  42
+            'scm': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
  43
+            'scm_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
  44
+            'version': ('django.db.models.fields.CharField', [], {'max_length': '20'})
  45
+        }
  46
+    }
  47
+
  48
+    complete_apps = ['docs']
0  django_website/docs/migrations/__init__.py
No changes.
19  django_website/docs/models.py
@@ -35,3 +35,22 @@ def save(self, *args, **kwargs):
35 35
             DocumentRelease.objects.update(is_default=False)
36 36
         super(DocumentRelease, self).save(*args, **kwargs)
37 37
     
  38
+class Document(models.Model):
  39
+    """
  40
+    An individual document. Used mainly as a hook point for Haystack.
  41
+    """
  42
+    release = models.ForeignKey(DocumentRelease, related_name='documents')
  43
+    path = models.CharField(max_length=500)
  44
+    title = models.TextField(max_length=500)
  45
+    content = models.TextField()
  46
+
  47
+    def __unicode__(self):
  48
+        return "/".join([self.release.lang, self.release.version, self.path])
  49
+
  50
+    @models.permalink
  51
+    def get_absolute_url(self):
  52
+        return (
  53
+            'document-detail',
  54
+            [],
  55
+            {'lang': self.lang, 'version': self.version, 'url': self.path}
  56
+        )
25  django_website/docs/search_indexes.py
... ...
@@ -0,0 +1,25 @@
  1
+import json
  2
+from django.conf import settings
  3
+import haystack
  4
+import haystack.indexes
  5
+from . import utils
  6
+from .models import Document
  7
+
  8
+class DocumentIndex(haystack.indexes.SearchIndex):
  9
+	text = haystack.indexes.CharField(document=True)
  10
+	lang = haystack.indexes.CharField(model_attr='release__lang', faceted=True)
  11
+	version = haystack.indexes.CharField(model_attr='release__version', faceted=True)
  12
+	path = haystack.indexes.CharField(model_attr='path')
  13
+	title = haystack.indexes.CharField(model_attr='title')
  14
+
  15
+	def get_queryset(self):
  16
+		return Document.objects.all().select_related('release')
  17
+
  18
+	def prepare_text(self, obj):
  19
+		root = utils.get_doc_root(obj.release.lang, obj.release.version)
  20
+		docpath = utils.get_doc_path(root, obj.path)
  21
+		with open(docpath) as fp:
  22
+			doc = json.load(fp)
  23
+		return doc['body']
  24
+
  25
+haystack.site.register(Document, DocumentIndex)
1  django_website/docs/search_sites.py
... ...
@@ -0,0 +1 @@
  1
+import haystack; haystack.autodiscover()
14  django_website/settings/docs.py
@@ -2,7 +2,10 @@
2 2
 
3 3
 PREPEND_WWW = False
4 4
 APPEND_SLASH = True
5  
-INSTALLED_APPS = ['django_website.docs']
  5
+INSTALLED_APPS = [
  6
+	'django_website.docs',
  7
+	'haystack',
  8
+]
6 9
 TEMPLATE_CONTEXT_PROCESSORS += ["django.core.context_processors.request"]
7 10
 ROOT_URLCONF = 'django_website.urls.docs'
8 11
 CACHE_MIDDLEWARE_KEY_PREFIX = 'djangodocs'
@@ -12,3 +15,12 @@
12 15
     DOCS_BUILD_ROOT = BASE.ancestor(2).child('docbuilds')
13 16
 else:
14 17
     DOCS_BUILD_ROOT = '/tmp/djangodocs'
  18
+
  19
+# Haystack settings
  20
+HAYSTACK_SITECONF = 'django_website.docs.search_sites'
  21
+if PRODUCTION:
  22
+	HAYSTACK_SEARCH_ENGINE = 'solr'
  23
+	HAYSTACK_SOLR_URL = 'http://127.0.0.1:8983/solr'
  24
+else:
  25
+	HAYSTACK_SEARCH_ENGINE = 'whoosh'
  26
+	HAYSTACK_WHOOSH_PATH = '/tmp/djangodocs.index'

0 notes on commit aaa0a6e

Please sign in to comment.
Something went wrong with that request. Please try again.