0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-12-01 11:41:20 +01:00

Added searchpicks admin views

This commit is contained in:
Karl Hobley 2015-04-24 10:38:59 +01:00
parent df20340060
commit 0c7f00e078
14 changed files with 789 additions and 0 deletions

View File

@ -0,0 +1,10 @@
from django.conf.urls import url
from wagtail.contrib.wagtailsearchpicks import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^add/$', views.add, name='add'),
url(r'^(\d+)/$', views.edit, name='edit'),
url(r'^(\d+)/delete/$', views.delete, name='delete'),
]

View File

@ -0,0 +1,57 @@
from django import forms
from django.forms.models import inlineformset_factory
from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin.widgets import AdminPageChooser
from wagtail.wagtailsearch import models
class SearchPickForm(forms.ModelForm):
sort_order = forms.IntegerField(required=False)
def __init__(self, *args, **kwargs):
super(SearchPickForm, self).__init__(*args, **kwargs)
self.fields['page'].widget = AdminPageChooser()
class Meta:
model = models.EditorsPick
fields = ('query', 'page', 'description')
widgets = {
'description': forms.Textarea(attrs=dict(rows=3)),
}
SearchPicksFormSetBase = inlineformset_factory(models.Query, models.EditorsPick, form=SearchPickForm, can_order=True, can_delete=True, extra=0)
class SearchPicksFormSet(SearchPicksFormSetBase):
minimum_forms = 1
minimum_forms_message = _("Please specify at least one recommendation for this search term.")
def add_fields(self, form, *args, **kwargs):
super(SearchPicksFormSet, self).add_fields(form, *args, **kwargs)
# Hide delete and order fields
form.fields['DELETE'].widget = forms.HiddenInput()
form.fields['ORDER'].widget = forms.HiddenInput()
# Remove query field
del form.fields['query']
def clean(self):
# Search pick must have at least one recommended page to be valid
# Check there is at least one non-deleted form.
non_deleted_forms = self.total_form_count()
non_empty_forms = 0
for i in range(0, self.total_form_count()):
form = self.forms[i]
if self.can_delete and self._should_delete_form(form):
non_deleted_forms -= 1
if not (form.instance.id is None and not form.has_changed()):
non_empty_forms += 1
if (
non_deleted_forms < self.minimum_forms
or non_empty_forms < self.minimum_forms
):
raise forms.ValidationError(self.minimum_forms_message)

View File

