зеркало из https://github.com/mozilla/FlightDeck.git
Merge branch 'search' into bug-625954-search_frontend
Conflicts: apps/search/urls.py apps/search/utils.py apps/search/views.py urls.py
This commit is contained in:
Коммит
1bb2a1f6a0
|
@ -1,6 +1,6 @@
|
||||||
<div id="search-bar">
|
<div id="search-bar">
|
||||||
<div class="UI_middleWrapper">
|
<div class="UI_middleWrapper">
|
||||||
<form id="Search" method="get" action="{% url search_results %}">
|
<form id="Search" method="get" action="{% url search.results %}">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label>
|
<label>
|
||||||
<span>Search for</span>
|
<span>Search for</span>
|
||||||
|
@ -10,4 +10,4 @@
|
||||||
<button type="submit">Search</button>
|
<button type="submit">Search</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link rel="stylesheet" href="/media/jetpack/css/UI.Browser.css" />
|
||||||
|
<link rel="stylesheet" href="/media/search/css/Search.css" />
|
||||||
|
{% endblock %}
|
||||||
|
{% block app_body %}
|
||||||
|
{% include "_search_form.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block app_sidebar %}
|
||||||
|
{% include "search_filter.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block app_content %}
|
||||||
|
<section id="SearchResults">
|
||||||
|
{% if addons %}
|
||||||
|
<h2 class="UI_Heading">Addon Results ({{ addon_total }})</h2>
|
||||||
|
{% for package in addons %}
|
||||||
|
{% include "_package_result.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if libraries %}
|
||||||
|
<h2 class="UI_Heading">Library Results ({{ library_total }})</h2>
|
||||||
|
{% for package in libraries %}
|
||||||
|
{% include "_package_result.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link rel="stylesheet" href="/media/jetpack/css/UI.Browser.css"
|
||||||
|
type="text/css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="/media/search/css/Search.css" />
|
||||||
|
{% endblock %}
|
||||||
|
{% block app_body %}
|
||||||
|
{% include "_search_form.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block app_sidebar %}
|
||||||
|
{% include "search_filter.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block app_content %}
|
||||||
|
<section id="SearchResults">
|
||||||
|
{% if addons %}
|
||||||
|
<h2 class="UI_Heading">Addon Results ({{ addon_total }})</h2>
|
||||||
|
{% for package in addons %}
|
||||||
|
{% include "_package_result.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if libraries %}
|
||||||
|
<h2 class="UI_Heading">Library Results ({{ library_total }})</h2>
|
||||||
|
{% for package in libraries %}
|
||||||
|
{% include "_package_result.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -1,25 +1,23 @@
|
||||||
<h2 class="UI_Heading">Narrow Search</h2>
|
<h2 class="UI_Heading">Narrow Search</h2>
|
||||||
<ul class="UI_Action_List">
|
<ul class="UI_Action_List">
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Combined</a>
|
<a href="{% url search.results %}?q={{ q }}">Combined</a>
|
||||||
<strong>({{ addons.count|add:libraries.count }})</strong>
|
<strong>({{ total }})</strong>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Addons</a>
|
<a href="{% url search 'addon' %}?q={{ q }}">Addons</a>
|
||||||
<strong>({{ addons.count }})</strong>
|
<strong>({{ addon_total }})</strong>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Libraries</a>
|
<a href="{% url search 'library' %}?q={{ q }}">Libraries</a>
|
||||||
<strong>({{ libraries.count }})</strong>
|
<strong>({{ library_total }})</strong>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
<ul class="UI_Action_List">
|
<ul class="UI_Action_List">
|
||||||
<li>
|
<li>
|
||||||
<a href="#">By Everyone</a>
|
<a href="{% url search.me %}?q={{ q }}">By Me</a>
|
||||||
<strong>(0)</strong>
|
<strong>({{ my_total }})</strong>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">By Me</a>
|
|
||||||
<strong>(0)</strong>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from django.conf.urls.defaults import url, patterns
|
from django.conf.urls.defaults import url, patterns
|
||||||
|
|
||||||
urlpatterns = patterns('search.views',
|
urlpatterns = patterns('search.views',
|
||||||
url(r'^$', 'results', name='search_results')
|
url(r'^$', 'results', name='search.results'),
|
||||||
|
url(r'^(?P<type_>addon|library)/$', 'search', name='search'),
|
||||||
|
url(r'^me/$', 'me', name='search.me'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,21 +1,93 @@
|
||||||
from django.shortcuts import render_to_response
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.shortcuts import render_to_response, redirect
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.db.models import Q
|
|
||||||
|
from elasticutils import get_es
|
||||||
|
|
||||||
from jetpack.models import Package
|
from jetpack.models import Package
|
||||||
|
|
||||||
def results(r):
|
|
||||||
search_term = r.GET.get('q', '')
|
def render(request, template, data={}):
|
||||||
addons = []
|
return render_to_response(template, data, RequestContext(request))
|
||||||
libraries = []
|
|
||||||
if search_term:
|
|
||||||
results = Package.objects.filter(Q(name__icontains=search_term) | Q(description__icontains=search_term))
|
|
||||||
addons = results.filter(type='a')
|
|
||||||
libraries = results.filter(type='l')
|
|
||||||
|
|
||||||
|
|
||||||
return render_to_response('results.html', {
|
def _get_facets(results):
|
||||||
'addons': addons,
|
facets = results['facets']
|
||||||
'libraries': libraries,
|
type_facets = dict(((z['term'], z['count']) for z in
|
||||||
'q': search_term,
|
facets['type']['terms']))
|
||||||
}, context_instance=RequestContext(r))
|
return type_facets.get('addon', 0), type_facets.get('library', 0)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_packages(results):
|
||||||
|
hits = results['hits']
|
||||||
|
results = {}
|
||||||
|
for type_ in ('a', 'l'):
|
||||||
|
ids = [r['_source']['id'] for r in hits['hits']
|
||||||
|
if r['_source']['type'] == type_]
|
||||||
|
results[type_] = Package.objects.filter(pk__in=ids)
|
||||||
|
return results['a'], results['l']
|
||||||
|
|
||||||
|
|
||||||
|
term_facet = lambda f: {'terms': dict(field=f, size=10)}
|
||||||
|
|
||||||
|
|
||||||
|
def _query(searchq, type_=None, user=None, filter_by_user=False):
|
||||||
|
if searchq:
|
||||||
|
es = get_es()
|
||||||
|
facets = dict(type=term_facet('_type'))
|
||||||
|
if user and user.is_authenticated():
|
||||||
|
facet = term_facet('author')
|
||||||
|
facet['terms']['script'] = 'term == %d ? true : false' % user.id
|
||||||
|
facets['author'] = facet
|
||||||
|
|
||||||
|
query = dict(query=dict(query_string=dict(query=searchq)),
|
||||||
|
facets=facets)
|
||||||
|
|
||||||
|
if type_ in ('addon', 'library'):
|
||||||
|
query['filter'] = {'term': {'_type': type_}}
|
||||||
|
|
||||||
|
# Can filter by user or type, not both.
|
||||||
|
if filter_by_user:
|
||||||
|
query['filter'] = {'term': {'author': user.id}}
|
||||||
|
|
||||||
|
r = es.search(query, 'flightdeck')
|
||||||
|
addon_total, library_total = _get_facets(r)
|
||||||
|
addons, libraries = _get_packages(r)
|
||||||
|
|
||||||
|
data = dict(addon_total=addon_total, library_total=library_total,
|
||||||
|
addons=addons, libraries=libraries,
|
||||||
|
total=r['hits']['total'], q=searchq)
|
||||||
|
|
||||||
|
if user and user.is_authenticated():
|
||||||
|
data['my_total'] = 0
|
||||||
|
facets = r['facets']['author']['terms']
|
||||||
|
if facets:
|
||||||
|
data['my_total'] = facets[0]['count']
|
||||||
|
|
||||||
|
else:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def results(request):
|
||||||
|
"""This aggregates the first results from add-ons and libraries."""
|
||||||
|
q = request.GET.get('q')
|
||||||
|
data = _query(q, user=request.user)
|
||||||
|
return render(request, 'search/results.html', data)
|
||||||
|
|
||||||
|
|
||||||
|
def search(request, type_):
|
||||||
|
"""This is a search into either addons or libraries."""
|
||||||
|
q = request.GET.get('q')
|
||||||
|
data = _query(q, type_, user=request.user)
|
||||||
|
return render(request, 'search/filtered.html', data)
|
||||||
|
|
||||||
|
|
||||||
|
def me(request):
|
||||||
|
if not request.user.is_authenticated():
|
||||||
|
return redirect(reverse('search.results') + '?' +
|
||||||
|
request.META['QUERY_STRING'])
|
||||||
|
q = request.GET.get('q')
|
||||||
|
data = _query(q, user=request.user, filter_by_user=True)
|
||||||
|
return render(request, 'search/filtered.html', data)
|
||||||
|
|
|
@ -119,7 +119,7 @@ JETPACK_ITEMS_PER_PAGE = 10
|
||||||
JETPACK_LIB_DIR = 'lib'
|
JETPACK_LIB_DIR = 'lib'
|
||||||
JETPACK_DATA_DIR = 'data'
|
JETPACK_DATA_DIR = 'data'
|
||||||
|
|
||||||
ATTACHMENT_MAX_FILESIZE = 100*1024*1024 # 100kb
|
ATTACHMENT_MAX_FILESIZE = 100 * 1024 * 1024 # 100kb
|
||||||
|
|
||||||
PYTHON_EXEC = 'python'
|
PYTHON_EXEC = 'python'
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ INSTALLED_APPS = [
|
||||||
# FLIGHTDECK APPS
|
# FLIGHTDECK APPS
|
||||||
'base', # basic flightdeck things (utils, urls)
|
'base', # basic flightdeck things (utils, urls)
|
||||||
'person', # user related stuff (profile etc.)
|
'person', # user related stuff (profile etc.)
|
||||||
'search', # ElasticSearch and related stuff.
|
'search', # ElasticSearch and search views.
|
||||||
'amo', # currently addons.mozilla.org authentication
|
'amo', # currently addons.mozilla.org authentication
|
||||||
'jetpack', # Jetpack functionality
|
'jetpack', # Jetpack functionality
|
||||||
'xpi', # XPI management
|
'xpi', # XPI management
|
||||||
|
|
7
urls.py
7
urls.py
|
@ -5,10 +5,7 @@ from django.conf import settings
|
||||||
from base import views as base_views
|
from base import views as base_views
|
||||||
|
|
||||||
|
|
||||||
urls = [
|
urls = [url(r'^$', base_views.homepage, name='home')]
|
||||||
# home
|
|
||||||
url(r'^$', base_views.homepage, name='home'),
|
|
||||||
]
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|
||||||
|
@ -30,10 +27,8 @@ urls.extend([
|
||||||
# API Browser
|
# API Browser
|
||||||
(r'^api/', include('api.urls')),
|
(r'^api/', include('api.urls')),
|
||||||
|
|
||||||
# Tutorial
|
|
||||||
(r'^tutorial/', include('tutorial.urls')),
|
(r'^tutorial/', include('tutorial.urls')),
|
||||||
|
|
||||||
# Person
|
|
||||||
(r'^user/', include('person.urls')),
|
(r'^user/', include('person.urls')),
|
||||||
|
|
||||||
# Search
|
# Search
|
||||||
|
|
Загрузка…
Ссылка в новой задаче