Using Django 1.4.2, Haystack 2.0beta, and ElasticSearch 0.19, how do I query for results which have an empty set [] for a MultiValueField?
I'd create an integer field named num_<field> and query against it.
In this example 'emails' is the MultiValueField, so we'll create 'num_emails':
class PersonIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
name = indexes.CharField(model_attr='name')
emails = indexes.MultiValueField(null=True)
num_emails = indexes.IntegerField()
def prepare_num_emails(self, object):
return len(object.emails)
Now, in your searches you can use
SearchQuerySet().filter(num_emails=0)
You can also change prepare_ method of your MultiValueField:
def prepare_emails(self, object):
emails = [e for e in object.emails]
return emails if emails else ['None']
Then you can filter:
SearchQuerySet().filter(emails=None)
Related
I'm using flask-wtf with mongoengine. Currently, when I create a form using model_form it generates 'author' as a SelectField containing all users in the db as choices! Is there an easy way to customize model_form such that ReferenceField results are filtered? For example, the SelectField only contains users from the acme group as choices?
class User(db.Document):
name = db.StringField()
group = db.StringField(choices = (acme, apple))
class Task(db.Document):
author = db.ReferenceField(User)
description = db.StringField(max_length = 300)
wtfTask = model_form(Task, wtf.Form)
Okay, here is my solution:
wtfTask = model_form(Task, wtf.Form, field_args = {'author': {'queryset': User.objects(group = 'acme').order_by('name')}})
I am using a script to populate the model database in django, but there seems to be a problem because of the foreignKey relationship.
The populating script seems to work fine but after I try to access the page it gives an error:
Exception Type: DoesNotExist
Exception Value: Week matching query does not exist.
Populating script:
def add_week(week):
w = Week.objects.get_or_create(date=week)
return w
def add_song(name, artist, position, week):
s = week.song_set.get_or_create(name=name, artist=artist, position=position)
return s
this_week = (add_week(week=soup.time.text))[0]
for position, (song_name, artist) in enumerate(chart):
print "%d. %s - %s" % (position+1, song_name, artist)
add_song(name=song_name, artist=artist, position=position+1, week=this_week)
Model:
from django.db import models
class Week(models.Model):
date = models.CharField(max_length=50)
def __unicode__(self):
return self.date
class Song(models.Model):
week = models.ForeignKey(Week, default=1)
name = models.CharField(max_length=300)
artist = models.CharField(max_length=300)
position = models.SmallIntegerField()
difference = models.SmallIntegerField(default=0)
def __unicode__(self):
return self.name
View:
from django.shortcuts import render
from charts.models import Song, Week
# Create your views here.
def chart(request):
songs = Song.objects.order_by('position')
week = Week.objects.get(pk=1) #here comes the error, even though I see two weeks in admin view
def changed_since_last_week(request):
week = Week.objects.get(pk=5)
last_week = Week.objects.get(pk=6)
songs = Song.objects.filter(week=week).order_by('position')
songs_last_week = Song.objects.filter(week=last_week)
context_dict = {'songs_last_week': songs}
for song in songs:
song_last= Song.objects.all().filter(name=song.name)
if song_last:
song.objects.difference = song_last.position - song.position
return render(request, 'charts/change.html', context_dict)
If you look at the url in your admin view, are the primary keys of the two weeks in the database really 1 (and 2)? It is possible that if you tested the generating script more than once (or maybe played with the database before) the two records just happen to have other primary keys than 1 (or 2).
Also, if you want a specific record you could query by each of the model's fields, e.g. Week.objects.get(date='my_hardcoded_date'). (by the way, I guess the value in date is something customized, so that you can't use one of Django's native DateField or DateTimeField).
I'm using Django Haystack v2.0.0 and Whoosh v2.4.0. According to Haystack's documentation search indexes can use Django's related field lookup in the model_attr parameter. However, running the following code using manage.py shell command:
from haystack.query import SearchQuerySet
for r in SearchQuerySet():
print r.recruitment_agency # Prints True for every job
print r.recruitment_agency == r.object.employer.recruitment_agency
# Prints False if r.object.employer.recruitment_agency is False
I have tried rebuilding the index several times, the index's directory is writeable, and I don't get any error messages. All other fields work as expected.
I have the following (simplified) models:
companies/models.py:
class Company(models.Model):
recruitment_agency = models.BooleanField(default=False)
jobs/models.py:
class Job(models.Model):
employer = models.ForeignKey(Company, related_name='jobs')
jobs/search_indexes.py:
class JobIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
recruitment_agency = indexes.BooleanField(model_attr='employer__recruitment_agency')
def get_model(self):
return Job
jobs/forms.py:
class JobSearchForm(SearchForm):
no_recruitment_agencies = forms.BooleanField(label="Hide recruitment agencies", required=False)
def search(self):
sqs = super(JobSearchForm, self).search()
if self.cleaned_data['no_recruitment_agencies']:
sqs = sqs.filter(recruitment_agency=False)
return sqs
Does anyone know what could be the problem?
Meanwhile I've switched over to the ElasticSearch backend, but the problem persisted, indicating that it might be a problem in haystack, and not in Whoosh.
The problem is that the python values True and False are not saved as boolean values, but as string, and they are not converted back to boolean values. To filter on boolean values, you have to check for the strings 'true' and 'false':
class JobSearchForm(SearchForm):
no_recruitment_agencies = forms.BooleanField(label="Hide recruitment agencies", required=False)
def search(self):
sqs = super(JobSearchForm, self).search()
if self.cleaned_data['no_recruitment_agencies']:
sqs = sqs.filter(recruitment_agency='false') # Change the filter here
return sqs
In the database objects are named news and news test
class ItemIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True)
name = indexes.CharField(model_attr='name')
name_alt = indexes.CharField(model_attr='name_alt')
def get_model(self):
return Serial
>>> from haystack.query import SearchQuerySet
>>> sqs = SearchQuerySet().all()
>>> sqs.count()
4
>>> SearchQuerySet().auto_query('new') # not working all query!
[]
If use haystack.backends.simple_backend.SimpleEngine its working.
Django==1.5.1
Elasticsearch==0.90
django-haystack==master (2.0)
Why????
It doesn't look like you're populating the all import document field.
Your SearchIndex class has these fields:
text = indexes.CharField(document=True)
name = indexes.CharField(model_attr='name')
name_alt = indexes.CharField(model_attr='name_alt')
You've defined the data source for name and name_alt but not for text. The output from your command line search shows that that field is empty in the search index. You have several options:
Populate that field from a model attribute
Use a prepare_FOO method to prepare the content for that field
Use a template, using the use_template argument for the text field and include any and all content in that template
Now the follow up question is why did auto_query fail but a basic curl query work? Because auto_query is searching the content - the document - and that's missing.
I'm trying to index a model in Solr with django-haystack, but it returns me the following error(when using rebuild_index or update_index) :
Indexing 2 jobposts
Failed to add documents to Solr: [Reason: None]
<response><lst name="responseHeader"><int name="status">400</int><int name="QTime">358</int></lst><lst name="error"><str name="msg">ERROR: [doc=jobpost.jobpost.1] unknown field 'django_id'</str><int name="code">400</int></lst></response>
This is search_indexes.py
from haystack import indexes
from haystack.indexes import SearchIndex
from jobpost.models import *
class JobIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
post_type = indexes.CharField(model_attr='post_type')
location = indexes.CharField(model_attr='location')
job_type = indexes.CharField(model_attr='job_type')
company_name = indexes.CharField(model_attr='company_name')
title = indexes.CharField(model_attr='title')
def get_model(self):
return jobpost
def index_queryset(self,**kwargs):
return self.get_model().objects.all()
You need to update schema.xml of your solr engine, as it written here:
"You’ll need to revise your schema. You can generate this from your application (once Haystack is installed and setup) by running ./manage.py build_solr_schema. Take the output from that command and place it in apache-solr-3.5.0/example/solr/conf/schema.xml. Then restart Solr."