OOP design issue - 'postulantet' object has no attribute 'tabla_postulante'

Viewed 46

I have a problem using tkinter and object-oriented programming. I have 3 functions:

  1. First I have the v2() function which is a function that allows to open a second window through a button and show the data saved in the database

  2. My second function is agregar_postulantes(). This function saves the data in the database.

  3. My third function is the one that saves the data of agregar_postulantes() and send it to the v2() function.

I want to emphasize that all the functions are in the same class and are declared outside the __init__().

A short version of the code:

def v2(self):
    self.tabla_postulante=ttk.Treeview(tablaBD,columns=("Name","last name","id")
    self.tabla_postulante.heading("Name",text="Name")
    self.tabla_postulante.heading("last name",text="last name")
    self.tabla_postulante.heading("id",text="id")

    self.tabla_postulante['show']='headings'
    self.tabla_postulante.column("Name",width=100)
    self.tabla_postulante.column("last name",width=100)
    self.tabla_postulante.column("id",width=100)
    self.fetch_all()
    self.tabla_postulante.pack(fill=BOTH,expand=1)

def agregar_postulantes(self):
    con = pymysql.connect(host="localhost", user="root",password="", database="postulantebd")
    cur = con.cursor()
    cur.execute("insert into postulantes values(%s, %s, %s)",(
            self.name_var.get(),
            self.lastname_var.get(),
            self.id_var.get(),
            ))
    con.commit()
    self.fetch_all()
    con.close()

def fetch_all(self):
    con = pymysql.connect(host="localhost", user="root",password="", database="postulantebd")
    cur = con.cursor()
    cur.execute("select * from postulantes")
    rows=cur.fetchall()
    if len(rows)!=0:
        self.tabla_postulante.delete(*self.tabla_postulante.get_children())
        for row in rows:
            self.tabla_postulante.insert('',END,values=row)
        con.commit()
    con.close()

The error that appears is the following:

Traceback (most recent call last):
  File "C:\Users\dimitri\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:\Users\dimitri\Documents\Programas de Yolo\practicadeinterfazypoo\tkinter\interfaz_tesis_poo.py", line 273, in agregar_postulantes
    self.fetch_all()
  File "C:\Users\dimitri\Documents\Programas de Yolo\practicadeinterfazypoo\tkinter\interfaz_tesis_poo.py", line 282, in fetch_all
    self.tabla_postulante.delete(*self.tabla_postulante.get_children())
AttributeError: 'postulante' object has no attribute 'tabla_postulante'

the error is because I am calling the v2 function after saving the data using the other two functions How can I call the v2 function afterwards and not show errors?

1 Answers

It seems likely that, as the AttributeError states, self has no tabla_postulante attribute. Since you create a table_postulante attribute on self in the v2 function, I'd guess that you don't define self.table_postulante in the __init__() or you aren't calling v2() prior to calling fetch_all().

Which should mean you have a couple options:

  1. create some logic in fetch_all() that checks for the existence of self.tabla_postulante and only executes if that attribute is found. That could take the form of a try/except statement.

  2. Alternatively, define the self.tabla_postulante attribute in your call to __init__() when the object is instantiated.

Update

A little more detail about implementing what I described above. I'm going to assume you aren't creating a self.tabla_postulante attribute on your class in the __init__(), since if you were you wouldn't be getting a ValueError when the function goes looking for it.

So this gives you a couple options. One would be to simply ensure that when you instantiate your class the __init__() creates a self.table_postulante attribute like so:

class ClassName:
    def __init__(self):
        #create attribute here
        self.table_postulante = ttk.Treeview(tablaBD,columns=("Name", "last name","id")
        ...

Another option, if this doesn't make sense for the application you're developing, is to do some exception handling inside fetch_all(). For instance you could do something like:

if len(rows)!=0:
    try:
        self.tabla_postulante.delete(*self.tabla_postulante.get_children())
        for row in rows:
            self.tabla_postulante.insert('',END,values=row)
        con.commit()
    except:
        #define some appropriate response to this attribute not existing here

Your use case will of course determine which approach makes the most sense. Hope this helps.

Related