Bladeren bron

Bumped haystack to 2.0.0-beta

This is needed for internal Tangent projects.  The search app in oscar
still needs some work but it works in a very basic fashion at the
moment.

The template for search results still needs attention.
master
David Winterbottom 13 jaren geleden
bovenliggende
commit
0ec010a20b

+ 1
- 0
.gitignore Bestand weergeven

@@ -34,3 +34,4 @@ sandbox/public/
34 34
 logs/
35 35
 build/
36 36
 *.pdf
37
+sandbox/whoosh_index

+ 0
- 1
oscar/apps/search/__init__.py Bestand weergeven

@@ -1 +0,0 @@
1
-import oscar.search_sites

+ 0
- 35
oscar/apps/search/abstract_indexes.py Bestand weergeven

@@ -1,35 +0,0 @@
1
-from haystack.indexes import *
2
-
3
-from oscar.core.loading import import_module
4
-product_models = import_module('catalogue.models', ['Product'])
5
-
6
-
7
-class AbstractProductIndex(SearchIndex):
8
-    u"""
9
-    Base class for products solr index definition.  Overide by creating your
10
-    own copy of oscar.search_indexes.py
11
-    """
12
-    text = EdgeNgramField(document=True, use_template=True, template_name='search/indexes/product/item_text.txt')
13
-    title = EdgeNgramField(model_attr='title', null=True)
14
-    upc = CharField(model_attr="upc", null=True)
15
-    product_score = FloatField(model_attr="score")
16
-    date_created = DateTimeField(model_attr='date_created')
17
-    date_updated = DateTimeField(model_attr='date_updated')
18
-
19
-    def index_queryset(self):
20
-        """
21
-        Used when the entire index for model is updated.
22
-
23
-        Orders by the most recently updated so that new objects are indexed first
24
-        """
25
-        return product_models.Product.objects.order_by('-date_updated')
26
-
27
-    def get_updated_field(self):
28
-        u"""
29
-        Used to specify the field used to determine if an object has been updated
30
-
31
-        Can be used to filter the query set when updating the index
32
-        """
33
-        return 'date_updated'
34
-
35
-

+ 2
- 15
oscar/apps/search/app.py Bestand weergeven

@@ -1,30 +1,17 @@
1 1
 from django.conf.urls.defaults import patterns, url
2
-from django.contrib.admin.views.decorators import staff_member_required
3
-from haystack.query import SearchQuerySet
4 2
 
5 3
 from oscar.core.application import Application
6
-from oscar.apps.search.views import SuggestionsView, MultiFacetedSearchView
7
-from oscar.apps.search.search_indexes import ProductIndex
4
+from oscar.apps.search.views import MultiFacetedSearchView
8 5
 from oscar.apps.search.forms import MultiFacetedSearchForm
9 6
 
10 7
 
11 8
 class SearchApplication(Application):
12 9
     name = 'search'
13
-    
14
-    suggestions_view = SuggestionsView
15 10
     search_view = MultiFacetedSearchView
16 11
 
17 12
     def get_urls(self):
18
-        sqs = SearchQuerySet()
19
-        for field_name, field in ProductIndex.fields.items():
20
-            if field.faceted is True:
21
-                # Ensure we facet the results set by the defined facetable fields
22
-                sqs.facet(field_name)
23
-        
24 13
         urlpatterns = patterns('',
25
-            url(r'^suggest/$', self.suggestions_view.as_view(), name='suggest'),
26
-            url(r'^$', self.search_view(form_class=MultiFacetedSearchForm, 
27
-                                        searchqueryset=sqs), name='search'),
14
+            url(r'^$', self.search_view(form_class=MultiFacetedSearchForm), name='search'),
28 15
         )
29 16
         return self.post_process_urls(urlpatterns)
30 17
 

+ 1
- 1
oscar/apps/search/forms.py Bestand weergeven

@@ -24,7 +24,7 @@ class MultiFacetedSearchForm(FacetedSearchForm):
24 24
         '''
25 25
         Overriding the search method to allow for multiple facets
26 26
         '''
27
-        sqs = super(FacetedSearchForm, self).search().order_by('-score')
27
+        sqs = super(FacetedSearchForm, self).search()
28 28
         if hasattr(self, 'cleaned_data') and 'selected_facets' in self.cleaned_data:
29 29
             for f in self.cleaned_data['selected_facets'].split("|"):
30 30
                 sqs = sqs.narrow(f)

+ 31
- 13
oscar/apps/search/search_indexes.py Bestand weergeven

@@ -1,19 +1,37 @@
1
-from haystack import site
2
-from haystack.exceptions import AlreadyRegistered
1
+from haystack import indexes
3 2
 
4
-from oscar.apps.search.abstract_indexes import AbstractProductIndex
5
-from oscar.core.loading import import_module
6
-product_models = import_module('catalogue.models', ['Product'])
3
+from django.db.models import get_model
7 4
 
8 5
 
