Sorry @ced
So with the exactly the above code I got compile error (in executing trytond-admin -c trytond.conf -d tryton --all command) like below:
Traceback (most recent call last):
File "/home/tryton/afx_project/.env/bin/trytond-admin", line 33, in <module>
admin.run(options)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/admin.py", line 59, in run
pool.init(update=options.update, lang=list(lang),
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/pool.py", line 143, in init
restart = not load_modules(
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/modules/__init__.py", line 425, in load_modules
_load_modules(update)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/modules/__init__.py", line 395, in _load_modules
load_module_graph(graph, pool, update, lang, indexes)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/modules/__init__.py", line 221, in load_module_graph
register_classes(classes, module)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/modules/__init__.py", line 181, in register_classes
cls.__register__(module)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/model/modelsql.py", line 463, in __register__
table = cls.__table_handler__(module_name)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/model/modelsql.py", line 447, in __table_handler__
return backend.TableHandler(cls, history=history)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/backend/table.py", line 23, in __new__
instance._init(model, history=history)
File "/home/tryton/afx_project/.env/lib/python3.10/site-packages/trytond/backend/postgresql/table.py", line 44, in _init
self.is_owner, = cursor.fetchone()
TypeError: cannot unpack non-iterable NoneType object
So I asked Qwen AI and I was told to implement TableHandlerInterface, so I did below:
class ProjectTrackListRecord(ModelSQL, ModelView):
'Project Track List'
__name__ = 'afx.project.tracklist.record'
_table = 'afx_project_tracklist_record' # Name of your actual DB view
project_id = fields.Integer('Project ID')
resource_id = fields.Char('Resource ID')
resource_name = fields.Char('Resource Name')
client_name = fields.Char('Client Name')
pic = fields.Char('PIC')
team = fields.Char('Team')
proj_no = fields.Char('Project No')
proj_name = fields.Char('Project Name')
po_no = fields.Char('PO No')
so_no = fields.Char('S/O No')
# quote_no = fields.Char('Quote No')
# loa = fields.Char('LOA')
start_date = fields.Char('Start Date')
end_date = fields.Char('End Date')
# duration = fields.Char('Duration')
# allocation = fields.Char('Allocaion')
# status = fields.Char('Project Status')
# completion = fields.Char('Completion')
@classmethod
def __setup__(cls):
cls._readonly = True
cls._history = False
super(ProjectTrackListRecord, cls).__setup__()
@classmethod
def __table_handler__(cls, module_name=None, **kwargs):
return ViewTableHandler(cls)
class ViewTableHandler(TableHandlerInterface):
"""
A custom table handler for mapping Tryton models to read-only database views.
Assumes all required columns and table exist in the database.
"""
def _init(self, model, history=False):
"""
Initialize the handler with the model.
Skips ownership checks and DDL operations.
"""
super()._init(model, history=history)
self.exists = True # Assume the view exists
self.is_owner = False # Not an owner (read-only)
self.def_columns = [] # No column definitions to manage
self.not_nulls = set() # Views typically don't enforce NOT NULL
self.uniques = {} # Skip unique constraints
self.indexes = {} # Skip index management
@classmethod
def table_exist(cls, table_name):
"""
Always return True since the view must already exist.
"""
return True
@classmethod
def table_rename(cls, old_name, new_name):
"""
Prevent renaming of views via Tryton.
"""
pass
def column_exist(self, column_name):
"""
Assume all columns exist; useful for skipping field-related checks.
"""
return True
def alter_size(self, column_name, column_type):
"""
Skip altering column size.
"""
pass
def alter_type(self, column_name, type_):
"""
Skip changing column types.
"""
pass
def column_is_type(self, column_name, type_, *, size=-1):
"""
Fake confirmation that the column matches the expected type.
"""
return True
def db_default(self, column_name, value):
"""
Skip setting defaults since views cannot have defaults.
"""
pass
def add_column(self, column_name, abstract_type, default=None, comment=''):
"""
Skip adding columns since views are fixed.
"""
pass
def add_fk(self, column_name, reference, on_delete=None):
"""
Skip foreign key operations.
"""
pass
def drop_fk(self, column_name, table=None):
"""
Skip FK removal.
"""
pass
def not_null_action(self, column_name, action='add'):
"""
Skip NOT NULL constraint changes.
"""
pass
def add_constraint(self, ident, constraint):
"""
Skip adding constraints.
"""
pass
def drop_constraint(self, ident, table=None):
"""
Skip dropping constraints.
"""
pass
def create_index(self, index):
"""
Skip creating indexes.
"""
pass
def drop_column(self, column_name):
"""
Skip dropping columns.
"""
pass
@classmethod
def drop_table(cls, model, table, cascade=False):
"""
Skip table deletion.
"""
pass
def column_default(self, column_name):
"""
Return None because views shouldn't have column defaults.
"""
return None
def index_action(self, columns, action='add', where=None):
"""
Skip index actions.
"""
pass
def sequence_exist(self):
"""
Views do not have sequences.
"""
return False
def sequence_create(self):
"""
Skip sequence creation.
"""
pass
def sequence_update(self):
"""
Skip updating sequences.
"""
pass
def sequence_rename(self, old_name):
"""
Skip renaming sequences.
"""
pass
def drop_sequence(self):
"""
Skip dropping sequences.
"""
pass
And this made me passed the compile time, but now I got Runtime Error:
Traceback (most recent call last):
File "/trytond/wsgi.py", line 97, in dispatch_request
return endpoint(request, **request.view_args)
File "/trytond/protocols/dispatcher.py", line 44, in rpc
return methods.get(request.rpc_method, _dispatch)(
File "/trytond/wsgi.py", line 77, in wrapper
return func(request, *args, **kwargs)
File "/trytond/protocols/wrappers.py", line 206, in wrapper
result = func(request, pool, *args, **kwargs)
File "/trytond/protocols/dispatcher.py", line 216, in _dispatch
result = rpc.result(meth(*c_args, **c_kwargs))
File "/trytond/model/modelsql.py", line 1219, in read
getter_result = field.get(ids, cls, fname, values=result)
File "/trytond/model/fields/one2many.py", line 170, in get
targets.append([r.id for r in Target.search(clause, order=order)])
File "/trytond/model/modelsql.py", line 1870, in search
cursor.execute(*select)
File "/trytond/backend/postgresql/database.py", line 78, in execute
cursor.execute(self, sql, args)
psycopg2.errors.UndefinedColumn: column a.id does not exist
LINE 1: SELECT "a"."id" AS "id", "a"."client_name" AS "client_name",...
^
Bromo