Skip to content

Commit

Permalink
Implementation of django-haystack
Browse files Browse the repository at this point in the history
  • Loading branch information
Andreu Vallbona committed Jul 26, 2016
1 parent b6ebd57 commit f2c0962
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 16 deletions.
22 changes: 22 additions & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Then you've to append :code:`transmanager` and :code:`django_tables2` to :code:`
...
'transmanager',
'django_tables2',
'haystack',
)
Expand All @@ -25,3 +26,24 @@ command in order to generate the translations tasks.
:code:`python manage.py generate_tasks`


As **Transmanager** comes with a translations suggestion system enable by default, we have to generate
the index of the suggestions, which relies on a haystack search index. First we need to add the HAYSTACK_CONNECTIONS
to the main app settings:

.. code-block:: python
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
},
}
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
It's recommended to activate the realtime signal processos in order to have the search index updated.
You can also cron the command :code:`python manage.py update_index`.
Take a look to the Django-haystack documentation_ for further information.

.. _documentation: http://django-haystack.readthedocs.io/en/latest/tutorial.html


9 changes: 9 additions & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ Number of chars that we want to show from the value to translate in the translat



TM_HAYSTACK_DISABLED
--------------------
This property allow us to disable the enabled by default suggestion system via the "haystack" search engine.
Default ``False``.


TM_HAYSTACK_SUGGESTIONS_MAX_NUMBER
----------------------------------
Maximum number of translation suggestions we want to show in the translation task edit form. Default ``20``.
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
haystack
alabaster==0.7.8
argh==0.26.2
Babel==2.3.4
Expand Down Expand Up @@ -35,3 +36,5 @@ xlrd==0.9.4
XlsxWriter==0.8.9
django-bootstrap-pagination==1.5.1
django-tables2==1.2.3
django-haystack==2.5.0
Whoosh==2.7.4
37 changes: 33 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@

import os
import re
import codecs
from setuptools import find_packages, setup

with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
Expand All @@ -7,17 +10,41 @@
# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))


