Skip to content

Commit 918cec8

Browse files
committed
Merge branch 'search'
2 parents b7cb390 + 0517aa6 commit 918cec8

File tree

27 files changed

+315
-32
lines changed

27 files changed

+315
-32
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""
2+
Haystack indexes definitions to make models from application {application_name} searchable.
3+
4+
See Haystack documentation for information to write these indexes: http://docs.haystacksearch.org/dev/searchindex_api.html
5+
"""
6+
7+
from haystack import indexes
8+
9+
from {package_name}.models import {class_name}
10+
11+
class {class_name}Index(indexes.RealTimeSearchIndex, indexes.Indexable):
12+
text = indexes.CharField(document=True, model_attr='message')
13+
14+
# The following is necessary so that djity search engine shall be able to narrow results by projects and according to users roles.
15+
project = indexes.IntegerField(model_attr='project__id')
16+
status = indexes.MultiValueField()
17+
18+
def prepare_status(self,obj):
19+
return range(obj.status+1)
20+
21+
22+
def get_model(self):
23+
return {class_name}
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{{% load highlight %}}
2+
3+
<a href="{{{{ result_url }}}}">{{{{ result.object.name }}}}</a><br>
4+
{{% highlight result.text with query %}}
5+
6+

djity/project/urls.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from djity.simplepage.urls import urlpatterns as simplepage_urls
55
from djity.style.urls import urlpatterns as css_urls
6+
from djity.search.urls import urlpatterns as search_urls
67
from djity.utils import djity_modules
78

89
from django.utils.importlib import import_module
@@ -16,14 +17,16 @@
1617
url(r'^forbidden/*$','djity.project.views.forbidden',name='forbidden'),
1718
)
1819

19-
2020
urlpatterns = patterns('',
2121
# project page redirect to the first tab
2222
url(r'^(?P<project_name>[-\w]+)/*$','djity.project.views.first_tab',name='first_tab'),
23-
# login view as a pseudo application
23+
# login and navigation views as a pseudo applications
2424
(r'^(?P<project_name>[-\w]+)/',include(portal_urls)),
25-
# all other urls are handled by djity.modules.simple_page
25+
# css as a pseudo application too
2626
(r'^(?P<project_name>[-\w]+)/css/',include(css_urls)),
27+
# and search also
28+
(r'^(?P<project_name>[-\w]+)/search/',include(search_urls)),
29+
2730
)
2831

2932
#import urls from djity applications

djity/project_skeleton/local_settings.py_tmpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ DEBUG = {develop!r}
3232
TEMPLATE_DEBUG = DEBUG
3333
DEBUG_TOOLBAR = DEBUG
3434

35+
DEBUG_TOOLBAR_CONFIG = {{}}
36+
DEBUG_TOOLBAR_CONFIG["INTERCEPT_REDIRECTS"] = False
37+
3538
if DEBUG :
3639
LOG_LEVEL = 'DEBUG'
3740
else:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import haystack
2+
haystack.autodiscover()

djity/project_skeleton/settings.py_tmpl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ INSTALLED_APPS = [
111111
'dajaxice',
112112
'dajax',
113113

114+
# Haystack for search
115+
'haystack',
116+
114117
#Djity Core
115118
'djity',
116119
'djity.portlet',
@@ -119,6 +122,7 @@ INSTALLED_APPS = [
119122
'djity.project',
120123
'djity.simplepage',
121124
'djity.transmeta',
125+
'djity.search',
122126
]
123127

124128
###########################################
@@ -158,6 +162,15 @@ STATUS_PERMISSIONS = {{
158162
# list of permissions to check when updating djity's context
159163
PERMISSIONS = ['view','edit','upload','manage']
160164

165+
# List of visible statuses according to role (used to filter search results)
166+
LOWER_VISIBLE_STATUS = {{
167+
ANONYMOUS:PUBLIC,
168+
AWAITING:PUBLIC,
169+
USER:PRIVATE,
170+
CONTRIBUTOR:DRAFT,
171+
MANAGER:DRAFT,
172+
}}
173+
161174
# Status display in user interface
162175
STATUS_DISPLAY = [[DRAFT,'Draft'],[PRIVATE,'Private'],[PUBLIC,'Public']]
163176

@@ -202,6 +215,34 @@ LOCALE_INDEPENDENT_PATHS = (
202215

203216
FIXTURE_DIRS = 'data/fixtures'
204217

218+
###########################
219+
# Djity indexing settings #
220+
###########################
221+
222+
# Haystack search engine connections configuration
223+
HAYSTACK_CONNECTIONS = {{'default':{{
224+
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
225+
'PATH': '%s/data/whoosh/djity_index/default' % (PROJECT_ROOT),
226+
'STORAGE': 'file',
227+
'POST_LIMIT': 128 * 1024 * 1024,
228+
'INCLUDE_SPELLING': True,
229+
'BATCH_SIZE': 100,
230+
}}
231+
}}
232+
233+
for (language,language_repr) in LANGUAGES:
234+
HAYSTACK_CONNECTIONS['default_'+language] = {{
235+
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
236+
'PATH': '%s/data/whoosh/djity_index/%s' % (PROJECT_ROOT,language),
237+
'STORAGE': 'file',
238+
'POST_LIMIT': 128 * 1024 * 1024,
239+
'INCLUDE_SPELLING': True,
240+
'BATCH_SIZE': 100,
241+
'LANGUAGE': '%s' % language
242+
}}
243+
244+
HAYSTACK_ROUTERS = ['haystack.routers.LanguageRouter']
245+
205246
###################################################################
206247
# Import local settings and those from djity apps #
207248
###################################################################

djity/project_skeleton/urls.py_tmpl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ urlpatterns = patterns('',
1414

1515
(r'^localeurl/', include('localeurl.urls')),
1616

17-
1817
(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),
1918

2019
(r'^jsi18n/', 'django.views.i18n.javascript_catalog',{{ 'packages': ('djity')}}),

djity/search/__init__.py

Whitespace-only changes.

djity/search/forms.py

Whitespace-only changes.

djity/search/templatetags/__init__.py

Whitespace-only changes.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from django import template
2+
3+
register = template.Library()
4+
5+
@register.simple_tag(takes_context=True)
6+
def search_result(context, result):
7+
"""
8+
Will render a search result for haystack by using the appropriate template for each model type
9+
"""
10+
if result.app_label.startswith("djity_"):
11+
template_path = "%s/%s_search_result.html" % (result.app_label,result.model_name)
12+
else:
13+
template_path = "djity/%s/%s_search_result.html" % (result.app_label,result.model_name)
14+
return template.loader.render_to_string(template_path, {'result_url':result.object.djity_url(context)}, context)
15+

djity/search/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.conf.urls.defaults import *
2+
from djity.search.views import project_search
3+
4+
urlpatterns = patterns('djity.search.views',
5+
url(r'^$', project_search, name='project_search'),
6+
)

djity/search/views.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from django.conf import settings
2+
3+
from haystack.views import basic_search
4+
from haystack.query import SearchQuerySet
5+
from haystack.forms import SearchForm
6+
7+
from djity.utils.decorators import djity_view
8+
from djity.utils.context import DjityContext
9+
10+
@djity_view(perm='view')
11+
def project_search(request,context=None):
12+
"""
13+
Override haystack basic_view for customization.
14+
"""
15+
sqs = SearchQuerySet().narrow("project:%s"% context['project'].id).narrow("status:%s" % settings.LOWER_VISIBLE_STATUS[context['role']])
16+
return basic_search(request, template='djity/search/search.html', searchqueryset=sqs, form_class=SearchForm, extra_context=context, context_class=DjityContext)

djity/simplepage/search_indexes.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from django.conf import settings
2+
3+
from haystack import indexes
4+
5+
from djity.simplepage.models import SimplePage
6+
7+
class SimplePageIndex(indexes.RealTimeSearchIndex, indexes.Indexable):
8+
text = indexes.CharField(document=True, model_attr='content')
9+
project = indexes.IntegerField(model_attr='project__id')
10+
status = indexes.MultiValueField()
11+
12+
def prepare_status(self,obj):
13+
return range(obj.status+1)
14+
15+
def get_model(self):
16+
return SimplePage

djity/static/djity/js/djity.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,28 @@ function widgetify() {
163163
$(this).removeClass("ui-state-hover");
164164
}
165165
);
166-
166+
167+
$('#search_query').keypress(function(e) {
168+
if(e.which == 13) {
169+
$("#search_button").click();
170+
}});
171+
172+
$('#search_button')
173+
.addClass("dj-mini-button")
174+
.button({
175+
icons: {
176+
primary: "ui-icon-search"
177+
},
178+
text:false,
179+
})
180+
.click(function(){
181+
query = $("#search_query").val();
182+
project_url = $("#search_button .ui-button-text").text();
183+
window.location.replace(project_url+"/search/?q="+query);
184+
});
167185

168186
$('#messages').notify();
169187

170-
171188

172189
if(dj.context.perm.manage){
173190
$("#project_title").editable({simple:true,save_function:'djity.project.save_project_title'});
@@ -195,13 +212,13 @@ function toolbar() {
195212
$("#toolbar").buttonset();
196213
$("#toolbar a")
197214
.button()
198-
.addClass('dj.context.mini-button');
215+
.addClass('dj-mini-button');
199216
};
200217

201218
function paginator() {
202219
$('#paginator a')
203220
.button()
204-
.addClass('dj.context.mini-button');
221+
.addClass('dj-mini-button');
205222

206223
$('#paginator .off')
207224
.button('option','disabled','true');

djity/templates/djity/base.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@
127127

128128
<nav id="portal_parameters" class="ui-helper-hidden">
129129
</nav>
130+
131+
132+
<div id="search_form">
133+
<input id="search_query" name='q' type="text"></input>
134+
<span class="ui-icon ui-icon-search" title="{% trans "Search" %}" id="search_button">{% djiurl project %}</span>
135+
</div>
130136

131137
<nav id="right_tabs" class="ui-helper-hidden" >
132138
{% if perm.manage %}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{% extends "djity/base.html" %}
2+
3+
{% load search_result %}
4+
5+
{% load i18n %}
6+
7+
{% block body %}
8+
{% if query %}
9+
<h3>{% trans "Search results for query" %} "{{ query }}"</h3>
10+
{% for result in page.object_list %}
11+
<p>
12+
{% search_result result %}
13+
</p>
14+
{% empty %}
15+
<p>{% trans "No results found." %}</p>
16+
{% endfor %}
17+
18+
{% if page.has_previous or page.has_next %}
19+
<div>
20+
{% if page.has_previous %}<a href="?q={{ query }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %}
21+
|
22+
{% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %}
23+
</div>
24+
{% endif %}
25+
{% else %}
26+
{% trans "Submit a query to get some results !"
27+
{% endif %}
28+
{% endblock %}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{% load highlight %}
2+
3+
<a href="{{ result_url }}">{{ result.object.name }}</a><br>
4+
{% highlight result.object.content with query %}
5+

djity/templates/djity/style/project.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@ html>body #main {
217217
float:right;
218218
}
219219

220+
#search_form {
221+
float:right;
222+
padding-right:50px;
223+
}
224+
225+
#search_query {
226+
}
227+
228+
#search_button {
229+
right:32px;
230+
border:none;
231+
background:none;
232+
}
220233

221234
#create_tab_button {
222235
float:right;

docsrc/source/admin/commands.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Project management commands
2+
===========================
3+
4+
* Prepare the databases. Useful in particular if you wish to update Djity for an existing project, or are modifying the models of an application used by the current project. (This is used automatically if you select the development mode of `djity-admin.py create_project`)::
5+
6+
$ python manage.py syncdb
7+
8+
* Create initial data for an empty project. (This is used automatically if you select the development mode of `djity-admin.py create_project`)::
9+
10+
$ python manage.py create_portal
11+
12+
* Run development server. (This is used automatically if you select the development mode of `djity-admin.py create_project`)::
13+
14+
$ python manage.py runserver
15+
16+
* Update search indexes. When the data of indexable contents from a project is modified, you should update all search indexes::
17+
18+
$ python manage.py update_indexes --using=all
19+
20+
* Install an application in the current project. You can use `djity-admin.py ls_apps` to list all installed apps in the system::
21+
22+
$ python manage.py install_app <app>

docsrc/source/admin/index.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Administration guide
2+
====================
3+
4+
Administrate a Djity based website. Still very raw.
5+
6+
.. toctree::
7+
:maxdepth: 2
8+
9+
commands.rst
10+

0 commit comments

Comments
 (0)