Search Routine Error in for loop

Struggling here, I made some changes to a working search routine and broke it.
Glossing over the details a little, the chosen search item is chosen and a query is performed on a db.

Search

def search_records(session, filter_choice, keyword):
    """
    Searches the database based on the filter chosen and the keyword
    given by the user
    """
    if filter_choice == "Budget Item":
        print('Budget Chosen')
        qry = session.query(Ledger)
        result = qry.filter(Ledger.budgetItem.contains('%s' % keyword)).all()
        records = []
        for record in result:
            for item in record.budgetItem:
                records.append(item)
        result = records
    elif filter_choice == "Date":
        qry = session.query(Ledger)
        result = qry.filter(Ledger.itemDate.contains('%s' % keyword)).all()
    ledger = convert_results(result)
    return ledger

Error

Traceback (most recent call last):
  File "G:\Projects\Python\GUI\wxPython\wxAccMan\wxAccMan.py", line 456, in search
    self.ledger_results = controller.search_records(self.session,
  File "G:\Projects\Python\GUI\wxPython\wxAccMan\controller.py", line 153, in search_records
    ledger = convert_results(result)
  File "G:\Projects\Python\GUI\wxPython\wxAccMan\controller.py", line 84, in convert_results
    ledger = OlvLedger(record.id, record.itemDate,
AttributeError: 'str' object has no attribute 'id'

Any thoughts you have are appreciated.

Okay, and what was the code for the working version? What actually changed? The first step to debugging is to locate a problem.

Aside from that: when you call convert_results(result), what is your understanding of the interface? What type do you think result should have, and what should its contents be like? What is your understanding of how convert_results will use result in order to compute the ledger?

Being somewhat detached from the full source code, it’s not easy to make any constructive comments, but I’d be concentrating on the last two line of the Traceback:

ledger = OlvLedger(record.id, record.itemDate,
AttributeError: 'str' object has no attribute 'id'

… and examine the record object, which seems to be a string object at this point.

I presume the convert_results has something like for record in result: .... To debug why record is a string, you need to know whether filter_choice was “Budget Item” or “Date” so you know which type of result had that string.

conver_results iterates over OlvLedger

def convert_results(results):
    """
    Convert results to Olv objects
    """
    print(f" Contoller.py convert_results: {results}")
    ledgerItems = []
    for record in results:
        ledger = OlvLedger(record.id, record.itemDate,
                       record.description, record.budgetItem,
                       record.credit, record.debit, record.balance
                       )
        ledger.append(ledgerItems)
        print(f"convert_results: {ledgerItems}")
    return ledgerItems

OlvLedger(object)

class OlvLedger(object):
    """
    Ledger model (Object) for ObjectListView in main
    """

    def __init__(self, id, itemDate, description, budgetItem, credit, 
                 debit, balance):
   
        self.id = id  # unique row id from database
        self.ItemDate = itemDate
        self.description = description
        self.budgetItem = budgetItem
        self.credit = credit
        self.debit = debit
        self.balance = balance

I think your on to something. Still not clear on the error that seems to be associated with a missing attribute that I don’t explicitly call.

ledger = OlvLedger(record.id, record.itemDate,
AttributeError: 'str' object has no attribute 'id'

Thanks @tjreedy

olvLedger is never called because record.id fails. You need to look back at the generation of records in the result list and see what went wrong there. And that depends on which filter was used.