def get_version(package):
"""
Return package version as listed in `__version__` in `init.py`.
"""
init_py = codecs.open(os.path.join(package, '__init__.py'), encoding='utf-8').read()
return re.search("^__version__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)


def get_author(package):
"""
Return package author as listed in `__author__` in `init.py`.
"""
init_py = codecs.open(os.path.join(package, '__init__.py'), encoding='utf-8').read()
return re.search("^__author__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)


def get_email(package):
"""
Return package email as listed in `__email__` in `init.py`.
"""
init_py = codecs.open(os.path.join(package, '__init__.py'), encoding='utf-8').read()
return re.search("^__email__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)

setup(
name='transmanager',
version='0.2.4',
version=get_version('transmanager'),
packages=find_packages(),
include_package_data=True,
license='BSD License',
description='A simple Django app to deal with the model content translation tasks',
long_description=README,
url='https://github.com/APSL/transmanager',
author='Andreu Vallbona',
author_email='[email protected]',
author=get_author('transmanager'),
author_email=get_email('transmanager'),
install_requires=[
'django',
'django-filter',
Expand All @@ -28,6 +55,8 @@
'djangorestframework',
'django-yubin',
'django-tables2',
'django-haystack',
'whoosh'
],
classifiers=[
'Environment :: Web Environment',
Expand All @@ -44,4 +73,4 @@
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.9',
],
)
)
2 changes: 1 addition & 1 deletion transmanager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

__author__ = 'Andreu Vallbona'
__email__ = '[email protected]'
__version__ = '0.2.4'
__version__ = '0.2.5'

default_app_config = 'transmanager.apps.TransManagerConfig'
4 changes: 2 additions & 2 deletions transmanager/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ class Meta:
'object_field_label': forms.TextInput(attrs={'readonly': 'readonly'}),
'number_of_words': forms.TextInput(attrs={'readonly': 'readonly'}),
'object_field_value': forms.Textarea(attrs={'readonly': 'readonly'}),
'user': forms.Select(attrs={'readonly': 'readonly'}),
'language': forms.Select(attrs={'readonly': 'readonly'}),
'user': forms.Select(attrs={'readonly': 'readonly', 'disabled': 'disabled'}),
'language': forms.Select(attrs={'readonly': 'readonly', 'disabled': 'disabled'}),
}
21 changes: 21 additions & 0 deletions transmanager/search_indexes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- encoding: utf-8 -*-

import datetime
from haystack import indexes
from .models import TransTask


class TransTaskIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
object_field_value_translation = indexes.CharField(model_attr='object_field_value_translation', null=True)
language = indexes.CharField(model_attr='language')
user = indexes.CharField(model_attr='user')

def get_model(self):
return TransTask

def index_queryset(self, using=None):
"""
Used when the entire index for model is updated.
"""
return self.get_model().objects.filter(date_creation__lte=datetime.datetime.now())
2 changes: 2 additions & 0 deletions transmanager/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
TM_DEFAULT_ENABLED_ATTRIBUTE_NAME = getattr(settings, 'TRANSMANAGER_DEFAULT_ENABLED_ATTRIBUTE_NAME', 'enabled')
TM_BRAND_LOGO_URL = getattr(settings, 'TM_BRAND_LOGO_URL', 'transmanager/img/logo.png')
TM_ORIGINAL_VALUE_CHARS_NUMBER = getattr(settings, 'TM_ORIGINAL_VALUE_CHARS_NUMBER', 100)
TM_HAYSTACK_DISABLED = getattr(settings, 'TM_HAYSTACK_DISABLED', False)
TM_HAYSTACK_SUGGESTIONS_MAX_NUMBER = getattr(settings, 'TM_HAYSTACK_SUGGESTIONS_MAX_NUMBER', 20)
28 changes: 27 additions & 1 deletion transmanager/static/transmanager/css/transmanager.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ form.filter {
margin: 0 0 20px 0;
min-height: 45px;
}

form.filter input {
border-radius: 4px;
border:1px solid #ccc;
Expand Down Expand Up @@ -86,3 +85,30 @@ a.navbar-brand {
/*background: url(../img/logo.png) 0 -50px no-repeat;*/
padding:10px;
}

table#taskList td.detail {
text-align: center;
}

div#suggestions {
clear: both;
float: none;
margin:20px auto 0 auto;
padding-bottom: 100px;
overflow: hidden;
}
div#suggestions table td {
padding:5px;
}

div#suggestions table td:first-child {
width:2%;
text-align: center;
}
div#suggestions table td.translated {
width:46%;
}
div#suggestions table td:last-child{
width:6%;
text-align: center;
}
6 changes: 6 additions & 0 deletions transmanager/static/transmanager/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,11 @@ $(document).ready(function(){
e.preventDefault();
$(this).closest('form').find("input[type=text]").val("").end().find("select").val('').end().submit();
});

$('body').on('click', '.get-translation', function(e){
e.preventDefault();
var value = $(this).closest('td').prev().html();
$('#id_object_field_value_translation').val(value);
});

});
11 changes: 7 additions & 4 deletions transmanager/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Meta:
fields = ('user', 'language', 'object_name', 'object_pk', 'object_field_label', 'object_field_value',
'number_of_words', 'date_creation', 'date_modification', 'done', 'detail')
empty_text = _('No se han encontrado resultados')
attrs = {'class': 'table table-bordered table-hover table-condensed'}
attrs = {'class': 'table table-bordered table-hover table-condensed', 'id': 'taskList'}
template = 'table.html'

def __init__(self, *args, **kwargs):
Expand All @@ -35,8 +35,11 @@ def render_object_field_value(self, record, value):

