I am trying to add many2one field in a setting page in odoo11. I am able to add char or integer field in a setting page but with Many2one field I get an error.
The Error :
psycopg2.DataError: invalid input syntax for integer:"double.accounts(406,)"
LINE 1: ...FROM "double_accounts" WHERE "double_accounts".id IN ('double.acco...
here is my code :
class AccountSetting(models.TransientModel):
_inherit = 'res.config.settings'
authtoken_module = fields.Char(default_model='account.move')
organization_module = fields.Char(default_model='account.move')
double_accounts_id = fields.Many2one('double.accounts', string="double Entery", default_model='account.move')
def get_values(self):
res = super(AccountSetting, self).get_values()
res.update({
'authtoken_module': self.env['ir.config_parameter'].sudo().get_param('account.authtoken_module', default=''),
'organization_module': self.env['ir.config_parameter'].sudo().get_param('account.organization_module'),
#### the error that i am facing from this line
'double_accounts_id': self.env['ir.config_parameter'].sudo().get_param('account.double_accounts_id', default=''),
####
})
return res
def set_values(self):
super(AccountSetting, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('account.authtoken_module', (self.authtoken_module or ''))
self.env['ir.config_parameter'].sudo().set_param('account.organization_module', (self.organization_module or ''))
self.env['ir.config_parameter'].sudo().set_param('account.double_accounts_id', (self.double_accounts_id or ''))
Haven't looked very well into it. But it seems you get a recordset out of your parameter instead of an ID. So a simple solution is to put a .id to the end of the marked line. But that isn't the full solution, cause your default has to be changed to self.sudo().env['account.double_accounts_id'], where .id will work, too.
I'm really wondering why you get a recordset, maybe someone can answer that.
Related
im trying to add a string to an ArrayField and I'm getting DETAIL: Array value must start with "{" or dimension information. error.
this is how the model looks like the method update_credential is where im trying to add the merchant_id to merchants ArrayField.
class CloverCredential(models.Model):
tenant = models.OneToOneField('tenant.Tenant', unique=True, on_delete=models.CASCADE)
token = EncryptedCharField(max_length=255, null=True)
spreedly_receiver_token = EncryptedCharField(max_length=255, null=True)
merchants = ArrayField(models.CharField(max_length=200, blank=True), null=True)
def update_credential(self, new_token, merchant_id):
self.token = new_token
self.merchants = merchant_id
self.save()
This is the view where im calling update_credential and passing token and merchant_id
class OAuthCallback(APIView):
def api_request(self, path):
return requests.get(path).json()
def get(self, request, *args, **kwargs):
code = request.GET.get('code', '')
state = unsign_state(request.GET.get('state', ''))
merchant_id = request.GET.get('merchant_id', '')
tenant = get_object_or_404(Tenant, pk=state['tenant_id'])
clover_credential, created = CloverCredential.objects.get_or_create(tenant=tenant)
url = f'{settings.CLOVER_URL_US}/oauth/token?client_id={settings.CLOVER_APP_ID}&client_secret={settings.CLOVER_APP_SECRET}&code={code}'
oauth_response = self.api_request(url)
clover_credential.update_credential(oauth_response['access_token'], merchant_id)
return redirect(state['redirect'])
i also tried to append merchant_id to merchants
self.merchants.append(merchant_id)
and got this error
AttributeError: 'NoneType' object has no attribute 'append'
Problem
The field merchants is a list but by default it is null.
Solution
So the best things to do is set a default=list.
Error Explanation
Array value must start with "{" or dimension information.
This occurs because you are puttting a variable inside a list, instead do this self.merchants = [merchant_id, ]
'NoneType' object has no attribute 'append'
This occurs because you have a None, not a list. Make an empty list the default value or set it by code: self.merchants = list()
Further to this, my context was adding an ArrayField to a Django model, and on initial migration failing because I was passing it a string as a default, which the migration file referenced and failed out on when it interfaced with PSQL.
Solved this by hand-editing the migration file, finding the initial migration default string and putting brackets around the string.
Doesn't happen on future instances as I think the ArrayField implementation explicitly casts a comma separated list with brackets as part of the save operation, just not on the initial migration if it's expecting a default.
In hr.holidays model for employee_id field onchange function is there but I removed that onchange function from 'employee_id' field.The main aim of that function is Auto filling of 'department_id' field of same model when the change of 'employee_id' field.
problem:
My requirement is the below code is existing in odoo v7 but i need in odoo v8.
I tried in different ways but I didn't get any result so please help me.
def onchange_employee(self, cr, uid, ids, employee_id):
result = {'value': {'department_id': False}}
if employee_id:
employee = self.pool.get('hr.employee').browse(cr, uid, employee_id)
result['value'] = {'department_id': employee.department_id.id}
return result
My odoo V8 code:
I am getting object of 'hr.employee' but I am unable to fill that object in 'department_id' field because of it is many2one field.Below is my code.
#api.onchange('employee_id')
#api.constrains('employee_id')
def joining_date(self):
if self.employee_id:
self.department_id =''
depart_obj = self.env['hr.employee'].search([('name', '=' , self.employee_id.name)])
if depart_obj:
for departments in depart_obj:
depart_new_obj = self.env['hr.employee'].browse([departments.id])
for tax in depart_new_obj.department_id:
self.department_id = [tax.id]
Why are you searching and browsing object if you have already object of self.employee_id
just set
self.department_id = self.employee_id.department_id.id
At finally I got the answer removing of [ ] .""self.department_id = tax.id""
I'm trying to make this table with a clickable field which changes the boolean for the entry to its opposite value. It works, but I want an alternative text as "False" or "True" does not look nice, and the users are mainly Norwegian.
def bool_to_norwegian(boolean):
if boolean:
return "Ja"
else:
return "Nei"
class OrderTable(tables.Table):
id = tables.LinkColumn('admin_detail', args=[A('id')])
name = tables.Column()
address = tables.Column()
order = tables.Column()
order_placed_at = tables.DateTimeColumn()
order_delivery_at = tables.DateColumn()
price = tables.Column()
comment = tables.Column()
sent = tables.LinkColumn('status_sent', args=[A('id')])
paid = tables.LinkColumn('status_paid', args=[A('id')], text=[A('paid')])
class Meta:
attrs = {'class': 'order-table'}
If you look under the "paid" entry I am testing this right now, why can't I access the data with the same accessor as I do in the args? If I change the args to args=[A('paid')] and look at the link, it does indeed have the correct data on it. The model names are the same as the ones in this table, and "paid" and "sent" are BooleanFields.
This is kind of what I ultimately want:
text=bool_to_norwegian([A('paid')])
Here is what I send to the table:
orders = Order.objects.order_by("-order_delivery_at")
orders = orders.values()
table = OrderTable(orders)
RequestConfig(request).configure(table)
The text argument expects a callable that accepts a record, and returns a text value. You are passing it a list (which it will just ignore), and your function is expecting a boolean instead of a record. There is also no need for using accessors here.
Something like this should work:
def bool_to_norwegian(record):
if record.paid:
return "Ja"
else:
return "Nei"
Then in your column:
paid = tables.LinkColumn('status_paid', text=bool_to_norwegian)
(Note, it is not clear from your question where the data is coming from - is paid a boolean? You may need to adjust this to fit).
As an aside, the way you are passing args to your columns is weird (it seems the documentation also recommends this, but I don't understand why - it's very confusing). A more standard approach would be:
id = tables.LinkColumn('admin_detail', A('id'))
or using named arguments:
id = tables.LinkColumn('admin_detail', accessor=A('id'))
Hello to all I have been developing module under Odoo 8. I have a class "hrEmployee" with "_inherit=hr.employee" , now in my hrEmployee there is a One2many field having relation with another model "hr.employee.visa". I want to get the field values of the "hrEmployee" with onchange function defined on the field of "hr.employee.visa". Like when I change field value of "hrEmployee", I can get the field value entered on the current form (hrEmployee). How am I able to achieve this in Odoo v8? My Python code is shown below:
class hrEmployee(models.Model):
_inherit = "hr.employee"
diwan_no = fields.Char('Diwan No', size=30, help='Diwan Number')
zeo_number = fields.Char('ZEO Number',size=30, help='ZEO Number')
visas_ids = fields.One2many('hr.employee.visas', 'employee_id', 'Visas')
class hr_employee_visas(models.Model):
_name='hr.employee.visas'
employee_id = fields.Many2one("hr.employee.visas", "Employee" )
#api.onchange('visas_number')
#api.depends( 'visas_number')
def _visa_num(self):
cr=self._cr
uid=self._uid
ids=self._ids
for id in ids:
obj1=self.pool.get('hr.employee').browse(cr,uid,id,context=None)
print obj1.name_related
visas_sponsor = fields.Char('Sponsor')
visas_states = fields.Selection([('apply','Apply'),('active','Active'),('expire','Expire'),('cancel','Cancelled')], string='State' )
visas_number = fields.Char('Visa No', help='Visa Number')
I tried to use self.pool.get browse but it gives me "False" . Plz guide me or point me my mistake. Hopes for suggestion
Try following,
class hr_employee_visas(models.Model):
_name='hr.employee.visas'
employee_id = fields.Many2one("hr.employee", "Employee" )
#api.onchange('visas_number')
#api.depends( 'visas_number')
def _visa_num(self):
for obj in self:
print obj.employee_id.name
Here is the mistake
employee_id = fields.Many2one("hr.employee.visas", "Employee" )
You need to set hr.employee here.
No need to write both of the decorators together, in case of any changes into the visas_number field this method will be called, you can use any of the single decorator for this.
I am trying to iterate over form results and I can't help but think that I am re-inventing the wheel here.
filterlist = []
if request.POST:
form = FilterForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.iteritems():
filterlist.append(key)
filterlist.append(value)
This works, but seems very awkward and creates lots of other problems. For example the values come back with u' so I have to use value.encode("utf8") but then if a value is None it throws in error. So now I have to check if it is None, if not then encode. There has to be a better way.
EDIT: What I am trying to do.
I am trying to filter what is shown on a page. The problem I am running into is that if a value is empty (the user don't fill the box because they only want to filter against one object) then I get no results. For example a user wants to search for all books by the author name "Smith" but doesn't want to search against a genre.
results = Books.objects.filter(author=author, genre=genre)
The user would get no results because this is an AND search. But, if a user put in "Smith" for the author and "mystery" for the genre then it works exactly like I want it to, only giving results where both are true.
So, I am trying to eliminate the empty stuff by iterating over the form results. Like I said I am probably re-inventing the wheel here.
In Python 3 use:
for key, value in form.cleaned_data.items():
If the field names are the same in the model and the form, try this:
filter = {}
if request.method == 'POST':
form = FilterForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.iteritems():
if value:
filter[key] = value
results = Books.objects.filter(**filter)
Python is one of the few languages having named parameters. You can assemble a dict with the non-empty form fields and pass it to the filter method using the kwargs unpacking operator **.
For example:
kwargs = {"author": "Freud"}
results = Books.objects.filter(**kwargs)
Is the same as:
results = Books.objects.filter(author="Freud")
I think the problem is that by default the Model form is not valid if a form field does not have a value entered by the user, if you don`t require the field every time from the user you need to set the required field to false in the ModelForm class in forms.py as shown in the code below. Remember that the field is set false only in the model form not in the model itself
class myForm(forms.ModelForm):
myfield_id = forms.CharField(required=False)
myfield_foo = forms.CharField(required=False)
myfield_bar = forms.CharField(required=False)
myfield_name = forms.CharField(required=False)
class Meta:
model = myModel
exclude = ('myfield_ex','myfield_file')
fields = ['myfield_id','myfield_foo','myfield_bar','myfield_name',]
After you have the form entered by the user what you need is use the Q object which can be used to create complex queries as described in the manula page here
https://docs.djangoproject.com/en/1.7/topics/db/queries/#complex-lookups-with-q
A simple example code would look like
if form.is_valid():
qgroup = []
for key,value in form.cleaned_data.iteritems():
if value:
q_name = Q(**{"%s"%format(filterKey[key]) : value})
qgroup.append(q_name)
q = None
# can use the reduce as shown here qgroup = reduce(operator.or_, (Q(**{"{0}".format(filterKey[key]): value}) for (key,value) in form.cleaned_data.iteritems()))
for key,value in form.cleaned_data.iteritems():
if value:
q_name = Q(**{"%s"%format(filterKey[key]) : value})
qgroup.append(q_name)
for x in qgroup:
q &= x ### Or use the OR operator or
if q:
resultL = myModel.objects.filter(q).select_related()
The filterKey can look something on the lines of
filterKey = {'myfield_id' : "myfield_id",
'myfield_foo' : "myfield_foo__icontains",
'myfield_bar' : "myfield_bar__relative_field__icontains",
}