diff --git a/requirements.pip b/requirements.pip
index df5af99b..93acadbe 100644
--- a/requirements.pip
+++ b/requirements.pip
@@ -8,4 +8,5 @@ django==1.4.2
#south==0.7.6
git+git://github.com/petry/django-foundation.git
git+git://github.com/yohanboniface/django-chickpea.git
-git+git://github.com/frankban/django-endless-pagination.git
\ No newline at end of file
+git+git://github.com/frankban/django-endless-pagination.git
+hg+https://bitbucket.org/liberation/sesql
\ No newline at end of file
diff --git a/youmap/sesql_config.py b/youmap/sesql_config.py
new file mode 100644
index 00000000..3d898902
--- /dev/null
+++ b/youmap/sesql_config.py
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) Pilot Systems and Libération, 2010-2011
+
+# This file is part of SeSQL.
+
+# SeSQL is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# Foobar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with SeSQL. If not, see .
+
+#
+# Full text search configuration - we must define that before the imports,
+# because those are used by the imports
+#
+
+# Name of the PostgreSQL Text Search Configuration
+TS_CONFIG_NAME = "simple_french"
+
+# Name of the stopwards file, must be plain ASCII
+STOPWORDS_FILE = "ascii_french"
+
+# Global charset to use
+CHARSET = "utf-8"
+
+from sesql.fields import *
+from sesql.sources import *
+from django.db.models import Q
+from chickpea import models
+
+#
+# Select the ORM to use
+#
+from sesql.orm.django import DjangoOrmAdapter
+orm = DjangoOrmAdapter()
+
+
+#
+# Fields and tables configuration
+#
+
+# Configuration of SeSQL search fields
+FIELDS = (ClassField("classname"),
+ IntField("id"),
+ DateField("modified_at"),
+ FullTextField("name"),
+ FullTextField("fulltext",
+ ['name', 'description',
+ SubField("owner", ["username"])
+ ],
+ primary=True,
+ ),
+ DateField('indexed_at', sql_default='NOW()'),
+ )
+
+# Name of the global lookup table that should contain no real data
+MASTER_TABLE_NAME = "sesql_index"
+
+# Type map, associating Django classes to SeSQL tables
+TYPE_MAP = ((models.Map, "sesql_default"), )
+
+# Additional indexes to create
+CROSS_INDEXES = ()
+
+#
+# Cleanup configuration
+#
+
+from htmlentitydefs import name2codepoint
+from xml.sax import saxutils
+
+html_entities = dict([('&%s;' % k, unichr(v).encode(config.CHARSET)) for k,v in name2codepoint.items() ])
+ADDITIONAL_CLEANUP_FUNCTION = lambda value: saxutils.unescape(value, html_entities)
+
+#
+# Query configuration
+#
+
+# General condition to skip indexing content
+SKIP_CONDITION = None
+
+# Default sort order for queries
+DEFAULT_ORDER = ('-modified_at',)
+
+# Default LIMIT in short queries
+DEFAULT_LIMIT = 20
+
+# First we ask for the SMART_QUERY_INITIAL first sorted items
+SMART_QUERY_INITIAL = 2500
+# Then, if we have at least SMART_QUERY_THRESOLD of our limit, we go on
+SMART_QUERY_THRESOLD = 0.35
+# If we have a second query, we do * (wanted/result) * SMART_QUERY_RATIO
+SMART_QUERY_RATIO = 3.0
+
+#
+# Long query cache configuration
+#
+
+# Maximal number of queries to store in the long query cache
+QUERY_CACHE_MAX_SIZE = 10000
+# Life time of a query in the query cache
+QUERY_CACHE_EXPIRY = 24 * 3600
+
+#
+# Daemon configuration
+#
+
+DAEMON_DEFAULT_CHUNK = 100
+DAEMON_DEFAULT_DELAY = 120
+DAEMON_DEFAULT_PID = '/var/run/sesql/update.pid'
+
+#
+# Suggest/history configuration
+#
+
+# default number of hit before including query in db
+HISTORY_DEFAULT_FILTER = 5
+
+# erode factor for time-based decay of recent searches score
+HISTORY_ALPHA = 0.95
+# weight of frequency of the search in the final score
+HISTORY_BETA = 1.0
+# weight of number of results in the final score
+HISTORY_GAMMA = 1.0
+
+# queries to ignore in history
+HISTORY_BLACKLIST = []
+
+
+#
+# Enable sesql searches from Django admin ?
+#
+ENABLE_SESQL_ADMIN = False
+
+#
+# Enable to force all updates to be processed asynchronously by the daemon
+#
+
+ASYNCHRONOUS_INDEXING = False
diff --git a/youmap/settings/base.py b/youmap/settings/base.py
index 7e0098a9..9f375ac1 100644
--- a/youmap/settings/base.py
+++ b/youmap/settings/base.py
@@ -29,6 +29,7 @@ INSTALLED_APPS = (
'foundation',
'endless_pagination',
'youmap',
+ 'sesql',
#'south',
diff --git a/youmap/templates/youmap/navigation.html b/youmap/templates/youmap/navigation.html
index 2ddaf3ce..9c1017a2 100644
--- a/youmap/templates/youmap/navigation.html
+++ b/youmap/templates/youmap/navigation.html
@@ -15,15 +15,11 @@
diff --git a/youmap/templates/youmap/search.html b/youmap/templates/youmap/search.html
new file mode 100644
index 00000000..b6ae472b
--- /dev/null
+++ b/youmap/templates/youmap/search.html
@@ -0,0 +1,33 @@
+{% extends "youmap/home.html" %}
+
+{% block content %}
+
+
+
+
+
+ {% include 'youmap/navigation.html' %}
+
+
+
+
+
+
+
+
Search for maps containing «{{ q }}»
+
+
+
+
+
+ {% if maps %}
+ {% include "chickpea/map_list.html" %}
+ {% else %}
+
+ Not map found.
+
+ {% endif %}
+
+
+
+{% endblock content %}
diff --git a/youmap/urls.py b/youmap/urls.py
index 95a4ef94..a05459ea 100644
--- a/youmap/urls.py
+++ b/youmap/urls.py
@@ -14,6 +14,7 @@ urlpatterns = patterns('',
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)),
url(r'^$', views.home, name="home"),
+ url(r'^search/$', views.search, name="search"),
url(r'^user/(?P[-_\w]+)/$', views.user_maps, name='user_maps'),
(r'', include('chickpea.urls')),
)
diff --git a/youmap/views.py b/youmap/views.py
index 98557a85..a04e53ef 100644
--- a/youmap/views.py
+++ b/youmap/views.py
@@ -1,6 +1,9 @@
from django.views.generic import TemplateView
from django.contrib.auth.models import User
from django.views.generic import DetailView
+from django.db.models import Q
+
+from sesql.shortquery import shortquery
from chickpea.models import Map
@@ -53,3 +56,28 @@ class UserMaps(DetailView):
return super(UserMaps, self).get_template_names()
user_maps = UserMaps.as_view()
+
+
+class Search(TemplateView):
+ template_name = "youmap/search.html"
+ list_template_name = "chickpea/map_list.html"
+
+ def get_context_data(self, **kwargs):
+ q = self.request.GET['q']
+ maps = shortquery(Q(fulltext__containswords=q))
+ kwargs.update({
+ 'maps': maps,
+ 'q': q
+ })
+ return kwargs
+
+ def get_template_names(self):
+ """
+ Dispatch template according to the kind of request: ajax or normal.
+ """
+ if self.request.is_ajax():
+ return [self.list_template_name]
+ else:
+ return super(Search, self).get_template_names()
+
+search = Search.as_view()