@ -0,0 +1,48 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% trans "Add search pick" %}{% endblock %}
{% block content %}
{% trans "Add search pick" as add_str %}
{% include "wagtailadmin/shared/header.html" with title=add_str icon="pick" %}
<div class="nice-padding">
<div class="help-block help-info">
{% blocktrans %}
<p>Promoted search results are a means of recommending specific pages that might not organically come high up in search results. E.g recommending your primary donation page to a user searching with the less common term "<em>giving</em>".</p>
{% endblocktrans %}
{% blocktrans %}
<p>The "Search term(s)/phrase" field below must contain the full and exact search for which you wish to provide recommended results, <em>including</em> any misspellings/user error. To help, you can choose from search terms that have been popular with users of your site.</p>
{% endblocktrans %}
</div>
<form action="{% url 'wagtailsearchpicks:add' %}" method="POST">
{% csrf_token %}
<ul class="fields">
<li>
{% include "wagtailsearch/queries/chooser_field.html" with field=query_form.query_string only %}
</li>
<li>
{% include "wagtailsearchpicks/includes/searchpicks_formset.html" with formset=searchpicks_formset only %}
</li>
<li><input type="submit" value="{% trans 'Save' %}" /></li>
</ul>
</form>
</div>
{% endblock %}
{% block extra_css %}
{% include "wagtailadmin/pages/_editor_css.html" %}
{% endblock %}
{% block extra_js %}
{% include "wagtailadmin/pages/_editor_js.html" %}
<script type="text/javascript">
{% include "wagtailsearchpicks/includes/searchpicks_formset.js" with formset=searchpicks_formset only %}
{% include "wagtailsearch/queries/chooser_field.js" only %}
$(function() {
createQueryChooser('{{ query_form.query_string.auto_id }}');
});
</script>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% blocktrans with query=query.query_string %}Delete {{ query }}{% endblocktrans %}{% endblock %}
{% block content %}
{% trans "Delete" as delete_str %}
{% include "wagtailadmin/shared/header.html" with title=delete_str subtitle=query.query_string %}
<div class="nice-padding">
<p>{% trans "Are you sure you want to delete all promoted results for this search term?" %}</p>
<form action="{% url 'wagtailsearchpicks:delete' query.id %}" method="POST">
{% csrf_token %}
<input type="submit" value="{% trans 'Yes, delete' %}" class="serious" />
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,40 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% blocktrans with query=query.query_string %}Editing {{ query }}{% endblocktrans %}{% endblock %}
{% block content %}
{% trans "Editing" as editing_str %}
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=query.query_string icon="pick" %}
<form action="{% url 'wagtailsearchpicks:edit' query.id %}" method="POST" class="nice-padding">
{% csrf_token %}
<ul class="fields">
<li>
{% include "wagtailsearch/queries/chooser_field.html" with field=query_form.query_string only %}
</li>
<li>
{% include "wagtailsearchpicks/includes/searchpicks_formset.html" with formset=searchpicks_formset only %}
</li>
<li>
<input type="submit" value="{% trans 'Save' %}" />
<a href="{% url 'wagtailsearchpicks:delete' query.id %}" class="button button-secondary no">{% trans "Delete" %}</a>
</li>
</ul>
</form>
{% endblock %}
{% block extra_css %}
{% include "wagtailadmin/pages/_editor_css.html" %}
{% endblock %}
{% block extra_js %}
{% include "wagtailadmin/pages/_editor_js.html" %}
<script type="text/javascript">
{% include "wagtailsearchpicks/includes/searchpicks_formset.js" with formset=searchpicks_formset only %}
{% include "wagtailsearch/queries/chooser_field.js" only %}
$(function() {
createQueryChooser('{{ query_form.query_string.auto_id }}');
});
</script>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% load i18n %}
<li id="inline_child_{{ form.prefix }}"{% if form.DELETE.value %} style="display: none;"{% endif %}>
<ul class="controls">
<li><button class="icon text-replace icon-order-up inline-child-move-up" id="{{ form.prefix }}-move-up">{% trans "Move up" %}</button></li>
<li><button class="icon text-replace icon-order-down inline-child-move-down" id="{{ form.prefix }}-move-down">{% trans "Move down" %}</button></li>
<li><button class="icon text-replace icon-bin" id="{{ form.DELETE.id_for_label }}-button">{% trans "Delete" %}</button></li>
</ul>
<fieldset>
<legend>{% trans "Promoted search result" %}</legend>
<ul class="fields">
<li class="model_choice_field">
{% include "wagtailadmin/shared/field.html" with field=form.page only %}
</li>
<li class="char_field">
{% include "wagtailadmin/shared/field.html" with field=form.description only %}
</li>
</ul>
{{ form.id }}
{{ form.ORDER }}
{{ form.DELETE }}
</fieldset>
</li>

View File

@ -0,0 +1,17 @@
{% load i18n wagtailadmin_tags %}
{{ formset.management_form }}
<ul class="multiple" id="id_{{ formset.prefix }}-FORMS">
{% for form in formset.forms %}
{% include "wagtailsearchpicks/includes/searchpick_form.html" with form=form only %}
{% endfor %}
</ul>
<script type="text/django-form-template" id="id_{{ formset.prefix }}-EMPTY_FORM_TEMPLATE">
{% escapescript %}
{% include "wagtailsearchpicks/includes/searchpick_form.html" with form=formset.empty_form only %}
{% endescapescript %}
</script>
<p class="add">
<a class="button bicolor icon icon-plus" id="id_{{ formset.prefix }}-ADD" value="Add">{% trans "Add recommended page" %}</a>
</p>

View File

@ -0,0 +1,13 @@
$(function() {
var panel = InlinePanel({
formsetPrefix: "id_{{ formset.prefix }}",
emptyChildFormPrefix: "{{ formset.empty_form.prefix }}",
canOrder: true
});
{% for form in formset.forms %}
panel.initChildControls('{{ formset.prefix }}-{{ forloop.counter0 }}');
{% endfor %}
panel.updateMoveButtonDisabledStates();
});

