kopia lustrzana https://github.com/wagtail/wagtail
Merge branch 'master' of github.com:torchbox/wagtail
commit
7207ab02af
|
@ -13,7 +13,7 @@ It supports Django 1.6.2+ on Python 2.6, 2.7, 3.2, 3.3 and 3.4. Django 1.7 suppo
|
|||
building_your_site/index
|
||||
editing_api
|
||||
snippets
|
||||
wagtail_search
|
||||
wagtailsearch/index
|
||||
form_builder
|
||||
model_recipes
|
||||
advanced_topics
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
.. _wagtailsearch_backends:
|
||||
|
||||
======================
|
||||
Wagtailsearch backends
|
||||
======================
|
||||
|
||||
|
||||
Wagtail can degrade to a database-backed text search, but we strongly recommend `Elasticsearch`_.
|
||||
|
||||
.. _Elasticsearch: http://www.elasticsearch.org/
|
||||
|
||||
|
||||
.. _wagtailsearch_backends_database:
|
||||
|
||||
Database Backend
|
||||
===============
|
||||
|
||||
The default DB search backend uses Django's ``__icontains`` filter.
|
||||
|
||||
|
||||
Elasticsearch Backend
|
||||
=====================
|
||||
|
||||
Prerequisites are the Elasticsearch service itself and, via pip, the `elasticsearch-py`_ package:
|
||||
|
||||
.. code-block:: guess
|
||||
|
||||
pip install elasticsearch
|
||||
|
||||
.. note::
|
||||
If you are using Elasticsearch < 1.0, install elasticsearch-py version 0.4.5: ```pip install elasticsearch==0.4.5```
|
||||
|
||||
The backend is configured in settings:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
WAGTAILSEARCH_BACKENDS = {
|
||||
'default': {
|
||||
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
|
||||
'URLS': ['http://localhost:9200'],
|
||||
'INDEX': 'wagtail',
|
||||
'TIMEOUT': 5,
|
||||
'FORCE_NEW': False,
|
||||
}
|
||||
}
|
||||
|
||||
Other than ``BACKEND`` the keys are optional and default to the values shown. ``FORCE_NEW`` is used by elasticsearch-py. In addition, any other keys are passed directly to the Elasticsearch constructor as case-sensitive keyword arguments (e.g. ``'max_retries': 1``).
|
||||
|
||||
If you prefer not to run an Elasticsearch server in development or production, there are many hosted services available, including `Searchly`_, who offer a free account suitable for testing and development. To use Searchly:
|
||||
|
||||
- Sign up for an account at `dashboard.searchly.com/users/sign\_up`_
|
||||
- Use your Searchly dashboard to create a new index, e.g. 'wagtaildemo'
|
||||
- Note the connection URL from your Searchly dashboard
|
||||
- Configure ``URLS`` and ``INDEX`` in the Elasticsearch entry in ``WAGTAILSEARCH_BACKENDS``
|
||||
- Run ``./manage.py update_index``
|
||||
|
||||
.. _elasticsearch-py: http://elasticsearch-py.readthedocs.org
|
||||
.. _Searchly: http://www.searchly.com/
|
||||
.. _dashboard.searchly.com/users/sign\_up: https://dashboard.searchly.com/users/sign_up
|
||||
|
||||
|
||||
Rolling Your Own
|
||||
================
|
||||
|
||||
Wagtail search backends implement the interface defined in ``wagtail/wagtail/wagtailsearch/backends/base.py``. At a minimum, the backend's ``search()`` method must return a collection of objects or ``model.objects.none()``. For a fully-featured search backend, examine the Elasticsearch backend code in ``elasticsearch.py``.
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
.. _wagtailsearch_editors_picks:
|
||||
|
||||
|
||||
Editors picks
|
||||
=============
|
||||
|
||||
Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties.
|
||||
|
||||
``query.editors_picks.all``
|
||||
This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties:
|
||||
|
||||
``editors_pick.page``
|
||||
The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object.
|
||||
|
||||
``editors_pick.description``
|
||||
The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms.
|
||||
|
||||
Putting this all together, a block of your search results template displaying editor's Picks might look like this:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% with query.editors_picks.all as editors_picks %}
|
||||
{% if editors_picks %}
|
||||
<div class="well">
|
||||
<h3>Editors picks</h3>
|
||||
<ul>
|
||||
{% for editors_pick in editors_picks %}
|
||||
<li>
|
||||
<h4>
|
||||
<a href="{% pageurl editors_pick.page %}">
|
||||
{{ editors_pick.page.title }}
|
||||
</a>
|
||||
</h4>
|
||||
<p>{{ editors_pick.description|safe }}</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
|
@ -0,0 +1,152 @@
|
|||
|
||||
.. _wagtailsearch_for_python_developers:
|
||||
|
||||
|
||||
====================================
|
||||
Wagtailsearch: For python developers
|
||||
====================================
|
||||
|
||||
|
||||
Basic usage
|
||||
===========
|
||||
|
||||
All searches are performed on Django QuerySets. Wagtail provides a ``search`` method on the queryset for all page models:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Search future EventPages
|
||||
>>> from wagtail.wagtailcore.models import EventPage
|
||||
>>> EventPage.objects.filter(date__gt=timezone.now()).search("Hello world!")
|
||||
|
||||
|
||||
All methods of ``PageQuerySet`` are supported by wagtailsearch:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Search all live EventPages that are under the events index
|
||||
>>> EventPage.objects.live().descendant_of(events_index).search("Hello")
|
||||
[<EventPage: Event 1>, <EventPage: Event 2>]
|
||||
|
||||
|
||||
Indexing extra fields
|
||||
=====================
|
||||
|
||||
Fields need to be explicitly added to the search configuration in order for you to be able to search/filter on them.
|
||||
|
||||
You can add new fields to the search index by overriding the ``search_fields`` property and appending a list of extra ``SearchField``/``FilterField`` objects to it.
|
||||
|
||||
``Page`` sets a default value to ``search_fields`` indexing the ``title`` field as a ``SearchField`` and some other generally useful fields as ``FilterField``s.
|
||||
|
||||
|
||||
Quick example
|
||||
-------------
|
||||
|
||||
This creates an ``EventPage`` model with two fields ``description`` and ``date``. ``description`` is indexed as a ``SearchField`` and ``date`` is indexed as a ``FilterField``
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailsearch import indexed
|
||||
|
||||
class EventPage(Page):
|
||||
description = models.TextField()
|
||||
date = models.DateField()
|
||||
|
||||
search_fields = Page.search_fields + ( # Inherit search_fields from Page
|
||||
indexed.SearchField('description'),
|
||||
indexed.FilterField('date'),
|
||||
)
|
||||
|
||||
|
||||
# Get future events which contain the string "Christmas" in the title or description
|
||||
>>> EventPage.objects.filter(date__gt=timezone.now()).search("Christmas")
|
||||
|
||||
|
||||
``indexed.SearchField``
|
||||
-----------------------
|
||||
|
||||
These are added to the search index and are used for performing full-text searches on your models. These would usually be text fields.
|
||||
|
||||
|
||||
Options
|
||||
```````
|
||||
|
||||
- **partial_match** (boolean) - Setting this to true allows results to be matched on parts of words. For example, this is set on the title field by default so a page titled "Hello World!" will be found if the user only types "Hel" into the search box.
|
||||
- **boost** (number) - This allows you to set fields as being more important than others. Setting this to a high number on a field will make pages with matches in that field to be ranked higher. By default, this is set to 100 on the title field and 1 on all other fields.
|
||||
- **es_extra** (dict) - This field is to allow the developer to set or override any setting on the field in the ElasticSearch mapping. Use this if you want to make use of any ElasticSearch features that are not yet supported in Wagtail.
|
||||
|
||||
|
||||
``indexed.FilterField``
|
||||
-----------------------
|
||||
|
||||
These are added to the search index but are not used for full-text searches. Instead, they allow you to run filters on your search results.
|
||||
|
||||
|
||||
Indexing callables and other attributes
|
||||
---------------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This is not supported in the :ref:`wagtailsearch_backends_database`
|
||||
|
||||
|
||||
Search/filter fields do not need to be Django fields, they could be any method or attribute on your class.
|
||||
|
||||
One use for this is indexing ``get_*_display`` methods Django creates automatically for fields with choices.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailsearch import indexed
|
||||
|
||||
class EventPage(Page):
|
||||
IS_PRIVATE_CHOICES = (
|
||||
(False, "Public"),
|
||||
(True, "Private"),
|
||||
)
|
||||
|
||||
is_private = models.BooleanField(choices=IS_PRIVATE_CHOICES)
|
||||
|
||||
search_fields = Page.search_fields + (
|
||||
# Index the human-readable string for searching
|
||||
indexed.SearchField('get_is_private_display'),
|
||||
|
||||
# Index the boolean value for filtering
|
||||
indexed.FilterField('is_private'),
|
||||
)
|
||||
|
||||
|
||||
Indexing non-page models
|
||||
========================
|
||||
|
||||
Any Django model can be indexed and searched.
|
||||
|
||||
To do this, inherit from ``indexed.Indexed`` and add some ``search_fields`` to the model.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailsearch import indexed
|
||||
|
||||
class Book(models.Model, indexed.Indexed):
|
||||
title = models.CharField(max_length=255)
|
||||
genre = models.CharField(max_length=255, choices=GENRE_CHOICES)
|
||||
author = models.ForeignKey(Author)
|
||||
published_date = models.DateTimeField()
|
||||
|
||||
search_fields = (
|
||||
indexed.SearchField('title', partial_match=True, boost=10),
|
||||
indexed.SearchField('get_genre_display'),
|
||||
|
||||
indexed.FilterField('genre'),
|
||||
indexed.FilterField('author'),
|
||||
indexed.FilterField('published_date'),
|
||||
)
|
||||
|
||||
# As this model doesn't have a search method in its QuerySet, we have to call search directly on the backend
|
||||
>>> from wagtail.wagtailsearch.backends import get_search_backend
|
||||
>>> s = get_search_backend()
|
||||
|
||||
# Run a search for a book by Roald Dahl
|
||||
>>> roald_dahl = Author.objects.get(name="Roald Dahl")
|
||||
>>> s.search("chocolate factory", Book.objects.filter(author=roald_dahl))
|
||||
[<Book: Charlie and the chocolate factory>]
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
.. _wagtail_search:
|
||||
.. _wagtailsearch_frontend_views:
|
||||
|
||||
Search
|
||||
======
|
||||
|
||||
Wagtail provides a comprehensive and extensible search interface. In addition, it provides ways to promote search results through "Editor's Picks." Wagtail also collects simple statistics on queries made through the search interface.
|
||||
Wagtailsearch frontend views
|
||||
============================
|
||||
|
||||
|
||||
Default Page Search
|
||||
-------------------
|
||||
|
@ -71,43 +71,6 @@ The search view provides a context with a few useful variables.
|
|||
``query``
|
||||
A Wagtail ``Query`` object matching the terms. The ``Query`` model provides several class methods for viewing the statistics of all queries, but exposes only one property for single objects, ``query.hits``, which tracks the number of time the search string has been used over the lifetime of the site. ``Query`` also joins to the Editor's Picks functionality though ``query.editors_picks``. See :ref:`editors-picks`.
|
||||
|
||||
Editor's Picks
|
||||
--------------
|
||||
|
||||
Editor's Picks are a way of explicitly linking relevant content to search terms, so results pages can contain curated content instead of being at the mercy of the search algorithm. In a template using the search results view, editor's picks can be accessed through the variable ``query.editors_picks``. To include editor's picks in your search results template, use the following properties.
|
||||
|
||||
``query.editors_picks.all``
|
||||
This gathers all of the editor's picks objects relating to the current query, in order according to their sort order in the Wagtail admin. You can then iterate through them using a ``{% for ... %}`` loop. Each editor's pick object provides these properties:
|
||||
|
||||
``editors_pick.page``
|
||||
The page object associated with the pick. Use ``{% pageurl editors_pick.page %}`` to generate a URL or provide other properties of the page object.
|
||||
|
||||
``editors_pick.description``
|
||||
The description entered when choosing the pick, perhaps explaining why the page is relevant to the search terms.
|
||||
|
||||
Putting this all together, a block of your search results template displaying editor's Picks might look like this:
|
||||
|
||||
.. code-block:: django
|
||||
|
||||
{% with query.editors_picks.all as editors_picks %}
|
||||
{% if editors_picks %}
|
||||
<div class="well">
|
||||
<h3>Editors picks</h3>
|
||||
<ul>
|
||||
{% for editors_pick in editors_picks %}
|
||||
<li>
|
||||
<h4>
|
||||
<a href="{% pageurl editors_pick.page %}">
|
||||
{{ editors_pick.page.title }}
|
||||
</a>
|
||||
</h4>
|
||||
<p>{{ editors_pick.description|safe }}</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
Asynchronous Search with JSON and AJAX
|
||||
--------------------------------------
|
||||
|
@ -142,30 +105,30 @@ Finally, we'll use JQuery to make the asynchronous requests and handle the inter
|
|||
// when there's something in the input box, make the query
|
||||
searchBox.on('input', function() {
|
||||
if( searchBox.val() == ''){
|
||||
resultsBox.html('');
|
||||
return;
|
||||
resultsBox.html('');
|
||||
return;
|
||||
}
|
||||
// make the request to the Wagtail JSON search view
|
||||
$.ajax({
|
||||
url: wagtailJSONSearchURL + "?q=" + searchBox.val(),
|
||||
dataType: "json"
|
||||
url: wagtailJSONSearchURL + "?q=" + searchBox.val(),
|
||||
dataType: "json"
|
||||
})
|
||||
.done(function(data) {
|
||||
console.log(data);
|
||||
if( data == undefined ){
|
||||
resultsBox.html('');
|
||||
return;
|
||||
}
|
||||
// we're in business! let's format the results
|
||||
var htmlOutput = '';
|
||||
data.forEach(function(element, index, array){
|
||||
htmlOutput += '<p><a href="' + element.url + '">' + element.title + '</a></p>';
|
||||
});
|
||||
// and display them
|
||||
resultsBox.html(htmlOutput);
|
||||
console.log(data);
|
||||
if( data == undefined ){
|
||||
resultsBox.html('');
|
||||
return;
|
||||
}
|
||||
// we're in business! let's format the results
|
||||
var htmlOutput = '';
|
||||
data.forEach(function(element, index, array){
|
||||
htmlOutput += '<p><a href="' + element.url + '">' + element.title + '</a></p>';
|
||||
});
|
||||
// and display them
|
||||
resultsBox.html(htmlOutput);
|
||||
})
|
||||
.error(function(data){
|
||||
console.log(data);
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -178,12 +141,12 @@ Results are returned as a JSON object with this structure:
|
|||
{
|
||||
[
|
||||
{
|
||||
title: "Lumpy Space Princess",
|
||||
url: "/oh-my-glob/"
|
||||
title: "Lumpy Space Princess",
|
||||
url: "/oh-my-glob/"
|
||||
},
|
||||
{
|
||||
title: "Lumpy Space",
|
||||
url: "/no-smooth-posers/"
|
||||
title: "Lumpy Space",
|
||||
url: "/no-smooth-posers/"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
@ -199,67 +162,8 @@ The AJAX interface uses the same view as the normal HTML search, ``wagtailsearch
|
|||
|
||||
In this template, you'll have access to the same context variables provided to the HTML template. You could provide a template in JSON format with extra properties, such as ``query.hits`` and editor's picks, or render an HTML snippet that can go directly into your results ``<div>``. If you need more flexibility, such as multiple formats/templates based on differing requests, you can set up a custom search view.
|
||||
|
||||
.. _editors-picks:
|
||||
|
||||
Custom Search Views
|
||||
-------------------
|
||||
|
||||
Indexing Custom Fields & Custom Search Views
|
||||
--------------------------------------------
|
||||
|
||||
This functionality is still under active development to provide a streamlined interface, but take a look at ``wagtail/wagtail/wagtailsearch/views/frontend.py`` if you are interested in coding custom search views.
|
||||
|
||||
|
||||
Search Backends
|
||||
---------------
|
||||
|
||||
Wagtail can degrade to a database-backed text search, but we strongly recommend `Elasticsearch`_.
|
||||
|
||||
.. _Elasticsearch: http://www.elasticsearch.org/
|
||||
|
||||
|
||||
Default DB Backend
|
||||
``````````````````
|
||||
The default DB search backend uses Django's ``__icontains`` filter.
|
||||
|
||||
|
||||
Elasticsearch Backend
|
||||
`````````````````````
|
||||
Prerequisites are the Elasticsearch service itself and, via pip, the `elasticsearch-py`_ package:
|
||||
|
||||
.. code-block:: guess
|
||||
|
||||
pip install elasticsearch
|
||||
|
||||
.. note::
|
||||
If you are using Elasticsearch < 1.0, install elasticsearch-py version 0.4.5: ```pip install elasticsearch==0.4.5```
|
||||
|
||||
The backend is configured in settings:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
WAGTAILSEARCH_BACKENDS = {
|
||||
'default': {
|
||||
'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
|
||||
'URLS': ['http://localhost:9200'],
|
||||
'INDEX': 'wagtail',
|
||||
'TIMEOUT': 5,
|
||||
'FORCE_NEW': False,
|
||||
}
|
||||
}
|
||||
|
||||
Other than ``BACKEND`` the keys are optional and default to the values shown. ``FORCE_NEW`` is used by elasticsearch-py. In addition, any other keys are passed directly to the Elasticsearch constructor as case-sensitive keyword arguments (e.g. ``'max_retries': 1``).
|
||||
|
||||
If you prefer not to run an Elasticsearch server in development or production, there are many hosted services available, including `Searchly`_, who offer a free account suitable for testing and development. To use Searchly:
|
||||
|
||||
- Sign up for an account at `dashboard.searchly.com/users/sign\_up`_
|
||||
- Use your Searchly dashboard to create a new index, e.g. 'wagtaildemo'
|
||||
- Note the connection URL from your Searchly dashboard
|
||||
- Configure ``URLS`` and ``INDEX`` in the Elasticsearch entry in ``WAGTAILSEARCH_BACKENDS``
|
||||
- Run ``./manage.py update_index``
|
||||
|
||||
.. _elasticsearch-py: http://elasticsearch-py.readthedocs.org
|
||||
.. _Searchly: http://www.searchly.com/
|
||||
.. _dashboard.searchly.com/users/sign\_up: https://dashboard.searchly.com/users/sign_up
|
||||
|
||||
Rolling Your Own
|
||||
````````````````
|
||||
Wagtail search backends implement the interface defined in ``wagtail/wagtail/wagtailsearch/backends/base.py``. At a minimum, the backend's ``search()`` method must return a collection of objects or ``model.objects.none()``. For a fully-featured search backend, examine the Elasticsearch backend code in ``elasticsearch.py``.
|
||||
This functionality is still under active development to provide a streamlined interface, but take a look at ``wagtail/wagtail/wagtailsearch/views/frontend.py`` if you are interested in coding custom search views.
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
.. _wagtailsearch:
|
||||
|
||||
|
||||
Wagtailsearch
|
||||
=============
|
||||
|
||||
Wagtail provides a comprehensive and extensible search interface. In addition, it provides ways to promote search results through "Editor's Picks." Wagtail also collects simple statistics on queries made through the search interface.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
for_python_developers
|
||||
frontend_views
|
||||
editors_picks
|
||||
backends
|
Ładowanie…
Reference in New Issue