haystack SearchQueryResult object returns multiple objects - django-haystack

I don't get why get() with pk=1 would result in multiple objects returned below..
sqs = SearchQuerySet().more_like_this(self)
for obj in sqs:
do something with obj.object # obj.object results in error
get() returned more than one MyModel -- it returned 4! Lookup parameters were {'pk': u'1'}

I don't know why but I was having the same problem, the following gave me MultipleObjectReturned error:
context['object_list'] = [result.object for result in results]
lib/python2.7/site-packages/haystack/models.py", line 80, in _get_object
self._object = self.searchindex.read_queryset().get(pk=self.pk)
instead of referencing the obj.object directly, I worked around with using pk
context['object_list'] = Entry.objects.filter(pk__in=[result.pk for result in results])

Related

Under which circumstances filter can refuse to work in Python?

I get the following line
db_dir_content = os.listdir(db_path)
db_states = filter(is_state, db_dir_content)
returning empty iterator, while the following
db_dir_content = os.listdir(db_path)
db_states = [state for state in db_dir_content if is_state(state)]
returning non empty an correct list.
is_state is following
def is_state(name):
return _STATE_NAME_PATTERN.match(name) is not None
How can it be and how to fix?

how to pass complex string to pymongo for query by python?

I need to filter the webserver requests and setting a query for pymongo, its not so simple as I need to have "and", or "or" functionality for multiple fields.
I have filtered the get request, got the parameters, built the string to be passed to db..find. But it throws error. I have identified the error as because I am forming a string like this to passed to the function, now as its a string and not actually a dict, its throwing an error. What is the right way of doing it?
Actually, I have to get something like: {$and:[{Title:{"$regex":"Hong Kong"}},{Url:{"$regex":"hong"}}]}{'_id':0, 'Body':0}
The get request I am sending is: http://127.0.0.1:5000/getRequest?Title="Hong Kong protest"&Url="hong" Now the below thing gives the exact required string, but it throws an error as its not supposed to be string. Please help.
#app.route('/getRequest', methods=['GET'])
def request():
global connection
args = request.args
if len(args) > 1:
search_str = ""
for key, val in args.items():
search_str += '{'+key+':{"$regex":'+str(val)+'}},'
search_str = search_str[:-1]
display_dict={'id':0, 'Body':0}
final_search_str = "{$and:["+search_str+"]},{'_id':0, 'Body':0}"
#return(final_search_str)
# query_str = request.args.get('query_string')
db = connection['test']
collection = db['collect1']
output = []
for s in collection.find(final_search_str):
output.append({'Title' : s['Title'], 'Url' : s['Url']})
It should be dict which should be passed to the function. Any better way to do this complex query via pymongo?
You can do this using re and bson.regex.Regex module.
http://api.mongodb.com/python/current/api/bson/regex.html
import re
from bson.regex import Regex
query = {}
for key, val in args.items():
pattern = re.compile(val)
regex = Regex.from_native(regex)
query[key] = regex
for s in collection.find(query):
output.append({'Title' : s['Title'], 'Url' : s['Url']})

calling a class without () is working fine but not giving desired output

I am new to python, can anyone please explain to me why this is happening??
What is the meaning of "()"
class ganga:
a ="subhanshu"
def course(self,name):
self.ab = name
obj1=ganga() #it works fine
obj = ganga #works fine
obj1.course("apple") #it works fine
onj.course("apple") #gives me error
error is:
TypeError: course() missing 1 required positional argument: 'name'
Function course has two arguments: self and name. The self argument refers to the object on which to perform the function's operation.
Case #1
obj1 = ganga()
You created an object of the class ganga. When you called the function via the object obj1.course("apple"), the self argument was automatically filled in as obj1.
Case #2
obj = ganga
Here you made a copy of the class ganga and assigned it to the variable. Therfore, when you called the function, it expects you to specify both the arguments. Try the following -
obj1 = ganga()
obj.course(obj1, "apple")
This perform the course operation on obj1.

Python calling mock with "=" not called result