9
-class ProductIndex(AbstractProductIndex):
10
-    pass
6
+class ProductIndex(indexes.SearchIndex, indexes.Indexable):
7
+    """
8
+    Base class for products solr index definition.  Overide by creating your
9
+    own copy of oscar.search_indexes.py
10
+    """
11
+    text = indexes.EdgeNgramField(document=True, use_template=True,
12
+                                  template_name='oscar/search/indexes/product/item_text.txt')
13
+    title = indexes.EdgeNgramField(model_attr='title', null=True)
14
+    upc = indexes.CharField(model_attr="upc", null=True)
15
+    date_created = indexes.DateTimeField(model_attr='date_created')
16
+    date_updated = indexes.DateTimeField(model_attr='date_updated')
11 17
 
18
+    def get_model(self):
19
+        return get_model('catalogue', 'Product')
20
+
21
+    def index_queryset(self):
22
+        """
23
+        Used when the entire index for model is updated.
24
+
25
+        Orders by the most recently updated so that new objects are indexed first
26
+        """
27
+        return self.get_model().objects.order_by('-date_updated')
28
+
29
+    def get_updated_field(self):
30
+        """
31
+        Used to specify the field used to determine if an object has been updated
32
+
33
+        Can be used to filter the query set when updating the index
34
+        """
35
+        return 'date_updated'
12 36
 
13
-try:
14
-    site.register(product_models.Product, ProductIndex)
15
-except AlreadyRegistered:
16
-    # If already registered, it means that a different search app is being
17
-    # used to search products.
18
-    pass
19 37
 

+ 3
- 6
oscar/apps/search/views.py Bestand weergeven

@@ -3,7 +3,6 @@ import json
3 3
 from django.http import HttpResponse, HttpResponseRedirect
4 4
 from django.views.generic.base import View
5 5
 from django.conf import settings
6
-from django.template.response import TemplateResponse
7 6
 from haystack.query import SearchQuerySet
8 7
 from haystack.views import FacetedSearchView
9 8
 
@@ -55,7 +54,7 @@ class SuggestionsView(View):
55 54
 
56 55
 
57 56
 class MultiFacetedSearchView(FacetedSearchView):
58
-    u"""
57
+    """
59 58
     Search view for multifaceted searches
60 59
     """
61 60
     template = 'search/results.html'
@@ -63,18 +62,16 @@ class MultiFacetedSearchView(FacetedSearchView):
63 62
     def __call__(self, request, *args, **kwargs):
64 63
         """
65 64
         Generates the actual response to the search.
66
-        
65
+
67 66
         Relies on internal, overridable methods to construct the response.