View File

@ -0,0 +1,26 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% trans "Search Terms" %}{% endblock %}
{% block bodyclass %}menu-editorspicks{% endblock %}
{% block extra_js %}
<script>
window.headerSearch = {
url: "{% url 'wagtailsearchpicks:index' %}",
termInput: "#id_q",
targetOutput: "#editorspicks-results"
}
</script>
{% endblock %}
{% block content %}
{% trans "Promoted search results" as sp_title_str %}
{% trans "Add new promoted result" as sp_text_str %}
{% include "wagtailadmin/shared/header.html" with title=sp_title_str add_link="wagtailsearchpicks:add" icon="pick" add_text=sp_text_str search_url="wagtailsearchpicks:index" %}
<div class="nice-padding">
<div id="editorspicks-results" class="redirects">
{% include "wagtailsearchpicks/results.html" %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,30 @@
{% load i18n %}
<table class="listing">
<col width="40%" />
<col width="40%"/>
<col />
<thead>
<tr>
<th class="title">{% trans "Search term(s)" %}</th>
<th>{% trans "Promoted results" %}</th>
<th>{% trans "Views (past week)" %}</th>
</tr>
</thead>
<tbody>
{% for query in queries %}
<tr>
<td class="title">
<h2><a href="{% url 'wagtailsearchpicks:edit' query.id %}" title="{% trans 'Edit this pick' %}">{{ query.query_string }}</a></h2>
</td>
<td>
{% for searchpick in query.editors_picks.all %}
<a href="{% url 'wagtailadmin_pages:edit' searchpick.page.id %}" class="nolink">{{ searchpick.page.title }}</a>{% if not forloop.last %}, {% endif %}
{% empty %}
{% trans "None" %}
{% endfor %}
</td>
<td>{{ query.hits }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,23 @@
{% load i18n %}
{% if queries %}
{% if is_searching %}
<h2>
{% blocktrans count counter=queries|length %}
There is one match
{% plural %}
There are {{ counter }} matches
{% endblocktrans %}
</h2>
{% endif %}
{% include "wagtailsearchpicks/list.html" %}
{% include "wagtailadmin/shared/pagination_nav.html" with items=queries is_searching=is_searching linkurl="wagtailsearchpicks_index" %}
{% else %}
{% if is_searching %}
<p>{% blocktrans %}Sorry, no promoted results match "<em>{{ query_string }}</em>"{% endblocktrans %}</p>
{% else %}
{% url 'wagtailsearchpicks:add' as wagtailsearchpicks_add_url %}
<p>{% blocktrans %}No promoted results have been created. Why not <a href="{{ wagtailsearchpicks_add_url }}">add one</a>?{% endblocktrans %}</p>
{% endif %}
{% endif %}

View File

@ -0,0 +1,311 @@
from django.test import TestCase
from django.core.urlresolvers import reverse
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailsearch import models
class TestSearchPicks(TestCase):
def test_search_pick_create(self):
# Create a search pick to the root page
models.EditorsPick.objects.create(
query=models.Query.get("root page"),
page_id=1,
sort_order=0,
description="First search pick",
)
# Check
self.assertEqual(models.Query.get("root page").editors_picks.count(), 1)
self.assertEqual(models.Query.get("root page").editors_picks.first().page_id, 1)
def test_search_pick_ordering(self):
# Add 3 search picks in a different order to their sort_order values
# They should be ordered by their sort order values and not their insertion order
models.EditorsPick.objects.create(
query=models.Query.get("root page"),
page_id=1,
sort_order=0,
description="First search pick",
)
models.EditorsPick.objects.create(
query=models.Query.get("root page"),
page_id=1,
sort_order=2,
description="Last search pick",
)
models.EditorsPick.objects.create(
query=models.Query.get("root page"),
page_id=1,
sort_order=1,
description="Middle search pick",
)
# Check
self.assertEqual(models.Query.get("root page").editors_picks.count(), 3)
self.assertEqual(models.Query.get("root page").editors_picks.first().description, "First search pick")
self.assertEqual(models.Query.get("root page").editors_picks.last().description, "Last search pick")
class TestSearchPicksIndexView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def test_simple(self):
response = self.client.get(reverse('wagtailsearchpicks:index'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/index.html')
def test_search(self):
response = self.client.get(reverse('wagtailsearchpicks:index'), {'q': "Hello"})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['query_string'], "Hello")
def make_search_picks(self):
for i in range(50):
models.EditorsPick.objects.create(
query=models.Query.get("query " + str(i)),
page_id=1,
sort_order=0,
description="First search pick",
)
def test_pagination(self):
self.make_search_picks()
response = self.client.get(reverse('wagtailsearchpicks:index'), {'p': 2})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/index.html')
# Check that we got the correct page
self.assertEqual(response.context['queries'].number, 2)
def test_pagination_invalid(self):
self.make_search_picks()
response = self.client.get(reverse('wagtailsearchpicks:index'), {'p': 'Hello World!'})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/index.html')
# Check that we got page one
self.assertEqual(response.context['queries'].number, 1)
def test_pagination_out_of_range(self):
self.make_search_picks()
response = self.client.get(reverse('wagtailsearchpicks:index'), {'p': 99999})
# Check response
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/index.html')
# Check that we got the last page
self.assertEqual(response.context['queries'].number, response.context['queries'].paginator.num_pages)
class TestSearchPicksAddView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def test_simple(self):
response = self.client.get(reverse('wagtailsearchpicks:add'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/add.html')
def test_post(self):
# Submit
post_data = {
'query_string': "test",
'editors_picks-TOTAL_FORMS': 1,
'editors_picks-INITIAL_FORMS': 0,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Hello",
}
response = self.client.post(reverse('wagtailsearchpicks:add'), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearchpicks:index'))
# Check that the search pick was created
self.assertTrue(models.Query.get('test').editors_picks.filter(page_id=1).exists())
def test_post_without_recommendations(self):
# Submit
post_data = {
'query_string': "test",
'editors_picks-TOTAL_FORMS': 0,
'editors_picks-INITIAL_FORMS': 0,
'editors_picks-MAX_NUM_FORMS': 1000,
}
response = self.client.post(reverse('wagtailsearchpicks:add'), post_data)
# User should be given an error
self.assertEqual(response.status_code, 200)
self.assertFormsetError(response, 'searchpicks_formset', None, None, "Please specify at least one recommendation for this search term.")
class TestSearchPicksEditView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
# Create an search pick to edit
self.query = models.Query.get("Hello")
self.search_pick = self.query.editors_picks.create(page_id=1, description="Root page")
self.search_pick_2 = self.query.editors_picks.create(page_id=2, description="Homepage")
def test_simple(self):
response = self.client.get(reverse('wagtailsearchpicks:edit', args=(self.query.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/edit.html')
def test_post(self):
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.search_pick.id,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Description has changed", # Change
'editors_picks-1-id': self.search_pick_2.id,
'editors_picks-1-DELETE': '',
'editors_picks-1-ORDER': 1,
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearchpicks:edit', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearchpicks:index'))
# Check that the search pick description was edited
self.assertEqual(models.EditorsPick.objects.get(id=self.search_pick.id).description, "Description has changed")
def test_post_reorder(self):
# Check order before reordering
self.assertEqual(models.Query.get("Hello").editors_picks.all()[0], self.search_pick)
self.assertEqual(models.Query.get("Hello").editors_picks.all()[1], self.search_pick_2)
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.search_pick.id,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 1, # Change
'editors_picks-0-page': 1,
'editors_picks-0-description': "Root page",
'editors_picks-1-id': self.search_pick_2.id,
'editors_picks-1-DELETE': '',
'editors_picks-1-ORDER': 0, # Change
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearchpicks:edit', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearchpicks:index'))
# Check that the ordering has been saved correctly
self.assertEqual(models.EditorsPick.objects.get(id=self.search_pick.id).sort_order, 1)
self.assertEqual(models.EditorsPick.objects.get(id=self.search_pick_2.id).sort_order, 0)
# Check that the recommendations were reordered
self.assertEqual(models.Query.get("Hello").editors_picks.all()[0], self.search_pick_2)
self.assertEqual(models.Query.get("Hello").editors_picks.all()[1], self.search_pick)
def test_post_delete_recommendation(self):
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.search_pick.id,
'editors_picks-0-DELETE': '',
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Root page",
'editors_picks-1-id': self.search_pick_2.id,
'editors_picks-1-DELETE': 1,
'editors_picks-1-ORDER': 1,
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearchpicks:edit', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearchpicks:index'))
# Check that the recommendation was deleted
self.assertFalse(models.EditorsPick.objects.filter(id=self.search_pick_2.id).exists())
# The other recommendation should still exist
self.assertTrue(models.EditorsPick.objects.filter(id=self.search_pick.id).exists())
def test_post_without_recommendations(self):
# Submit
post_data = {
'query_string': "Hello",
'editors_picks-TOTAL_FORMS': 2,
'editors_picks-INITIAL_FORMS': 2,
'editors_picks-MAX_NUM_FORMS': 1000,
'editors_picks-0-id': self.search_pick.id,
'editors_picks-0-DELETE': 1,
'editors_picks-0-ORDER': 0,
'editors_picks-0-page': 1,
'editors_picks-0-description': "Description has changed", # Change
'editors_picks-1-id': self.search_pick_2.id,
'editors_picks-1-DELETE': 1,
'editors_picks-1-ORDER': 1,
'editors_picks-1-page': 2,
'editors_picks-1-description': "Homepage",
}
response = self.client.post(reverse('wagtailsearchpicks:edit', args=(self.query.id, )), post_data)
# User should be given an error
self.assertEqual(response.status_code, 200)
self.assertFormsetError(response, 'searchpicks_formset', None, None, "Please specify at least one recommendation for this search term.")
class TestSearchPicksDeleteView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
# Create an search pick to delete
self.query = models.Query.get("Hello")
self.search_pick = self.query.editors_picks.create(page_id=1, description="Root page")
self.search_pick_2 = self.query.editors_picks.create(page_id=2, description="Homepage")
def test_simple(self):
response = self.client.get(reverse('wagtailsearchpicks:delete', args=(self.query.id, )))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailsearchpicks/confirm_delete.html')
def test_post(self):
# Submit
post_data = {
'foo': 'bar',
}
response = self.client.post(reverse('wagtailsearchpicks:delete', args=(self.query.id, )), post_data)
# User should be redirected back to the index
self.assertRedirects(response, reverse('wagtailsearchpicks:index'))
# Check that both recommendations were deleted
self.assertFalse(models.EditorsPick.objects.filter(id=self.search_pick_2.id).exists())
# The other recommendation should still exist
self.assertFalse(models.EditorsPick.objects.filter(id=self.search_pick.id).exists())

View File

@ -0,0 +1,149 @@
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.utils.translation import ugettext as _
from django.views.decorators.vary import vary_on_headers
from wagtail.wagtailsearch import models, forms as search_forms
from wagtail.wagtailadmin.forms import SearchForm
from wagtail.wagtailadmin import messages
from wagtail.contrib.wagtailsearchpicks import forms
@vary_on_headers('X-Requested-With')
def index(request):
is_searching = False
page = request.GET.get('p', 1)
query_string = request.GET.get('q', "")
queries = models.Query.objects.filter(editors_picks__isnull=False).distinct()
# Search
if query_string:
queries = queries.filter(query_string__icontains=query_string)
is_searching = True
# Pagination
paginator = Paginator(queries, 20)
try:
queries = paginator.page(page)
except PageNotAnInteger:
queries = paginator.page(1)
except EmptyPage:
queries = paginator.page(paginator.num_pages)
if request.is_ajax():
return render(request, "wagtailsearchpicks/results.html", {
'is_searching': is_searching,
'queries': queries,
'query_string': query_string,
})
else:
return render(request, 'wagtailsearchpicks/index.html', {
'is_searching': is_searching,
'queries': queries,
'query_string': query_string,
'search_form': SearchForm(data=dict(q=query_string) if query_string else None, placeholder=_("Search editor's picks")),
})
def save_searchpicks(query, new_query, searchpicks_formset):
# Save
if searchpicks_formset.is_valid():
# Set sort_order
for i, form in enumerate(searchpicks_formset.ordered_forms):
form.instance.sort_order = i
# Make sure the form is marked as changed so it gets saved with the new order
form.has_changed = lambda: True
searchpicks_formset.save()
# If query was changed, move all search picks to the new query
if query != new_query:
searchpicks_formset.get_queryset().update(query=new_query)
return True
else:
return False
def add(request):
if request.POST:
# Get query
query_form = search_forms.QueryForm(request.POST)
if query_form.is_valid():
query = models.Query.get(query_form['query_string'].value())
# Save search picks
searchpicks_formset = forms.SearchPicksFormSet(request.POST, instance=query)
if save_searchpicks(query, query, searchpicks_formset):
messages.success(request, _("Editor's picks for '{0}' created.").format(query), buttons=[
messages.button(reverse('wagtailsearchpicks:edit', args=(query.id,)), _('Edit'))
])
return redirect('wagtailsearchpicks:index')
else:
if len(searchpicks_formset.non_form_errors()):
messages.error(request, " ".join(error for error in searchpicks_formset.non_form_errors())) # formset level error (e.g. no forms submitted)
else:
messages.error(request, _("Recommendations have not been created due to errors")) # specific errors will be displayed within form fields
else:
searchpicks_formset = forms.SearchPicksFormSet()
else:
query_form = search_forms.QueryForm()
searchpicks_formset = forms.SearchPicksFormSet()
return render(request, 'wagtailsearchpicks/add.html', {
'query_form': query_form,
'searchpicks_formset': searchpicks_formset,
})
def edit(request, query_id):
query = get_object_or_404(models.Query, id=query_id)
if request.POST:
# Get query
query_form = search_forms.QueryForm(request.POST)
# and the recommendations
searchpicks_formset = forms.SearchPicksFormSet(request.POST, instance=query)
if query_form.is_valid():
new_query = models.Query.get(query_form['query_string'].value())
# Save search picks
if save_searchpicks(query, new_query, searchpicks_formset):
messages.success(request, _("Editor's picks for '{0}' updated.").format(new_query), buttons=[
messages.button(reverse('wagtailsearchpicks:edit', args=(query.id,)), _('Edit'))
])
return redirect('wagtailsearchpicks:index')
else:
if len(searchpicks_formset.non_form_errors()):
messages.error(request, " ".join(error for error in searchpicks_formset.non_form_errors())) # formset level error (e.g. no forms submitted)
else:
messages.error(request, _("Recommendations have not been saved due to errors")) # specific errors will be displayed within form fields
else:
query_form = search_forms.QueryForm(initial=dict(query_string=query.query_string))
searchpicks_formset = forms.SearchPicksFormSet(instance=query)
return render(request, 'wagtailsearchpicks/edit.html', {
'query_form': query_form,
'searchpicks_formset': searchpicks_formset,
'query': query,
})
def delete(request, query_id):
query = get_object_or_404(models.Query, id=query_id)
if request.POST:
query.editors_picks.all().delete()
messages.success(request, _("Editor's picks deleted."))
return redirect('wagtailsearchpicks:index')
return render(request, 'wagtailsearchpicks/confirm_delete.html', {
'query': query,
})

View File

@ -0,0 +1,26 @@
from django.core import urlresolvers
from django.conf.urls import include, url
from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailcore import hooks
from wagtail.contrib.wagtailsearchpicks import admin_urls
from wagtail.wagtailadmin.menu import MenuItem
@hooks.register('register_admin_urls')
def register_admin_urls():
return [
url(r'^searchpicks/', include(admin_urls, namespace='wagtailsearchpicks')),
]
class SearchPicksMenuItem(MenuItem):
def is_shown(self, request):
# TEMPORARY: Only show if the user is a superuser
return request.user.is_superuser
@hooks.register('register_settings_menu_item')
def register_search_picks_menu_item():
return SearchPicksMenuItem(_('Promoted search results'), urlresolvers.reverse('wagtailsearchpicks:index'), classnames='icon icon-pick', order=900)