I'm making my blog on Django and I want to add site search based on django-haystack. I made a basic configuration of haystack, using official manuals, but when I want to test my search, I'm getting an error: 'Options' object has no attribute '_fields'
Here are some of my configs:
search_indexes.py
class PostIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title')
pub_date = indexes.DateTimeField(model_attr='date')
def get_model(self):
return Post
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.all()
settings.py
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
},
}
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
So this is my problem. Does anyone worked with smth similar? Thanks in advance!
You are hitting a bug in the simple backend which is fixed in git. There doesn't seem to be a release which contains this fix, though, so you can either upgrade to the development version:
pip install -e git+https://github.com/toastdriven/django-haystack.git#master#egg=django-haystack
Or use a different backend (elasticsearch, solr, ...)
Related
I have a project based on
Django==1.9.2
django-haystack==2.4.1
elasticsearch==2.2.0
A very simple search view:
def search_view(request):
query = request.GET.get('q', '')
sqs = SearchQuerySet().filter(content=query)
params = {
'results': sqs,
'query': query,
}
return render_to_response('results.html', params,
context_instance=RequestContext(request))
My search index is as simple as:
class CategoryIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
name = indexes.CharField(model_attr='name')
def get_model(self):
return Category
def index_queryset(self, using=None):
return self.get_model().objects.filter(published=True)
The category_text.txt file is just:
{{ object.name }}
In my database I have a few items:
Acqua
Acquario
Aceto
Accento
When I search with my view, I have strange behaviours.
Searching with query "ac" I receive no results! I was expecting to have all my items. I have tryed to change the query using .filter(content__contains=query) (I know it is the default!) but nothing changed.
Searching with query "acqua" I receive 1 result (correct) with the result object, but when I try to print it, the result.object field is None (the other fields contain the correct information).
What am I doing wrong?
Thank you.
UPDATE
I have found a solution to my problem number 2. Latest Haystack version from PyPi is not Django 1.9.x compatible.
I have just added -e git+https://github.com/django-haystack/django-haystack.git#egg=django-haystack to my requirements.txt file and the issue is fixed. More info about that on GitHub: https://github.com/django-haystack/django-haystack/issues/1291
The other issues is still opened and I cannot find any solution to it.
It sounds like you may be running into a minimum number of characters issue for #1. Take a look at the Haystack documents for autocomplete which shows an approach using EdgeNgramField instead of the typical CharField.
I have default django user model which i want to index using elasticsearch
I'm using django-haystack.
in settings.py
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 12
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://127.0.0.1:9200/',
'INDEX_NAME': 'haystack',
},
}
in search_indexes.py
import datetime
from haystack import indexes
from django.contrib.auth.models import User
class UserIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True)
first_name = indexes.CharField(model_attr='first_name', null=True)
last_name = indexes.CharField(model_attr='last_name', null=True)
def get_model(self):
return User
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.all()
and build the index using python manage.py rebuild_index
now in shell
from haystack.query import SearchQuerySet
SearchQuerySet().all()
it returns all the indexed objects (I can confirm the count is same as number of entries in db)
when I do
SearchQuerySet().filter(first_name='Wendy') It returns two results object which is again as expected.
but when I try SearchQuerySet().filter(content='Wendy') it returns None.
basically I want to create an API, in which we can pass a query param and return all the user objects that contains this query string in any field.
http://localhost/search/?q=Wendy
This is my first time I'm using Elasticsearch or (anysearch engine with haystack) so I'm not able to understand what is going on.
After little bit search I found few threads on stack overflow which suggests to use Ngram or EdgeNgram but again those also couldn't work.(I rebuilded the whole index). I even tried content_auto in filter but no success.
Any help or lead will be appreciated.
I was following this official docs.
http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#quick-start
PS: I wrote here only two fields (firstname, lastname) but there are couple more fields in my actual code. its just to write here.
PPS: I'm using Django 1.9. could that be an issue?
This is how my view looks like
def search_api(request):
query = request.GET.get('q')
sqs = SearchQuerySet().filter(content=query)
data = map(lambda x: x.get_stored_fields(), sqs)
return HttpResponse(json.dumps(data))
I have two problems setting up haystack/django/elasticsearch
I never get results from index fields, e.g. indexes.CharField(model_attr='title') doesn't get me results. Only if I put {{ object.title }} in my txt template I get results for matching titles
If my title is 'foo' I never get results for 'fo', while I do have the INCLUDE_SPELLING setting set to True in my backend setting.
The documentation doesn't state anything special about these cases, my setup is per the haystack documentation, what am I missing?
My index:
class FooIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title') # never gets me results unless I add it to the template
def get_model(self):
return Foo
My settings:
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://127.0.0.1:9200/',
'INDEX_NAME': 'haystack',
'INCLUDE_SPELLING': True,
},
}
1) If you have use_template=True only index what you put in the template file so put all the fields you want indexed in there.
2) Did you refresh the index after adding INCLUDE_SPELLING ?
Make sure you enabled spellcheck component.
The first thing to do is create a special field on your SearchIndex class that mirrors the text field, but uses FacetCharField. This disables the post-processing that Solr does, which can mess up your suggestions. Something like the following is suggested:
class MySearchIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
# ... normal fields then...
suggestions = indexes.FacetCharField()
def prepare(self, obj):
prepared_data = super(MySearchIndex, self).prepare(obj)
prepared_data['suggestions'] = prepared_data['text']
return prepared_data
Once this is done, spelling_suggestions method should return the appropriate values.
I am using the 2.2 django-cms on django 1.3, as well as the 2.3 django-cms git repo on django 1.4, and I notice that if I include a PlaceholderField in my model such as this:
##books/models.py
class Book(models.Model):
...
description = cmsmodels.PlaceholderField('book_description', null=True, blank=True)
class BookCMSPluginModelItem(models.Model):
t_book = models.ForeignKey(Book)
...
class BookCMSPluginModel(CMSPlugin):
featured_books = models.ManyToManyField(BookCMSPluginModelItem)
template = models.CharField(max_length=256, choices= settings.BOOKS_TEMPLATES, default=settings.BOOKS_TEMPLATES[0]);
and make my CMS Plugin like so:
##books/cms_plugins.py
class BookCMSPlugin(CMSPluginBase):
model = BookCMSPluginModel
name = _("Books Plugin")
def render(self, context, instance, placeholder):
self.render_template = instance.template;
context['instance'] = instance;
return context
Then in my template at some point I discover I can do the following:
{% for mitem in instance.featured_books.all %}
<!-- ...... -->
<div>{% render_placeholder mitem.t_book.description %}</div>
{% endfor %}
BUT, in the front end editor, I add my new plugin, and the description field does show up as a placeholder, however when I hover over it, the outer placeholder I placed the plugin into is active, and I cannot select directly the inner placeholder. It works quite well in the admin site, as I can add content using SemanticEditor and whatever else I wish to use. In the front-end, however, there's a frustrating issue with the javascript that seems to prevent the user from adding or editing the inner placeholder.
I should note that I followed the wonderful django-cms documentation here: http://docs.django-cms.org/en/latest/extending_cms/placeholders.html, but that site only addresses the issue in the context of displaying a model in a specifically designed page, unfortunately not using a template for a custom django-cms plugin.
In this thread on GitHub one of the django-cms developers says that there is no plugin-in-plugin architecture in Django CMS 2.2.
I've tried it with the latest development branch and it is working now.
Same issue with
Django==3.1.6
django-cms==3.8.0
python_version = 3.6.9
One unrecommended workaround is to change cms source code at 1 place
Go to virtualenvs/your-project-vitualenv/lib/python3.6/site-packages/cms/models
then edit the file placeholdermodel
got to line #123 Placeholder.has_change_permission and comment the first if-return.
=> Comment line #132 if not attached_models:
=> and line #136 return user.is_superuser
Save it and restart your server.
def has_change_permission(self, user):
"""
Returns True if user has permission
to change all models attached to this placeholder.
"""
from cms.utils.permissions import get_model_permission_codename
attached_models = self._get_attached_models()
# Comment this part!
# if not attached_models:
# # technically if placeholder is not attached to anything,
# # user should not be able to change it but if is superuser
# # then we "should" allow it.
# return user.is_superuser
attached_objects = self._get_attached_objects()
for obj in attached_objects:
try:
perm = obj.has_placeholder_change_permission(user)
except AttributeError:
model = type(obj)
change_perm = get_model_permission_codename(model, 'change')
perm = user.has_perm(change_perm)
if not perm:
return False
return True
I have been trying to get xapian working django haystack for a project im working on that requires some search functionality but have run into a bit of a wall!! Basically i got everything installed per the instructions, so:
ran make install for xapian-core and the xapian bindings
ran pip install haystack and pip install xapian-haystack and everything installed correctly
As im using the django cms app i simply copied thier example over to give the search functionality a test and ran into this error
InvalidIndexError at /search/
Unable to open index at /home/mike/sites/xapian_search
I have tried several different paths for the HAYSTACK_XAPIAN_PATH setting and have also encountered another error
OSError at /
(13, 'Permission denied')
the folder xapain_search has been given full perms (chmod 777) and theres an xapian_index.php file with full perms too. Im not sure what im missing here but im desperate to try and get this working!!
my haystack settings look like
HAYSTACK_SITECONF = 'lactoseintolerant.lactose_search'
HAYSTACK_SEARCH_ENGINE = 'xapian'
HAYSTACK_XAPIAN_PATH = '/home/mike/sites/xapian_search'
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 50
Any advice would be greatly appreciated!!
edit
Hey again
i think this error is relating to the fact that there are no indexes(is that right?) i have run the commands update_index rebuild_index clear_index all of which dont seem to do anything, there are no errors outputted but still the indexs never seem to be built when the commands are run
i have an app called lactose_search which my HAYSTACK_SITECONF points to like so projectname.lactose_search in this app folder i have a file called search_indexs.py. For now i have simply c+p the example from the django cms site as it is the cms_app content i want to search
this file looks like
from django.conf import settings
from django.utils.translation import string_concat, ugettext_lazy
from haystack import indexes, site
from cms.models.managers import PageManager
from cms.models.pagemodel import Page
def page_index_factory(lang, lang_name):
if isinstance(lang_name, basestring):
lang_name = ugettext_lazy(lang_name)
def get_absolute_url(self):
return '/%s%s' % (lang, Page.get_absolute_url(self))
class Meta:
proxy = True
app_label = 'cms'
verbose_name = string_concat(Page._meta.verbose_name, ' (', lang_name, ')')
verbose_name_plural = string_concat(Page._meta.verbose_name_plural, ' (', lang_name, ')')
attrs = {'__module__': Page.__module__,
'Meta': Meta,
'objects': PageManager(),
'get_absolute_url': get_absolute_url}
_PageProxy = type("Page%s" % lang.title() , (Page,), attrs)
_PageProxy._meta.parent_attr = 'parent'
_PageProxy._meta.left_attr = 'lft'
_PageProxy._meta.right_attr = 'rght'
_PageProxy._meta.tree_id_attr = 'tree_id'
class _PageIndex(indexes.SearchIndex):
language = lang
text = indexes.CharField(document=True, use_template=False)
pub_date = indexes.DateTimeField(model_attr='publication_date')
login_required = indexes.BooleanField(model_attr='login_required')
url = indexes.CharField(stored=True, indexed=False, model_attr='get_absolute_url')
title = indexes.CharField(stored=True, indexed=False, model_attr='get_title')
def prepare(self, obj):
self.prepared_data = super(_PageIndex, self).prepare(obj)
plugins = obj.cmsplugin_set.filter(language=lang)
text = ''
for plugin in plugins:
instance, _ = plugin.get_plugin_instance()
if hasattr(instance, 'search_fields'):
text += ''.join(getattr(instance, field) for field in instance.search_fields)
self.prepared_data['text'] = text
return self.prepared_data
def get_queryset(self):
return _PageProxy.objects.published().filter(title_set__language=lang, publisher_is_draft=False).distinct()
return _PageProxy, _PageIndex
for lang_tuple in settings.LANGUAGES:
lang, lang_name = lang_tuple
site.register(*page_index_factory(lang, lang_name))
and can be found here http://docs.django-cms.org/en/2.1.3/extending_cms/searchdocs.html
Hope this extra info may make answering this question abit easier!
it's more likely that you have not built the index using following command
python manage.py update_index
same thing happens to me, just needed to run above command.
This is a rather strange issue that I haven't yet encountered (and no one has yet reported here: https://github.com/notanumber/xapian-haystack/issues)
Older versions of the Xapian-Haystack required write permission (to be able create indexes) and had a check at startup that verified this was the case, but this was removed.
As long as the process can read the HAYSTACK_XAPIAN_PATH folder you shouldn't be receiving any Permission Denied errors.
Can you confirm what version of the backend you are using? If possible, I'd also suggest trying to swap out the backend with Whoosh just as a sanity check that there's not something hokey going on.
I figured out what my issue was here, when i installed the packages to my env i ran sudo pip install instead of simply using pip. I cant explain why this affected the haystack install but once i removed all the packages and re-installed them i managed to get haystack running