How to use BS4 to .find all id css selector - beautifulsoup

I'm following this tutorial. But i got stuck here:
for container in containers:
date = container.find('td', class_ = 'date-action').get_text()
date = parser.parse(date.strip()[6:]).date()
dateli.append(date) #make date relevant to current date
description_container_1 = container.find('td', class_ = 'description TL_NPI_TransDesc')
description_container_2 = description_container_1.find('a', class_ = 'transactionTitle')
description = description_container_2.find('span', class_ = 'transTitleForEditDesc').get_text()
descli.append(description)
amount = container.find('td', class_ = ['amount positive TL_NPI_Amt', 'amount TL_NPI_Amt isDebit']).get_text()
amtli.append(float(price_str(amount)))
My problem is how to replace the ('td', class_ = 'date-action') with 'div"[id*="wtDataMov"]', since its the only way to identify the lines i want to get is by a specific part of the a big id LT_BPINetEmpresas_wt37_block_wtMainContent_CW_Contas_Empresas_wtMovimentos_block_wtMovimentosList2_ctl04_wtDataMov.

To use a CSS selector use .select(). In your case to only find the first tag use .select_one()
...
date = container.select_one('div[id*=breakoutLeft]').get_text()

Related

Odoo: Override Integer field in onchange not working whereas Float is changed - WHY?

I have extended the product.template with following fields:
length = fields.Integer("Length", default=0)
length_float = fields.Float("Float", default=0.0)
Additionally I have extended the product.packaging model with this fields and an onchange method:
product_id_ref = fields.Many2one('product.product', string="Product Reference")
length = fields.Integer('Length')
length_float = fields.Float('Length_Float')
#api.onchange("product_id_ref")
def _onchange_product(self):
if self.product_id_ref:
self.length_float = self.product_id_ref.length_float
self.length = self.product_id_ref.length
Interestingly the FLOAT field length_float is changed as expected and shown in the view. The INTEGER field is not changed.
Something more suprising is that if I change the order of the onchange method
#api.onchange("product_id_ref")
def _onchange_product(self):
if self.product_id_ref:
self.length = self.product_id_ref.length
self.length_float = self.product_id_ref.length_float
NO value is changed!
How could that be?? Does anyone have an idea?
Thanks!
It came out that the problem was the 'length' field itself. This name leads to problems on the javascript side. Renaming leads to the desired result.

I am trying to set a series name dynamicallly in amcharts

I passing data into a line series but I cannot dynamically add anything to series.name I just get the string rather that teh variable.
I tried using .dataFields.name but this is teh incorrect syntax.
Please advise?
J
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "value"+ seriesId;
series.dataFields.dateX = "date";
series.name = "BrandNM"+ seriesId;
series.strokeWidth = 2;

How to change value of multiple fields onchange

I want to change the value of Ordered Qty (product_uom_qty) and prix unitaire (price_unit) when changing the Ligne Contrat. But my onchange functions only work for the Ordered Qty, although both functions are called correctly.
Here is my code :
from datetime import datetime, timedelta
from odoo import api, fields, models, _
# Contrat model
class Contrat(models.Model):
_name = 'contrat.contrat'
_rec_name = 'contrat_name'
contrat_name = fields.Char(string='Nom')
contrat_number = fields.Integer(string="Numero")
date_start = fields.Date(string='Date Debut')
date_end = fields.Date(string="Date Fin")
date_deadline = fields.Date(string="date echeance")
ligne_id = fields.One2many('contrat.lignes','ligne_ids',"mylignes")
# notebook_ids = fields.Many2one('contrat.lignes','ligne_id',string='Notebook')
client_name = fields.Many2one('res.partner',string="Client")
bons_ligne_ids = fields.One2many('sale.order.line', 'contrat_name_id', String='Contrat bons')
class ContratOrder(models.Model):
_name = 'contrat.lignes'
_rec_name = 'ligne_name'
ligne_ids = fields.Many2one('contrat.contrat',string="Contrat")
ligne_name = fields.Char(string="Nom de Ligne")
unit_price = fields.Float(string='Prix Unitaire')
article_name = fields.Many2one('product.template', string="Article")
quantity = fields.Float(string='Quantite')
# modifier les lignes des bons de commands
class bons_lignes(models.Model):
_inherit="sale.order.line"
bons_po = fields.Integer('PO')
contrat_name_id = fields.Many2one('contrat.contrat', string='Contrat')
contrat_lignes_id = fields.Many2one('contrat.lignes', string='Ligne contrat')
product_uom_qty = fields.Float('qtt', related='contrat_lignes_id.quantity')
price_unit = fields.Float(string='Prix Unitaire')
#api.onchange('contrat_lignes_id')
def onchange_conrat_lignes_id(self):
self.price_unit = self.contrat_lignes_id.unit_price
How is it possible to change both fields with one or more onchange functions.
EDIT: Odoo already has a onchange trigger on field product_uom_qty which is changing the field price_unit after calling my onchange methods. How is it possible to get my onchange functions get called later, or just forbid Odoo to call its other functions?
Just use a single onchange method to change both fields.
#api.onchange('contrat_lignes_id')
def onchange_conrat_lignes_id(self):
self.product_uom_qty = self.contrat_lignes_id.quantity
self.price_unit = self.contrat_lignes_id.unit_price

