Many to one relation not working in fields.selection() in openerp - python-2.7

I need to create a selection field in openerp , it's values should load from a function and also this field needs many2one relation with another table.I have created the selection field and values are loaded from the function but many2one relation not working in it.below given is my code.
def _sel_proj(self, cr, uid, context=None):
cr.execute("""SELECT project.id,account.name FROM project_project project
LEFT JOIN account_analytic_account account ON
account.id = project.analytic_account_id
LEFT JOIN project_user_rel rel ON rel.project_id = project.id
WHERE (account.user_id = %s or rel.uid = %s)
GROUP BY project.id,account.name"""%(uid, uid))
return [(r[0],r[1]) for r in cr.fetchall()]
_name = 'mat.mgmt'
_columns = {'project_id':fields.selection(_sel_proj,string='Project',type="many2one",relation="project.project",select="true",required="true"),}

change the field project_id to many2one and in the view for the field add widget='selection'.
in python:
_columns = {'project_id':fields.many2one('project.project','Project',select="true",required="true"),}
in xml:
<field name="project_id" widget="selection"/>
then override the fields_view_get function and add the filter condition for project_id. For example
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
if context is None:context = {}
res = super(<your_class_name>,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
for field in res['fields']:
if field == 'project_id':
cr.execute("""SELECT project.id,account.name FROM project_project project
LEFT JOIN account_analytic_account account ON
account.id = project.analytic_account_id
LEFT JOIN project_user_rel rel ON rel.project_id = project.id
WHERE (account.user_id = %s or rel.uid = %s)
GROUP BY project.id,account.name"""%(uid, uid))
project_select = [(r[0],r[1]) for r in cr.fetchall()]
res['fields'][field]['selection'] = project_select
return res

Related

Is there any way to get primary key using record when creating tables in django_tables2

I'm trying to get the primary key of my table in tables.py using django-tables2 by using the variables record.pk. I supposed that record.pk exist originally but somehow it's not.
class TableServeur(tables.Table):
type_server = tables.Column()
memory = tables.Column(attrs={"td": {"class": "memory"}}, verbose_name="% Mem")
cpu = tables.Column(attrs={"td": {"class": "cpu"}}, verbose_name="% Cpu")
port = tables.Column()
etat = tables.Column()
# here is the problem
T1 = '<a class="btn" href="/update/{{record.pk}}" >Icon</a>'
action = CustomTemplateColumn(T1)
class Meta:
fields = ["type_server", "cpu", "memory", "port", "etat", "action"]
template_name = "django_tables2/bootstrap4.html"
views.py
def cpu_view(request,nom_client):
output = []
liste = get_proc_output()
listServers = Serveurs.objects.all() # port, tp_serveur
listNetstat = get_netstat_output() # port,pid,etat
list_pcpu = get_proc_stat(liste) # pid,cpu,mem
# we add percentage of cpu of each item
for i in range(len(liste)):
liste[i]['cpu'] = list_pcpu[i]
# we mix and reorganise the list by their pid
for x in liste:
pid = x.get('pid')
for y in listNetstat:
if pid in y.values():
output.append({**x,**y})
# we add the type of server by their port
for i in listServers:
for j in output:
if i.port in j.values():
j['type_server'] = i.type_du_serveur
# if we have switched off server, print it with different way
temp_list_1 = [i.type_du_serveur for i in listServers]
temp_list_2 = [x['type_server'] for x in output]
serveurs_eteint = list(set(temp_list_1) - set(temp_list_2))
#
for j in serveurs_eteint:
if j == k['type_server']:
output.append({'type_server':j,'memory':'--','etat':'CLOSED'})
for k in output:
k['nom_client'] = nom_client
# here we construct the table
table = TableServeur(output)
RequestConfig(request).configure(table)
return render(request, 'server/table.html', {'table': table, 'nom': nom_client, 'output': output})
So is there any way I can get the primary key directly when creating a table using django-tbales2?

Foreign key value is returning as an object instead of id in datatables in django

When i try to get the data from the database I'm getting foreign key value as object instead of value.
in Models.py
class UP_ROLE_MENU_MAP(models.Model):
iRMID = models.AutoField(primary_key=True)
iRoleID = models.ForeignKey(UP_ROLE_MASTER,on_delete=models.CASCADE,default='',db_column='iRoleID')
iMenuID = models.ForeignKey(up_menus,on_delete=models.CASCADE,default='',db_column='iMenuID')
iStatus = models.PositiveSmallIntegerField(default=1, blank=True,null=True)
In Views for DataTables
class OrderListJson(BaseDatatableView):
model = UP_ROLE_MENU_MAP
columns = ['iMenuID', 'iDeleteAccess','iAddAccess','iViewAccess']
order_columns = ['iMenuID', 'iDeleteAccess','iAddAccess','iViewAccess']
max_display_length = 10
def render_column(self, row, column):
if column == 'iViewAccess':
return ...
else:
return super(OrderListJson, self).render_column(row, column)
output: ["up_menus object (3)", "0", "1", "link"]
How can i get the value instead of object.
to get the id instead of the object just change your columns from
columns = ['iMenuID', 'iDeleteAccess','iAddAccess','iViewAccess']
to
columns = ['iMenuID_id', 'iDeleteAccess','iAddAccess','iViewAccess']

Odoo on write() method check many2many relation

I have 2 classes:
class my_request(models.Model):
_name = 'my.request'
_inherit = ['mail.thread', 'ir.needaction_mixin']
supply_ids = fields.Many2many(comodel_name='supply.conditions',
relation='purchase_supply_rel',
column1='purchase_requests_id', column2='supply_conditions_id',
string='Supply Conditions')
and
class SupplyConditions(models.Model):
_name = 'supply.conditions'
vendor = fields.Char(string='Vendor', required=True)
quantity = fields.Char(string='Quantity', required=True)
request_id = fields.Many2one('my.request', 'My request')
name = fields.Many2one('my.request.line', string='Product', required=True)
currency_id = fields.Many2one('res.currency', string='Currency', default=_get_default_currency)
supply_rel_id = fields.Boolean(string='Relation field', default=False)
my.request class part of form view xml:
<page string="Order">
<field name="supply_ids" domain="[('purchase_id', '=', id)]"/>
</page>
When I select values from my.request form view and click on Save button I call write() method and at that time insert m2m values (if there is selected values) into relational table (purchase_supply_rel).
I want to add check if purchase.request id is in purchase_supply_rel table in purchase_requests_id field when I click on Save button. My function. Changes after # my new code coment:
#api.multi
def write(self, vals):
res = super(PurchaseRequest, self).write(vals)
for request in self:
if request.state != 'draft':
if vals.get('assigned_to'):
self.message_subscribe_users(user_ids=[request.assigned_to.id])
# my new code
test = self.env['purchase.request'].search([(self.id,'in','supply_ids')])
_logger.warning("test " + str(test));
return res
But I got an error:
File "/opt/odoo/openerp/osv/expression.py", line 586, in check_leaf
raise ValueError("Invalid leaf %s" % str(self.leaf))
ValueError: Invalid leaf (348, 'in', 'supply_ids')
How else I can check this? And what I am doing wrong?
UPDATE:
I need to get test value smth like this: purchase_request(245,352)
245,352 - ids of purchase.request class
You can not add dynamic value in domain in place of field name.
Domain is a list of tuples. Domain contains three portions in tuple.
Domain:
[('field_name','operator','values')]
So dynamic value is not allowed in field name in domain.
#api.multi
def write(self, vals):
res = super(PurchaseRequest, self).write(vals)
for request in self:
if request.state != 'draft':
if vals.get('assigned_to'):
self.message_subscribe_users(user_ids=[request.assigned_to.id])
# my new code
test = self.env['purchase.request'].search([('supply_ids','in',self.ids)])
_logger.warning("test " + str(test));
return res

django - compare two objects [using fields dynamically]

I need compare two objects, to determine if a field has changed or not
class Country(models.Model): # country code 'MX' -> Mexico
code = models.CharField(max_length=2)
name = models.CharField(max_length=15)
class Client(models.Model): # id=1, name=pedro, country.code=MX, rfc=12345
name = models.CharField(max_length=100)
country = models.ForeignKey(Country)
rfc = models.CharField(max_length=13)
> obj_db = Client.object.get(id=1)
> country = Country.objects.get(code='MX')
obj_no_db = Client(**{'id':1, 'name':'pedro', 'country': country, 'rfc':12345})
> obj_db == obj_no_db # True
> obj_no_db = Client(**{'id':1, 'name':'pedro', 'country': country, 'rfc':1})
> obj_db == obj_no_db # True # but isn't True because the rfc has change, how can compare field by field
> obj_db.rfc == obj_no_db.rfc # False I expected this result
I need to build a function to do it generic, the problem i don't found information about it, i think i can use the ._meta options, but i'm not sure.
I developed this function but i can't discover the way to compare field by field.
def get_insert_update(obj, key, obj_list, fields=None, exclude_fields=None):
"""
:param obj: The object for compare
:param key: a the key for compare to determine if we need to update or insert
:param obj_list: list objects to compare
:return: to_insert, _update
"""
db = {}
to_insert = []
to_update = []
if key == 'pk': # the field pk doesn't exists so we change to id, because its the same
key = 'id'
exclude_fields = exclude_fields or []
fields = fields or []
if 'pk' in fields:
fields[fields.index('pk')] = 'id' # we change the field pk, because it doesn't exists
if 'pk' in exclude_fields:
exclude_fields[exclude_fields.index('pk')] = 'id' # we change the field pk, because it doesn't exists
meta = obj._meta # we define meta object
if fields is None:
fields = meta.get_all_field_names()
fields = [f for f in meta.fields if f.attname in fields]
# dumping db into memory
for _obj in obj.objects.all():
if isinstance(key, list): # first check if is a list to create a custom key
_key = _get_key(_obj, key)
else:
_key = _obj.__dict__[key]
# if exclude fields exists
if exclude_fields:
d = {f.attname: _obj.__dict__[f.attname] for f in fields if f.attname not in exclude_fields}
db[_key] = obj(**d)
else: # we save the full object
db[_key] = _obj
# read local objects to determine if the record will be insert or update
for _obj in obj_list:
if isinstance(key, list): # first check if is a list to create a custom key
_key = _get_key(_obj, key)
else:
_key = _obj.__dict__[key]
if _key in db: # if the key is in db so we check if it equal
# if _obj.pk == 6: # debug
# print(_obj.__dict__, db[_key].__dict__, _obj.__dict__ == db[_key].__dict__)
if _obj != db[_key]: # HERE i need the determine if the fields are equal or not.
to_update.append(_obj) # if the object has changed, we update it
else:
pass # if the object is equal, we didn't do it anything
else:
to_insert.append(_obj) # because we didn't found into the database, we create it
return to_insert, to_update
def _get_key(obj, lst):
"""
create a string key using multiples keys
Example: obj.id -> 1, obj.name -> 'foo'
lst['id', 'name']
:param lst: list of keys
:return: 1_foo
"""
k = []
for t in lst:
k.append(str(obj.__dict__[t]))
return "_".split(k)
Django's Model class defines the __eq__ method to compare based on the value of the pk attribute, which is why your models compare equal.
One simple way to do this would be to override that method on your own model to compare the value of the __dict__, which contains all the instance's values.
There's a slight gotcha with this, in that __dict__ also contains a hidden _state object that will be compared by ID, so you'd need to filter that out of the comparison.
def __eq__(self, other):
values = [(k,v) for k,v in self.__dict__.items() if k != '_state']
other_values = [(k,v) for k,v in other.__dict__.items() if k != '_state']
return values == other_values

insert a data into mysql database if the field valus is change

I have developed a code for update a database,but right now I want to code if the value is change the database insert the data not update the database.Here is my code:-
def update_Sprint(self, ps):
id = ps.projectid
data=requests.get('https://example.com/api/v1/xyz/'+str(ps.projectid)+'/Iterations?include=[Id,Name,StartDate,EndDate,UserStories-Effort-Sum,UserStories-EffortCompleted-Sum]&token='+settings.AUTH_TOKEN+'&format=json')
data=json.loads(data.text)
data=data['Items']
if len(data)>0:
for data_ in data:
sprint_id=str(data_['Id']
sps = Day.objects.filter(sprintid=sprint_id, project__projectid=ps.projectid)
print ' creating new sprint '+str(sprint_id)
sp = Day(sprintid=sprint_id, project=ps)
sp = update_model(sp, sprint_name = Name,sprint_end_date = EndDate, sprint_start_date = StartDate, usesteff_sum = Effor_Sum,usesteffc_sum = Effort_Com,)
#self.update_story(sp)
#self.update_Bug(sp)
def update_model(obj, **params):
"""
:param obj: generic model object
:param params: fields, value dict of the obj's model
:return: updated object
"""
is_updating = False
for key in params:
try:
field = getattr(obj, key)
value = params[key]
if field==value:
print 'same value'
elif ((not value) and (not field)): print 'No value for '+key
else:
print 'updating value'
is_updating = True
setattr(obj, key, value)
# obj.field = value
except AttributeError as ex:
print ex
if is_updating:
obj.save()
return obj
How can I insert the data into database if the field and value are not same.I don't want to update the table.