set attribute to qstandarditem in pyqt5 - pyqt5

Basically I have a QTableView and I use View Model for the table and then append to model as following:
for i in range(0, 10):
self.tableViewModel.appendRow([QStandardItem("%s" % ("Hello")), QStandardItem("%s" % ("How are you?"))])
I want to set i as an attribute to each row where later I could access to understand which is which.
Is there a way to set an attribute to QStarndardItem?

Related

Odoo: how to set default field for many2many field by id?

i want to set default value in many2many field for example:
that field in models.py:
# alarms
alarm_ids = fields.Many2many(
'calendar.alarm', 'calendar_alarm_calendar_event_rel',
string='Reminders', ondelete="restrict",
help="Notifications sent to all attendees to remind of the meeting.")
also it is default values created by system, and i want first variant by default:
i know that i can set it by id, but dont know how.
You can use Command to set X2many field values.
From the documentation:
Via Python, we encourage developers craft new commands via the various functions of this namespace. We also encourage developers to use the command identifier constant names when comparing the 1st element of existing commands.
Example:
from odoo import Command, models, fields
class CalendarEvent(models.Model):
_inherit = 'calendar.event'
alarm_ids = fields.Many2many(default=lambda self: [Command.link(self.env.ref('calendar.alarm_notif_1').id)])
i just watch in postgres, there is no id`s like in xml screenshots, i just take id of a record and find some documentation.
next example works:

Django ImageFieldFile set to <ImageFieldFile: null>. How to change it to blank/empty, like other entries in the table?

I have a FileField in a Django Model. Some entries in this FileField are set to <ImageFieldFile: null>.
The rest of the Model table are blank or actual images. I need to clean this table so that these erroraneous entries are also changed to blank, as this is not acceptable in my DRF API.
Get all the image instance.
objs =myclassmodel.objects.all() //just assuming this
for obj in objs:
obj.image = ""
obj.save()
It will you if understand it right.

Expected singleton odoo 9

After enter 2 and more new row in tree view and click on save get error
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: my.model(2116, 2117)
My source code:
#api.depends('start', 'finish','stop')
def total_fun(self):
time1 = datetime.strptime(self.start, "%Y-%m-%d %H:%M:%S")
time2 = datetime.strptime(self.finish, "%Y-%m-%d %H:%M:%S")
self.total = round(((time2 - time1).seconds / float(60*60) - self.stop))
Error message says -> expected singleton this means: you are using recordset instead of record.
To fix this use
for rec in self:
in the begining of function, and then use rec instead of self
As you can see in the error message Expected singleton: my.model(2116, 2117)
By default in odoo the self is always a recordSet (means it can contain more then one record.) so when you do self.getSomeField here odoo will be confused wich record you want to get the value from.
if you don't tell odoo that make sure that the self will always contain one record when you acces an attribute if the recordSet contains more than one record this error is raised.
Now how to tell odoo make sure there is always one record is by adding #api.one decorator to the method. but is not recommended because odoo in your case there is two record so he will loop and call the method for each record and pass a recordSet that have only that record. imagine that you execute a search or any communication with database.
so don't use #api.one only if you are sure of what you are doing because you can make 10000 method call and interact with database.
like this example using #api.one:
# every call to this method you will execute a search.
self.env['some.model'].search([('m2o_id' , '=', self.id)]
you can do this before the loop:
# one query for all record with one call to the method
result = self.env['some.model'].search([('m2o_id' , 'in', self.ids)]
for rec in self:
# use result here
# or here ..

QTableView does not retain changes or update after adding records

I am constructing a GUI which displays the contents of a SQL database table and which should allow addition and modification of records through the GUI, using the base PyQt4 classes QTableView and QSqlTableModel. I am having problems with editing the table view.
Here is a Minimal, Complete and Verifiable version of the complete code. It does require changing the login info of whatever SQL database you are using, but besides that the code is sufficient to run the interface:
import sys
import site
from subprocess import Popen
from PyQt4.QtCore import(Qt)
from PyQt4.QtGui import(QMainWindow, QApplication, QWidget, QPushButton, qApp,
QVBoxLayout, QTableView, QApplication)
from PyQt4.QtSql import(QSqlDatabase, QSqlQuery, QSqlQueryModel, QSqlTableModel)
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
# Open and connect to database - this needs to be changed for the particular db you are using
self.__database = QSqlDatabase.addDatabase('QPSQL')
self.__database.setHostName('localhost')
self.__database.setDatabaseName('~/Desktop/H2 testing/TESTING/db/db')
self.__database.setPort(5435)
self.__database.setUserName('grav')
self.__database.setPassword('XXXXXXXXXX')
self.__database.open()
ok = self.__database.open()
if ok == False:
print 'Could not open database'
print 'Text: ', self.__database.lastError().text()
print 'Type: ', str(self.__database.lastError().type())
print 'Number: ', str(self.__database.lastError().number())
print 'Loaded drivers:', str(QSqlDatabase.drivers())
# Create the QSqlTableModel using the database
self.modelDirections = QSqlTableModel(None, self.__database)
self.modelDirections.setTable('PUBLIC.DIRECTIONS')
self.modelDirections.setEditStrategy(QSqlTableModel.OnFieldChange)
self.modelDirections.select()
# Create the QTableView and connect to the QSqlTableModel
self.tableDirections = QTableView()
self.tableDirections.setModel(self.modelDirections)
# Create a QPushButton to add a row to the table
self.buttonAddDir = QPushButton('Add direction')
self.buttonAddDir.clicked.connect(self.createDirection)
# Set up the rest of the window with the QTableView and the QPushButton
vbox = QVBoxLayout()
vbox.addWidget(self.tableDirections)
vbox.addWidget(self.buttonAddDir)
stretchBox = QWidget()
stretchBox.setLayout(vbox)
self.setCentralWidget(stretchBox)
self.show()
def createDirection(self):
# Define and execute query to determine current max direction serial
model = QSqlQueryModel()
query = 'SELECT * FROM directions WHERE id=(SELECT MAX(id) FROM directions)'
model.setQuery(query)
if model.record(0).value('id').toString() == '':
newDirectionSerial = 0
else:
newDirectionSerial = int(model.record(0).value('id').toString()) + 1
# Define queries to insert new direction record
queryText = 'INSERT INTO public.directions (id, text, olddir, opposite) \
VALUES (%s, NULL, 1, NULL)' % (newDirectionSerial)
query = QSqlQuery()
query.exec_(queryText)
if __name__ == "__main__":
app = QApplication(sys.argv)
newWindow = Window()
sys.exit(app.exec_())
On loading the GUI, the table displays correctly in the QTableView. However, I have 2 problems:
I am able to double-click into a field in the table and begin editing, but then when I double-click into another field, anything I entered in the first field disappears.
When I edit a field and then switch to editing a new field, I get the message "Data changed" even though whatever I entered disappears.
My best guess here is that the data is being changed in the QSqlTableModel but then for some reason not translating through to the underlying database field, and when the view refreshes, it does so with an updated model from the still-empty database field.
When I add a new record using the button, the new record doesn't show up. If I close out the script and then start it up again, the new record shows up.
These may well be 2 separate problems but I have a feeling they're related.
I have managed to gather some more information about issue 1 since first posting this problem:
After connecting the QSqlTableModel.dataChanged signal to a reporter function, I'm able to confirm that
The signal is indeed firing when I edit the table-view fields,
The data is not being transferred from the model to the database, because of a problem with the query. The database is returning the following error:
ERROR: Column "text" not found; SQL statement: UPDATE PUBLIC.DIRECTIONS SET "text"='test' WHERE "id" = 1 AND "text" = 'constitutes' AND "dir" = 1 AND "opposite" = 2 [42122-164]
(42S22) QPSQL: Unable to create query
I'm able to access the database through another application and I test-ran variants of this query. Stripping the quotes around the field names and getting rid of the trailing [42122-164] produces a successful query and the behavior I've been looking for.
That's great - but I want the QSqlTableView to handle this, and don't know how. Anyone clues to how to modify the query behavior of the view (without completely rebuilding it) would be immensely appreciated!

Using compute Method for Calculating Values in Odoo Module customization?

My aim is to create a CRM-Lead extension module in Odoo. My modules aim is to add certain more fields to the Lead section in The CRM Odoo module.
I created a module code which is working fine but one problem is that I have a field named percentage in it, which should calculate like
amount * 100 & store in database. So for that I used compute attribute in Model. But its is not calculating the value... I will provide my code below :-
from openerp import models, fields, api
class legacy_sales(models.Model):
_inherit='crm.lead'
legacy_description = fields.Text(string="Comments")
legacy_amount = fields.Float(string="Amount")
legacy_startdate = fields.Date(string="StartDate")
legacy_percentage = fields.Float(compute='_compute_percentage',store=True)
#api.depends('legacy_amount')
def _compute_percentage(self):
self.legacy_percentage = self.legacy_amount * 100
legacy_sales()
Here legacy_percentage is not storing calculated value in database.. please give advice:-
Browse self to set field value:
for record in self:
record.legacy_percentage= record.legacy_amount * 100