Haystack with Elasticsearch refuses to create search index - django

I am using Django (master branch) and Haystack (master branch) connected to an Elasticsearch server. The Python version is 3.4.
The search index class looks like this:
class PageIndex(indexes.SearchIndex, indexes.Indexable):
text = fields.EdgeNgramField(document=True)
name = fields.EdgeNgramField(model_attr='name', boost=2)
tags = fields.EdgeNgramField(model_attr='tags', boost=1.5)
description = fields.EdgeNgramField(model_attr='description_summary', boost=0.9)
def get_model(self):
return Page
def index_queryset(self, using=None):
return self.get_model().objects.filter(created__lte=datetime.datetime.now())
When I try to create the index, I get the following error:
> python manage.py update_index Indexing 7 communities
PUT /haystack [status:400 request:0.013s]
ERROR:root:Error updating page using default
Traceback (most recent call last):
File "/env/lib/python3.4/site-packages/haystack/management/commands/update_index.py", line 221, in handle_label
self.update_backend(label, using)
File "/env/lib/python3.4/site-packages/haystack/management/commands/update_index.py", line 266, in update_backend
do_update(backend, index, qs, start, end, total, self.verbosity)
File "/env/lib/python3.4/site-packages/haystack/management/commands/update_index.py", line 89, in do_update
backend.update(index, current_qs)
File "/env/lib/python3.4/site-packages/haystack/backends/elasticsearch_backend.py", line 158, in update
prepped_data = index.full_prepare(obj)
File "/env/lib/python3.4/site-packages/haystack/indexes.py", line 204, in full_prepare
self.prepared_data = self.prepare(obj)
File "/env/lib/python3.4/site-packages/haystack/indexes.py", line 187, in prepare
ID: get_identifier(obj),
File "/env/lib/python3.4/site-packages/haystack/utils/__init__.py", line 33, in default_get_identifier
obj_or_string._meta.module_name,
AttributeError: 'Options' object has no attribute 'module_name'

You receiving this error message because in Django >= 1.6 Options.module_name changed to .model_name (this is widley abused non-public API) so you just need change in haystack code module_name

You have to check that you have an attribute named "name" in your models.
models.py
class Page(models.Model):
name = models.CharField(max_length=20)
search_index.py
class PageIndex(indexes.SearchIndex, indexes.Indexable):
name = fields.EdgeNgramField(model_attr='name', boost=2)

Related

Django Sessions, handling of datetime types

I'm using sessions in a current django project and recently got a 'Object of type 'date' is not JSON serializable' error - due to the move_in_date field below.
When saving a modelform of the below model to the session via:
if form.is_valid():
request.session.update(form.cleaned_data)
my model:
class Address(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
house_name_number = models.CharField(max_length=255, verbose_name="house name or number")
street_name = models.CharField(max_length=255)
town_city = models.CharField(max_length=255)
county = models.CharField(max_length=255)
postcode = models.CharField(max_length=8)
same_address = models.BooleanField()
move_in_date = models.DateField(null=True, blank=True)
I've tried to solve the issue by using DjangoJSONEncoder as suggested by the docs, which can handle datetimes via the settings with SESSION_SERIALIZER=DjangoJSONEncoder (should this be a serializer rather than an encoder?), but trying that or SESSION_SERIALIZER=PickleSerializer both give an Attribute error - ... has no attribute 'rsplit'
Additionally I was using django wizard before which stores intermediate data (such as the field causing the date issue above) in the session. I've now switched that part of the app to use seperate views for flexibility (as signup wasn't just a linear path), django wizard doesn't have this issue, how does it get round this?
Updated with stacktrace
Traceback (most recent call last):
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/utils/deprecation.py", line 142, in __call__
response = self.process_response(request, response)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/middleware.py", line 58, in process_response
request.session.save()
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py", line 83, in save
obj = self.create_model_instance(data)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py", line 69, in create_model_instance
session_data=self.encode(data),
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 98, in encode
serialized = self.serializer().dumps(session_dict)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/core/signing.py", line 93, in dumps
return json.dumps(obj, separators=(',', ':')).encode('latin-1')
File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'date' is not JSON serializable
Stack trace for trying DjangoJSONEncoder:
Traceback (most recent call last):
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/utils/deprecation.py", line 138, in __call__
response = self.process_request(request)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/middleware.py", line 20, in process_request
request.session = self.SessionStore(session_key)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py", line 18, in __init__
super(SessionStore, self).__init__(session_key)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 51, in __init__
self.serializer = import_string(settings.SESSION_SERIALIZER)
File "/Users/Barclay/.virtualenvs/switcher5/lib/python3.6/site-packages/django/utils/module_loading.py", line 15, in import_string
module_path, class_name = dotted_path.rsplit('.', 1)
AttributeError: type object 'DjangoJSONEncoder' has no attribute 'rsplit'
A few things of confusion are hitting you:
When setting the serializer, do not provide a class reference, but a dotted part. This is seen in the error:
module_path, class_name = dotted_path.rsplit('.', 1)
DjangoJSONEncoder isn't the right fix for a serializer. It is referenced in the documentation as a way to serialize models before putting them into the session.
If you want to make a smart serializer then you still need to create a Serializer, which should support a dumps and loads interface, that leverage a JsonEncoder and JsonDecoder respectively.
The Pickle serializer will work just fine, but as said you need to provide the dotted path.
If you want to use JSON as serializer, then this might be a good start:
from django.core.serializers.json import DjangoJSONEncoder
from django.core.signing import JSONSerializer as BaseJSONSerializer
class SmartJSONSerializer(BaseJSONSerializer):
def dumps(self, obj):
return json.dumps(obj, separators=(',', ':'), cls=DjangoJSONEncoder).encode('latin-1')