68 67
         """
69
-        
70 68
         # Look for UPC match
71
-        query = request.GET['q'].strip()
69
+        query = request.GET.get('q', '').strip()
72 70
         try:
73 71
             item = product_models.Product._default_manager.get(upc=query)
74 72
             return HttpResponseRedirect(item.get_absolute_url())
75 73
         except product_models.Product.DoesNotExist:
76 74
             pass
77
-        
78 75
         return super(MultiFacetedSearchView, self).__call__(request, *args, **kwargs)
79 76
 
80 77
     @property

+ 0
- 3
oscar/search_sites.py Bestand weergeven

@@ -1,3 +0,0 @@
1
-import haystack
2
-
3
-haystack.autodiscover()

+ 26
- 29
oscar/templates/oscar/search/results.html Bestand weergeven

@@ -3,9 +3,27 @@
3 3
 {% load thumbnail %}
4 4
 {% load i18n %}
5 5
 
6
+{% block title %}
7
+"{{ query }}" | {{ block.super }}
8
+{% endblock %}
9
+
10
+{% block breadcrumbs %}
11
+<ul class="breadcrumb">
12
+	<li>
13
+	<a href="{% url promotions:home %}">{% trans "Home" %}</a>
14
+	<span class="divider">/</span>
15
+	</li>
16
+	<li>
17
+	{% trans "Search" %}
18
+	<span class="divider">/</span>
19
+	</li>
20
+	<li class="active"><a href=".">{% blocktrans with q=query%}"{{ q }}"{% endblocktrans %}</a></li>
21
+</ul>
22
+{% endblock %}
23
+
6 24
 {% block header%}
7 25
 <div class="page-header">
8
-    <h1>{% trans 'Search for' %} '{{ query }}'</h1>
26
+	<h1>{% trans 'Search for' %} '{{ query }}'</h1>
9 27
 </div>
10 28
 {% endblock %}
11 29
 
@@ -16,38 +34,17 @@
16 34
 {% endif %}
17 35
 
18 36
 {% if page.object_list %}
19
-    <ol class="products vertical three">
20
-        {% for result in page.object_list %}
21
-        <li>
22
-            <article class="product_pod">
23
-            {% with image=product.primary_image %}
24
-            {% thumbnail image.original "400x400" upscale=False as thumb %}
25
-            <a href="{{ product.get_absolute_url }}"><img class="thumbnail" src="{{ thumb.url }}" alt="{{ product.get_title }}"></a>
26
-            {% endthumbnail %}
27
-            {% endwith %}
28
-            <h3><a href="{{ result.object.get_absolute_url }}">{{ result.object.get_title }}</a></h3>
29
-            <div class="product_price">
30
-                {% if result.object.is_group %}
31
-                    <p>From {{ result.object.min_variant_price_incl_tax|currency }}</p>
32
-                {% else %}
33
-                    {% if result.object.has_stockrecord %}
34
-                        <h4>{{ result.object.stockrecord.price_incl_tax|currency }}</h4>
35
-                         <p class="app-ico avaliability instock">{{ result.object.stockrecord.availability }}</p>
36
-                     {% else %}
37
-                         <p class="app-ico avaliability outstock">{% trans 'Not available' %}</p>
38
-                     {% endif %}
39
-                {% endif %}
40
-            </div>
41
-            </article>    
42
-        </li>
43
-        {% endfor %}
44
-    </ol>
37
+<ol class="products vertical three">
38
+	{% for result in page.object_list %}
39
+	{% include "catalogue/partials/product.html" with product=result.object %}
40
+	{% endfor %}
41
+</ol>
45 42
 {% else %}
46
-    <p>{% trans 'No search results found.' %}</p>
43
+<p>{% trans 'No search results found.' %}</p>
47 44
 {% endif %}
48 45
 
49 46
 {% if page_obj %}
50
-    {% include "catalogue/partials/pagination.html" %}
47
+{% include "catalogue/partials/pagination.html" %}
51 48
 {% endif %}
52 49
 
53 50
 {% endblock %}

+ 1
- 0
requirements.txt Bestand weergeven

@@ -18,3 +18,4 @@ pinocchio==0.3.1
18 18
 nose-progressive==1.3
19 19
 django-nose==1.1
20 20
 django-rosetta==0.6.8
21
+Whoosh==2.4.1

+ 7
- 3
sandbox/settings.py Bestand weergeven

@@ -107,7 +107,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
107 107
     'oscar.apps.promotions.context_processors.promotions',
108 108
     'oscar.apps.checkout.context_processors.checkout',
109 109
     'oscar.core.context_processors.metadata',
110
-) 
110
+)
111 111
 
112 112
 MIDDLEWARE_CLASSES = (
113 113
     'django.middleware.common.CommonMiddleware',
@@ -229,8 +229,12 @@ LOGIN_REDIRECT_URL = '/accounts/'
229 229
 APPEND_SLASH = True
230 230
 
231 231
 # Haystack settings
232
-HAYSTACK_SITECONF = 'oscar.search_sites'
233
-HAYSTACK_SEARCH_ENGINE = 'dummy'
232
+HAYSTACK_CONNECTIONS = {
233
+    'default': {
234
+        'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
235
+        'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
236
+    },
237
+}
234 238
 
235 239
 DEBUG_TOOLBAR_CONFIG = {
236 240
     'INTERCEPT_REDIRECTS': False

+ 1
- 0
sandbox/update_sandbox.sh Bestand weergeven

@@ -14,6 +14,7 @@ cd sandbox
14 14
 ./manage.py syncdb --noinput
15 15
 ./manage.py migrate
16 16
 ./manage.py collectstatic --noinput
17
+./manage.py rebuild_index --noinput
17 18
 
18 19
 # Re-compile python code
19 20
 touch deploy/wsgi/sandbox.wsgi

+ 2
- 1
setup.py Bestand weergeven

@@ -29,12 +29,13 @@ setup(name='django-oscar',
29 29
           'PIL==1.1.7',
30 30
           'South==0.7.3',
31 31
           'django-extra-views==0.2.0',
32
-          'django-haystack==1.2.7',
32
+          'django-haystack==2.0.0-beta',
33 33
           'django-treebeard==1.61',
34 34
           'sorl-thumbnail==11.12',
35 35
           'python-memcached==1.48',
36 36
           'django-sorting==0.1',
37 37
           ],
38
+      dependency_links=['http://github.com/toastdriven/django-haystack/tarball/master#egg=django-haystack-2.0.0-beta'],
38 39
       # See http://pypi.python.org/pypi?%3Aaction=list_classifiers
39 40
       classifiers=['Environment :: Web Environment',
40 41
                    'Framework :: Django',

+ 5
- 2
tests/config.py Bestand weergeven

@@ -50,12 +50,15 @@ def configure(nose_args):
50 50
                 'oscar.apps.customer.auth_backends.Emailbackend',
51 51
                 'django.contrib.auth.backends.ModelBackend',
52 52
                 ),
53
+            HAYSTACK_CONNECTIONS={
54
+                'default': {
55
+                    'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
56
+                }
57
+            },
53 58
             ROOT_URLCONF='tests.site.urls',
54 59
             LOGIN_REDIRECT_URL='/accounts/',
55 60
             DEBUG=False,
56 61
             SITE_ID=1,
57
-            HAYSTACK_SEARCH_ENGINE='dummy',
58
-            HAYSTACK_SITECONF = 'oscar.search_sites',
59 62
             APPEND_SLASH=True,
60 63
             NOSE_ARGS=nose_args,
61 64
             **OSCAR_SETTINGS

Laden…
Annuleren
Opslaan