I am trying to mock the following call:
df_x = method() # returns a pandas dataframe
df_x.loc[df_x['atr'] < 0, 'atr'] = 0
I have mocked the method so it returns a MagicMock and set a default value to the __ getitem__ attribute of the MagicMock as like this:
mock_df_x = mock_method.return_value
mock_df_x.__getitem__.return_value = 0
The problem is when I try asserting the call:
mock_df_x.loc.__getitem__.assert_called_with(False, 'atr')
I get a function not called error. If I call the function like this without the "= 0" part the assertion works.
df_x.loc[df_x['atr'] < 0, 'atr']
The reason you are seeing this different behavior depending on whether on you have = 0 at the end of the call you are testing is that in Python's data model, those correspond to two different magic methods: __getitem__ and __setitem__.
This makes sense, because for example doing some_dictionary['nonexistent_key]' raises KeyError, whereas some_dictionary['nonexistent_key]' = 1 doesn't, and sets the value as expected.
Now, in order to fix your test, you only need to change your assertion from:
mock_df_x.loc.__getitem__.assert_called_with((False, 'atr'))
which only works if you are accessing the key, to:
mock_df_x.loc.__setitem__.assert_called_with((False, 'atr'), 0)
which works if you are trying to assign a value to that key.
Notice the extra parameter, too, corresponding to the value you are actually trying to assign.

How to get Id from Object in Odoo 10?

This is my structure:
class Imprint_Location(models.Model):
_name = 'imprint.location'
name = fields.Char()
product_id = fields.Many2one('product.template')
class Imprint_Charges(models.Model):
_name = 'imprint.charge'
_rec_name = 'location_id'
product_id_c = fields.Many2one('product.template', required=True)
location_id = fields.Many2one('imprint.location', required=True)
#api.multi
#api.onchange('product_id_c', 'location_id')
def product_filter(self):
res = {}
print '\n\n-------\n\n', self, self.product_id_c, '\n\n-------\n\n'
if self.product_id_c:
res['domain'] = {'location_id': [('product_id', '=', self.product_id_c.id)]}
print res
return res
class Product_Template(models.Model):
_inherit = 'product.template'
imprint_location_ids = fields.One2many('imprint.location', 'product_id')
sale_imprint_charge_ids = fields.One2many('imprint.charge', 'product_id_c')
Now i have defined a page in product.template and inside the page is sale_imprint_charge_ids which is in <tree editable="bottom"> and i am not selecting the product_id_c field[also this field doesn't show up in the tree defined].
Now my problem here is that when i select this from the form view which i defined for imprint.charge the method product_filter works fine, but when i enter from the product.template then i get a error saying
TypeError: <odoo.models.NewId object at 0x7fbb8bc21b90> is not JSON serializable
Because from product.template if passes the object <odoo.models.NewId object at 0x7fbb8bc21b90> , so if print self.product_id_c then it prints product.template(<odoo.models.NewId object at 0x7fbb8bc21b90>) so this is not serializable. i have tried doing self.product_id_c.ids which give output empty list [].
So how do get the product.template id from the object or pass the id itself overriding some method.
You should improve couple of following points.
res['domain'] = {'location_id': [('product_id', '=', self.product_id_c.id)]}
return res
study some search() method of ORM
Try with following code:
#api.multi
#api.onchange('product_id_c', 'location_id')
def product_filter(self):
res = {}
if self.product_id_c:
self.location_id = False
#search product_template in imprint.locationwith table and limit we will get only record if related record found
location_id = self.env['imprint.location'].search([('product_id', '=', self.product_id_c.id)], limit=1)
if location_id:
#location_id.ids will give you something like [2] so we need to set value as 2
self.location_id = location_id.ids[0]
EDIT:
As per your first comment, you need a list of related location then we should following trick.
Remove product_filter() method
Add domain in imprint.charge object view file
For example:
<field name="location_id" domain="[('product_id', '=', product_id_c)]"/>
Afterwards, Restart Odoo server and upgrade your custom module.
When creating a brand new record Odoo creates that wierd <odoo.models.NewId object at 0x7fbb8bc21b90> object. After you have written the record this id gets turned into the normal ids that you are used to (an integer). In this situation you have a function which (not unreasonably) expects a real id value at a point when no such value really exists. You need to provide a fallback, such as evaluating if the id is an integer and providing an alternate value in that circumstance. Although your function seems to return an object which I dont quite know what you are expecting to happen. If you wish to modify the value of one of your fields I would modify the values of the self object rather that returning an object.

Resources