I have a list of tasks related to a project in a one-to-many relationship one project have many tasks, reading the official documentation the field access should be as easy as iterating on a list and access the field by name, this is the code I have done so far:
def _roles_assigned(self):
for rec in self:
total = len(rec.task_ids)
for e in rec.tasks
logging.info(e.status) #<-- this should print status
I print the result and get 'project.task(X,)' where I guess X is the Id of the task, how can I access the task properties?
Note: the field is a selection field
try something like this:
def _roles_assigned(self):
for tasks in self.task_ids:
logging.info(tasks.status)
Since the field is a selection I had to access the dictionary
#api.multi
#api.depends('task_ids')
def _roles_assigned(self):
for rec in self:
total = len(rec.tasks)
assigned = 0
for e in rec.tasks:
selected = dict(e._fields['status'].selection).get(e.status) #<-- getting selected value from a selection field
Related
#api.depends('totalbook')
def _computebook(self):
sum_a = 0
for rec in self:
for l in rec.env['book.tickets'].search([('status', 'in', ('sold', 'rent'))]):
if l:
sum_a += 1
rec.currentbook = rec.totalbook - sum_a
I use this compute to calculate current book in library.
But when I run this code, the problem calculate of my each book base on all books.
When you are write any compute method in odoo, in self you will get all the list of browsable objects.
And then you are trying to search data from that browsable object. That's why you get a error.
You have to use self.env instead of rec.env.
Because you can't search data from browsable object you can access only data of that browsable object.
You have to add limit 1 on when you are searching a record of multiple record are than you will get another expected Singleton error.
Either you can you use another loop after searching record.
Let me know if you face any errors again.
Thanks
this error occured because
whenever you are trying to make a object of another model at that time you should have to use with self.env instead of rec.env because in your method rec is just a record-set of your instance
so please update your method as per the following snippet.
for l in self.env['book.tickets'].search([('status', 'in', ('sold','rent'))]):
Hi i am trying to delete a key value from the context for res.partner form view.
I opening the partner form view using controller function and trying to set phone number as default and its working fine. But when i try to create a new customer by clicking on the create button the phone number again auto-filled. In order to avoid this behaviour, in default_get function, i copied the context into another variable, removed the key value from the context using del context['cc_mobile']. And reassigned to self.env.context. But when i try to create a new customer, the deleted key value comes in the context again.
Controller.py
#http.route('/open_customer/<string:val>', type="http",method=['POST','GET'],website=False, auth="public")
def open_case_window(self,**kw):
mobile_no = kw.get('val')
action = request.env.ref('base.action_partner_form').sudo()
mobile_flag = 0
partner = 'res.partner'
partner_model = request.env[partner]
regex = re.match( '^(?:\01|02|03|04|06|07|09)\d*$', mobile_no)
if regex:
mobile_flag = 0
partner_id = partner_model.search([('phone', '=', mobile_no)]).id
else:
mobile_flag = 1
partner_id = partner_model.search([('mobile','=',mobile_no)]).id
if partner_id:
return werkzeug.utils.redirect('/web#id='+str(partner_id)+'&view_type=form&model='+partner)
else:
context = dict(action._context)
if mobile_flag == 0:
context.update({'cc_phone': mobile_no})
else:
context.update({'cc_mobile': mobile_no})
context.pop('lang')
url = werkzeug.utils.redirect('/web?debug=#view_type=form&model='+str(partner)+'&action=%s'%(action.id))
return url
ResPartner.py
#api.model
def default_get(self, fields):
context = self.env.context.copy()
print'default_get context',context
res = super(Partner, self).default_get(fields)
if 'cc_mobile' in context:
res.update({'mobile':context.get('cc_mobile')})
if 'cc_phone' in context:
res.update({'phone':context.get('cc_phone')})
if context.get('cc_mobile'):
del context['cc_mobile']
if context.get('cc_phone'):
del context['cc_phone']
self.env.context = context
print'self.env.context after',self.env.context
action = self.env.ref('base.action_partner_form').sudo()
action.env.context = self.env.context
return res
You cannot remove a key of action context from python side, because it's in the client side. when ever you call the server like search in many2one field, create a record in fly you will see this context comeback again every time (The way Odoo work).
What you need is something that will be used for one time, I think you need some kind of persistence for example:
dummy model that contains user_id, model_name, value, active fields so in the controller you create a record for default value for that specific user.
get that value by overriding default_get by searching with user_id and model_name field and hide that value or delete it.
this way when yo hit create button or create contact in fly when you search for the value it will be gone so it will not be used a second time.
This a simple Idea and easy to implement, you need to handle some cases to prevent user from saving two default value if some interruption happens should not be hard.
Edit
After second thought to prevent any error when you create a record just pass it's ID in the context with a special key, then use That Id to retrieve it, use it then delete it. easier, safer and no need for search.
I have this many2one field that I want to get the ID of the selected value
service = fields.Many2one('mainservices.mtvehlog', string='Select Service(s)')
so onchange i want to know the id and do something after knowing (I want to make other fields invisible)
What if the many2one is multi selection? How do you get the ID's that have been selected?
#api.depends('service')
def _compute_hide(self):
source_obj=self.pool.get('mainservices.mtvehlog').browse(self.service)
if source_obj == '1':
self.services_selected = source_obj
self.hide = True
else:
self.services_selected = source_obj
self.hide = False
kindly help
In compute methods using depends decorator always loop throuth self first.
for rec in self:
# and this is how you get the id value
#you don't have to browse you have direct acces to properties of the selected value
if rec.service.id == somthing :
# and you will not get except singlton error
you question is not clear what you want to do with the id value exactly.
I have created an one2many to customer form. So, when I am validating (button validate) an invoice I am trying to pass some values in that one2many. I have tried many ways and followed odoo forums, but I am having trouble to do that. Using following code:
My one2many field is 'customer_status' in 'res.partner' :
#api.multi
#api.model
def invoice_validate(self):
customer_obj=self.env['res.partner']
customer_id=customer_obj.search([('id','=',self.partner_id.id)])
customer_line=customer_obj.browse(customer_id)
dd = {'policy_number': self.policy_no,}
customer_stat_add = customer_obj.write([customer_line.id],{
'customer_status': [(0, 0, dd)]
})
state_change = self.write({'state': 'open'})
return state_change, customer_stat_add
It gives me this error:
ValueError: "invoice_validate() takes exactly 2 arguments (1 given)" while evaluating
u'invoice_validate()'
Thanks.
buttons w/ new api need #api.multi and if you want to work on a single object you can use self.ensure_one();
#api.multi
def foo(self):
self.ensure_one()
print self.my_field
Also, you don't need to browse object as you already get browse objects w/ new api.
Bear in mind that if that feature is an odoo base feature you must call super().method_name to not break anything ;)
In a lot of situations I add a custom queryset to a selectfield in django form.
form.fields[fieldname] = model.objects.all()
Now I have a selectfield where I need to assign as choices the result of a RawQueryset.
I tried this (queryset is simplified):
sql = "SELECT * FROM table WHERE value = %s"
param.append (1234)
qs = model.objects.raw (sql, param)
form.fields[fieldname] = qs
The page is correctly displayed and the select field contains the data from the queryset.
When I try to save the form, form validation (form.is_valid()) throws the error:
*** Attribut error: 'RawQuerySet' object has no attribut 'get'
How can I fix this?
Thanks
You cannot assign a queryset to a form field, like this:
# this is wrong
form.fields[fieldname] = qs
you need to define the field using one of the fields django has, like:
form.fields[fieldname] = forms.ModelChoiceField(queryset=qs)
django doc.