def render_detail(self, record, value):
url = reverse('transmanager-task-detail', kwargs={'pk': record.id})
text = _('Editar')
if self.GET:
return mark_safe('<a href="{0}?{1}">{2}</a>'.format(url, self.GET.urlencode(), text))
return mark_safe('<a href="{0}?{1}">'
'<i class="fa fa-pencil-square-o" aria-hidden="true"></i> '
'</a>'.format(url, self.GET.urlencode()))
else:
return mark_safe('<a href="{0}">{1}</a>'.format(url, text))
return mark_safe('<a href="{0}">'
'<i class="fa fa-pencil-square-o" aria-hidden="true"></i> '
'</a>'.format(url))
33 changes: 32 additions & 1 deletion transmanager/templates/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{% block content %}
<link rel="stylesheet" href="{% static 'transmanager/css/transmanager.css' %}" type="text/css" media="screen"/>
<div id="task-form" class="col-xs-4 center-block">
<div id="task-form" class="col-xs-12 col-md-8 center-block">
<form action="{% url 'transmanager-task-detail' object.id %}?{{ request.GET.urlencode }}" method="post">
{% csrf_token %}
<table>
Expand All @@ -15,4 +15,35 @@
<input id="bsend" name="bsend" type="submit" value="{% trans 'Guardar' %}" class="btn btn-primary pull-right" />
</form>
</div>
{% if sqs %}
<div id="suggestions" class="col-xs-12 col-md-8 center-block">
<h3>{% trans 'Sugerencias' %}</h3>
<table border="1" class="col-xs-12">
{% for item in sqs %}
{% if item.pk != obj_id %}
<tr>
<td nowrap>
<a href="{% url 'transmanager-task-detail' item.pk %}?{{ request.GET.urlencode }}">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
</a>
</td>
<td class="original">{{ item.object.object_field_value }}</td>
<td class="translated">{{ item.object.object_field_value_translation }}</td>
<td><a href="#" class="get-translation">
<i class="fa fa-flag-o" aria-hidden="true"></i>
{% trans 'Usar traducción' %}
</a>
</td>
</tr>
{% endif %}
{% empty %}
<tr>
<td colspan="4">
{% trans 'No se han encontrado sugerencias' %}
</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{ object.object_field_value }}
{{ object.object_field_value_translation }}
{{ object.user }}
{{ object.language.code }}
14 changes: 11 additions & 3 deletions transmanager/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.views.generic import ListView, UpdateView
from django_tables2 import SingleTableView, RequestConfig
from django_yubin.messages import TemplatedHTMLEmailMessageView
from haystack.query import SearchQuerySet

from rest_framework.views import APIView
from rest_framework.response import Response
Expand All @@ -20,7 +21,7 @@
from .forms import TaskForm
from .filters.filters import TaskFilter
from .permissions import AuthenticationMixin
from .settings import TM_ORIGINAL_VALUE_CHARS_NUMBER
from .settings import TM_ORIGINAL_VALUE_CHARS_NUMBER, TM_HAYSTACK_DISABLED, TM_HAYSTACK_SUGGESTIONS_MAX_NUMBER


# class TaskListView(AuthenticationMixin, ListView):
Expand Down Expand Up @@ -78,6 +79,14 @@ class TaskDetailView(AuthenticationMixin, UpdateView):
form_class = TaskForm
template_name = 'detail.html'

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if not TM_HAYSTACK_DISABLED:
sqs = SearchQuerySet().filter(content=self.object.object_field_value).filter(language=self.object.language)
context['sqs'] = sqs[:TM_HAYSTACK_SUGGESTIONS_MAX_NUMBER]
context['obj_id'] = str(self.object.id)
return context

def get_success_url(self):
url = '{}?{}'.format(reverse('transmanager-task-list'), self.request.GET.urlencode())
return url
Expand All @@ -97,10 +106,9 @@ def get_initial(self):
return initial


# @todo resolve permission to post/delete to the API
# @todo resolve permission to post/delete to the API
# class TaskBulksView(AuthenticationMixin, APIView):
class TaskBulksView(APIView):

"""
Handles the bulk addtion of translation tasks
POST creates translations
Expand Down

0 comments on commit f2c0962

Please sign in to comment.