Odoo: Access field by it's name (given as string)

I have a model, where I want to access a field, given by a string. Example:
def test(self):
field = 'name'
name = getattr(self, field)
This works fine - name is set to self.name. But then I want to access a related field:
def test2(self):
field = 'partner_id.name'
name = getattr(self, field)
That doesn't work (because 'partner_id.name' does not exist on self). Any idea how to do it right?
getattr doesn't support the dot notation, only simple attribute names. You can however create a simple function that does:
def getfield(model, field_name):
value = model
for part in field_name.split('.'):
value = getattr(value, part)
return value
You would use it like this:
def test2(self):
field = 'partner_id.name'
name = getfield(self, field)
You need to use the object that contain partner_id.name
def test2(self):
field = 'name'
object = self.pool.get('res.partner').browse(cr, uid, self.partner_id.id)#v7
#object = self.env['res.partner'].browse(self.partner_id.id)#v8
name = getattr(object, field)
I also came across another solution, inspired by the mail template system:
from openerp.tools.safe_eval import safe_eval as eval
def test2(self):
field = 'partner_id.name'
field = 'object.' + field
name = eval(field, {'object': self})

Outputting data from variables in coder

I'm working in PsychoPy to design an experiment. It's almost complete, but I'm trying to output a few variables that I created in a code component into my data file for the experiment, and I haven't been able to figure out how to do that. Here is some relevant code:
if branch == 1:
if money.keys == 'left':
feedback = 'You chose $10 immediately'
TotalNow = TotalNow + 10
add = (amount - 10)/2
amount = add + amount
elif money.keys == 'right':
feedback = 'You chose $%.2f in two weeks' %(amount)
TotalLater = TotalLater + amount
TLtext = '%.2f' %(TotalLater)
amount = (amount + 10)/2
elif money.keys in ['', [], None]:
feedback = 'You did not make a choice. No reward given.'
amount = amount
if branch == 2:
if money.keys == 'right':
feedback = 'You chose $10 immediately'
TotalNow = TotalNow + 10
add = (amount - 10)/2
amount = add + amount
elif money.keys == 'left':
feedback = 'You chose $%.2f in two weeks' %(amount)
TotalLater = TotalLater + amount
TLtext = '%.2f' %(TotalLater)
amount = (amount + 10)/2
elif money.keys in ['', [], None]:
feedback = 'You did not make a choice. No reward given.'
amount = amount
I would like to output the following variables into the data file: 'TotalLater', 'TotalNow', and 'amount'. I've tried a few things, but it doesn't seem that I'm close. Any help would be appreciated.
Use the addData() method of the current experiment handler (which by default is named thisExp in Builder:
# specify each column name and its associated variable:
thisExp.addData('TotalLater', TotalLater)
thisExp.addData('TotalNow', TotalNow)
thisExp.addData('amount', amount)
Do this at the end of the relevant routine to save the current values for that trial.
If you like writing your own code, and want to learn a bit more Python, look into dictionaries which store things as "key" and "value" pairs. You start somewhere are the beginning of your program to create the dictionary with all the keys you want, and then as the program runs you store the values in the dictionary. Before the first trial you can use a function to write the keys as the column headings of a spreadsheet, and then each trial add lines with the values. For instance:
import csv ; #to use the spreadsheet export
def createDataFile(fh,d):
#fh is the handle for a file you created
#d is the name of the dictionary you have created
cdw = csv.DictWriter(fh,fieldnames = d.keys(),quoting = csv.QUOTE_MINIMAL)
cdw.writeheader()
return(cdw)
Here are some example lines from a dictionary where I am setting the values for the conditions of an expriments, note that some of these lines have keys where the value is another dictionary - the dictionaries are nested.
dty['tstX'] = dty['xoffset']['r']
dty['cbCon'] = dict(r = dty['tstCon'], l = dty['stdCon'])
dty['cbOri'] = dict(r = dty['tstStrOri'], l = dty['stdStrOri'])
dty['stdX'] = dty['xoffset']['l']
In your case you would have values for dty['amt'] = amount and at the end of a trial, you would use the function writerow() to put the latest values in their right place in the spreadsheet.
I know this is a lot more detailed, and less intuitive then the above, but you can use dictionaries in lots of places, and they are pretty darn handy.
As I have been cutting and pasting from a file of ours, the above code will likely not work out of the box for you, but will hopefully provide some useful guide posts for your own explorations.