Django 1.8 - FieldError: Cannot resolve keyword into field

I recently upgraded from Django 1.6 to Django 1.8. When I did, I found that I was no longer able to to do a lookup back through a foreign key relationship as described in:
https://docs.djangoproject.com/en/1.8/topics/db/queries/#lookups-that-span-relationships.
The system is set up so that there are two projects which use the same database. (Not my idea, but not something I would like to change right now.) The project where the models were initially created and migrated works just fine after the upgrade, but the other one does not. The models file for each is identical.
Models.py:
class Site(models.Model):
name = models.CharField(max_length=255)
class Meta:
app_label = 'project1'
class Page(models.Model):
title = models.CharField(max_length=255)
site = models.ForeignKey('Site')
class Meta:
app_label = 'project1'
Error traceback from the Django Shell:
>>> x = models.Site.objects.filter(page__id=1000)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 679, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 697, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1314, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1342, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1154, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1035, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/home/user_name/project2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1401, in names_to_path
"Choices are: %s" % (name, ", ".join(available)))
FieldError: Cannot resolve keyword 'page' into field. Choices are: name, id
In the first project, the same query works as expected:
>>> x = models.Site.objects.filter(page__id=1000)
[<Site: http://stackoverflow.com>]
What if you set a related_name on the `ForeignKey ?
class Page(models.Model):
site = models.ForeignKey('Site', related_name="pages") # Note the related_name here
I tried it on another project and it work as axpected:
>>> Site.objects.filter(pages__pk=42)
[<Site: http://stackoverflow.com>]
If you don't set a related_name, I think the default is <model>_set. So it should be page_set.
I am new to Django, don't know if this helps but I had same issue. In my case, it was typing error.
I had written this earlier:
Question.objects.filter(question_text_startswith='What')
In Django documentation, I noticed there should be 2 underscores before the lookup startswith:
Question.objects.filter(question_text__startswith='What')

Django South schemamigration error AttributeError: 'Options' object has no attribute 'index_together'

I am working on a Django web app with south for db migration. I am quite new to south, and django as well. I tried using south with the official tutorials, however it failed with an exception: AttributeError: 'Options' object has no attribute 'index_together'.
I run the south command like this:
python manage.py schemamigration southtut --initial
The southtut models is this:
class Knight(models.Model):
name = models.CharField(max_length=100)
of_the_round_table = models.BooleanField()
My project models is this:
class Author(models.Model):
name = models.CharField(max_length=64)
authorId = models.CharField(max_length=32)
def __unicode__(self):
return self.name
class Meta:
db_table="Author"
class Video(models.Model):
videoId = models.CharField(max_length=32)
videoUrl = models.URLField(max_length=200)
author = models.ForeignKey(Author, null=True, related_name="videos", on_delete=models.SET_NULL)
class Meta:
db_table="Video"
class User(models.Model):
token = models.CharField(max_length=50, null=True)
favs = models.ManyToManyField(Video, related_name="fans", db_table="VideoUserR")
class Meta:
db_table = "User"
The whole error message I got is as below:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Library/Python/2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Library/Python/2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Library/Python/2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
self.execute(*args, **options.__dict__)
File "/Library/Python/2.7/site-packages/django/core/management/base.py", line 232, in execute
output = self.handle(*args, **options)
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/management/commands/schemamigration.py", line 151, in handle
for action_name, params in change_source.get_changes():
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/creator/changes.py", line 460, in get_changes
model_defs = freeze_apps([self.migrations.app_label()])
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/creator/freezer.py", line 37, in freeze_apps
model_defs[model_key(model)] = prep_for_freeze(model)
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/creator/freezer.py", line 78, in prep_for_freeze
fields['Meta'] = remove_useless_meta(modelsinspector.get_model_meta(model))
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/modelsinspector.py", line 441, in get_model_meta
meta_def[kwd] = get_value(model._meta, defn)
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/modelsinspector.py", line 258, in get_value
value = get_attribute(field, attrname)
File "/Library/Python/2.7/site-packages/South-0.7.6-py2.7.egg/south/utils/__init__.py", line 38, in get_attribute
value = getattr(value, part)
AttributeError: 'Options' object has no attribute 'index_together'
Thanks
It's bug in south 0.8. Just update to 0.8.1 or newer and all be good.
It looks like this is because you are trying to use index_together option in Meta section of your model. But this option is available only for django 1.5+ and i guess that you run it on a less recent version of django.
I updated my django to 1.5.1, and this error disappeared. I have no idea how the 'index_together' come out, but since it is available in django 1.5.1, it get what it needs.

Extending Django FlatPages to use MPTT

Preface: I was writing my own Page app that used MPTT and a custom page model. This was working for me, but FlatPages is more refined than my custom Page Model and so I'm leaning toward just extending it.
from django.db import models
from django.contrib.flatpages.models import FlatPage
from mptt.models import MPTTModel
class ExtendedFlatPage(FlatPage, MPTTModel):
parent = models.ForeignKey('ExtendedFlatPage', null=True, blank=True, default=None, related_name="children", help_text="Hierarchical parent page (if any)")
class Meta:
ordering = ['flatpages__url']
order_with_respect_to = 'parent'
verbose_name = 'page'
verbose_name_plural = 'pages'
class MPTTMeta:
left_attr = 'mptt_left'
right_attr = 'mptt_right'
level_attr = 'mptt_level'
order_insertion_by = ['title']
def __unicode__(self):
return self.url
This almost works, except throws an error when I go to run python manage.py syncdb
Error:
iMac:cms colab$ python manage.py syncdb
Creating tables ...
Creating table my_flatpages_extendedflatpage
Traceback (most recent call last):
File "manage.py", line 14, in <module>
execute_manager(settings)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/core/management/__init__.py", line 438, in execute_manager
utility.execute()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/core/management/__init__.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/core/management/base.py", line 191, in run_from_argv
self.execute(*args, **options.__dict__)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/core/management/base.py", line 220, in execute
output = self.handle(*args, **options)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/core/management/base.py", line 351, in handle
return self.handle_noargs(**options)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/core/management/commands/syncdb.py", line 101, in handle_noargs
cursor.execute(statement)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/db/backends/util.py", line 34, in execute
return self.cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.3-py2.7.egg/django/db/backends/mysql/base.py", line 86, in execute
return self.cursor.execute(query, args)
File "build/bdist.macosx-10.6-intel/egg/MySQLdb/cursors.py", line 174, in execute
File "build/bdist.macosx-10.6-intel/egg/MySQLdb/connections.py", line 36, in defaulterrorhandler
django.db.utils.DatabaseError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 2")
If anyone could point me in the right direction, I would greatly appreciate it. Thanks!
replace
class ExtendedFlatPage(FlatPage, MPTTModel):
with
class ExtendedFlatPage(MPTTModel, FlatPage):
This will allow MPTTModel class to override FlatPage attributes and methods.
#comment
It appears that something (an attribute, method) in FlatPage model overrides something in MPTTModel cousing this error.
order of classes you import from is important. here's an example:
class A:
attribute = 1
class B:
attribute = 2
class C(A,B):
pass
class C attribute value will be 1.

Error while using date between in django raw query

I am always getting this error TypeError: not all arguments converted during string formatting
Here is my query
State.objects.raw('...review_create_date between %s and %s group by error_type',[fromdate,todate])
Here fromdate=2011-05-21 and todate='2011-05-27'
The above query executes in mysql prompt but could not able to run in python shell
Please some one help me
Here is the traceback
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 1412, in __iter__
query = iter(self.query)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 73, in __iter__
self._execute_query()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 87, in _execute_query
self.cursor.execute(self.sql, self.params)
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/util.py", line 18, in execute
sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py", line 216, in last_executed_query
return smart_unicode(sql) % u_params
TypeError: not all arguments converted during string formatting
django raw sql query in view
I also faced this issue, so I changes the old formatting to new using
format. I it works for me.
models.py
class VehicleDamage(models.Model):
requestdate = models.DateTimeField("requestdate")
vendor_name = models.CharField("vendor_name", max_length=50)
class Meta:
managed=False
views.py
def location_damageReports(request):
#static date for testing
date_from = '2019-11-01'
date_to = '2019-21-01'
vehicle_damage_reports = VehicleDamage.objects.raw("SELECT * FROM VendorReport_vehicledamage WHERE requestdate BETWEEN '{0}' AND '{1}'".format(date_from, date_to))
damage_report = DashboardDamageReportSerializer(vehicle_damage_reports, many=True)
data={"data": damage_report.data}
return HttpResponse(json.dumps(data), content_type="application/json")
Try using ? instead of %s.