Get the string of two upper levels in foraign relations - python-3.x

Good Morning,
How to get the value Entity.name about ProjectsComments row.
Top model :
class Entities(models.Model):
code = models.CharField(verbose_name='Código', max_length=10, blank=False, unique=True,
help_text='Codigo de entidad.')
name = models.CharField(max_length=150, verbose_name='Nombre', unique=True,
help_text='Nombre de la entidad.')
def __str__(self):
return self.name
def toJSON(self):
item = model_to_dict(self)
return item
Second Level:
class Projects(models.Model):
entity = models.ForeignKey(Entities, on_delete=models.DO_NOTHING, verbose_name="Entidad")
def __str__(self):
return f'{self.entity}' + ' \ ' + f'{self.code}' + ' \ ' + f'{self.name}' # + ' \ ' + f'{self.phase}'
def toJSON(self):
item = model_to_dict(self)
item['entity'] = self.entity.toJSON()
return item
Third Level
class ProjectsComments(models.Model):
project = models.ForeignKey(Projects, on_delete=models.DO_NOTHING, default=0, verbose_name='Proyecto',
help_text='Proyecto')
def __str__(self):
return f'{self.date}' + f' ' + f'#' + f'{self.user}' + f'# ' + f'{self.comment}'
def toJSON(self):
item = model_to_dict(self)
item['project'] = self.project.toJSON()
item['entity'] = Entities.objects.get(pk = )
item['user'] = self.user.toJSON()
return item
I would need that from projectscommentsListView get the value of ProjectsComments__Projects__Entity.name
I have tried get into ProjectsComments.toJSON() with :
item['entity'] = Entities.objects.get(pk = )
AND
item['entity'] = self.entity.toJSON()
I do not know anymore.

You can get the entity from your project since they are related
item['entity'] = self.project.entity.toJSON()
No need for another query.

Related

Threading while loading wxGrid - Python

I'm loading a wxGrid with values from a dataframe. I'm trying to use threading so my GUI doesn't freeze(some of the SQL tables are ~60,000 x 16 and take some time to load), but I guess I'm not understanding the concept. Sometimes it runs just fine works.
Other times it crashes and exits with:
Could not convert to integer: 3221226525. Path 'exitCode'.
Value was either too large or too small for an Int32.
I have also tried implementing another thread so that my wx.gauge loads properly. That causes it to fail more often. Can anyone give me any leads? I've been stuck on this for hours.
Snippets from my code:
I also tried implementing another thread to update the wx.Gauge seperately with no success. The gauge updated but had very weird behavior. Any help would be greatly appreciated.
EDIT CODE ADDED Warning, this is probably going to be ugly
import sys
import os
import wx
import wx.grid as gridlib
import wx.lib.agw.pygauge as PG
import mysql.connector as sql
import MySQLdb
import datetime
import pandas as pd
from collections import OrderedDict
import threading #as thread
import time
from time import sleep
#import urllib
#result_available = threading.Event()
#df_data=pd.DataFrame()
class PageOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#wx.StaticText(self, -1, "This is a PageOne object", (20,20))
class PageTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#wx.StaticText(self, -1, "This is a PageTwo object", (40, 40))
class PageThree(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
#wx.StaticText(self, -1, "This is a PageThree object", (60, 60))
class PageDynamic(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
wx.StaticText(self, -1, "This is a Dynamic object", (60, 60))
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Varkey Foundation") #none
#Layout
self.__DoLayout()
def __DoLayout(self):
self.SetBackgroundColour( wx.Colour( 58, 56, 56 ) )
# Here we create a panel and a notebook on the panel
self.p = wx.Panel(self)
self.p.SetBackgroundColour( wx.Colour( 0, 0, 0 ) ) # 38,38,38
#self.Show() <Layout Error when GUI is launched
self.Maximize(True)
self.nb = wx.Notebook(self.p)
self.nb.SetBackgroundColour(wx.Colour(58, 56, 56) )
#CreateFonts
self.b_font = wx.Font(14,wx.ROMAN,wx.NORMAL,wx.BOLD, True)
self.lbl_font = wx.Font(14,wx.ROMAN,wx.NORMAL,wx.NORMAL, True)
self.cb_font = wx.Font(11,wx.SCRIPT,wx.ITALIC,wx.NORMAL, True)
self.h_font = wx.Font(18,wx.DECORATIVE,wx.ITALIC,wx.BOLD, True)
#Create Title bmp
ico = wx.Icon('varkey_bmp.bmp', wx.BITMAP_TYPE_ICO)
self.SetIcon(ico)
# create the page windows as children of the notebook
self.page1 = PageOne(self.nb)
self.page2 = PageTwo(self.nb)
self.page3 = PageThree(self.nb)
# add the pages to the notebook with the label to show on the tab
self.nb.AddPage(self.page1, "Data")
self.nb.AddPage(self.page2, "Analyze")
self.nb.AddPage(self.page3, "Change Log")
#Create widgets for top sizer
self.lbl_user = wx.StaticText(self.p,label="Username:")
self.lbl_password = wx.StaticText(self.p,label="Password:")
self.lbl_interaction = wx.StaticText(self.p,label="Interaction:")
self.lbl_table = wx.StaticText(self.p,label="Table:")
#SetForground colors
self.lbl_user.SetForegroundColour((255,255,255))
self.lbl_password.SetForegroundColour((255,255,255))
self.lbl_interaction.SetForegroundColour((255,255,255))
self.lbl_table.SetForegroundColour((255,255,255))
#Set Fonts
self.lbl_user.SetFont(self.lbl_font)
self.lbl_password.SetFont(self.lbl_font)
self.lbl_interaction.SetFont(self.lbl_font)
self.lbl_table.SetFont(self.lbl_font)
self.tc_user =wx.TextCtrl(self.p,size = (130,25))
self.tc_password =wx.TextCtrl(self.p, style=wx.TE_PASSWORD | wx.TE_PROCESS_ENTER,size = (130,25))
self.tc_password.Bind(wx.EVT_TEXT_ENTER,self.onLogin)
self.tc_user.SetFont(self.cb_font)
self.tc_password.SetFont(self.cb_font)
self.btn_login = wx.Button(self.p,label="Login", size=(105,25))
self.btn_login.SetBackgroundColour(wx.Colour(198, 89, 17))
self.btn_login.SetFont(self.b_font)
self.btn_login.Bind(wx.EVT_BUTTON, self.onLogin) #connect_mysql
self.btn_logout = wx.Button(self.p,label="Logout",size=(105,25))
self.btn_logout.SetBackgroundColour(wx.Colour(192,0,0))
self.btn_logout.SetFont(self.b_font)
self.btn_logout.Bind(wx.EVT_BUTTON, self.onLogout)
self.combo_interaction = wx.ComboBox(self.p, size = (160,25),style = wx.CB_READONLY | wx.CB_SORT | wx.CB_SORT)
self.combo_interaction.Bind(wx.EVT_COMBOBOX, self.onComboInteraction)
self.combo_table = wx.ComboBox(self.p, size = (160,25),style = wx.CB_READONLY | wx.CB_SORT | wx.CB_SORT)
self.combo_table.Bind(wx.EVT_COMBOBOX, self.onHideCommands)
self.combo_interaction.SetFont(self.cb_font)
self.combo_table.SetFont(self.cb_font)
#self.combo_table.Bind(wx.EVT_COMBOBOX ,self.OnComboTable)
self.btn_load = wx.Button(self.p,label="Load Table", size=(105,25))
self.btn_load.SetBackgroundColour(wx.Colour(31, 216, 6))
self.btn_load.SetFont(self.b_font)
self.btn_load.Bind(wx.EVT_BUTTON, self.onLoadData)
#Create Widgets for bottom sizer
self.lc_change = wx.ListCtrl(self.p,-1,style = wx.TE_MULTILINE | wx.LC_REPORT | wx.LC_VRULES)
self.lc_change.InsertColumn(0,"User ID")
self.lc_change.InsertColumn(1,"Status")
self.lc_change.InsertColumn(2,"Description")
self.lc_change.InsertColumn(3,"Date/Time")
#Set column widths
self.lc_change.SetColumnWidth(0, 75)
self.lc_change.SetColumnWidth(1, 75)
self.lc_change.SetColumnWidth(2, 450)
self.lc_change.SetColumnWidth(3, 125)
#Add Row Button
self.btn_new = wx.Button(self.page1,label="+", size = (35,25))
self.btn_new.SetForegroundColour(wx.Colour(112,173,71))
self.btn_new.SetFont(self.h_font)
self.btn_new.Bind(wx.EVT_BUTTON, self.onInsertRecordBelow)
#Page 1 - Create grids/sizers and add to notebook
self.color1 = (0,0,0)
self.title = wx.StaticText(self.page1,label="",style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE)
self.title.SetForegroundColour((255,255,255))
self.title.SetFont(self.h_font)
self.data_grid = gridlib.Grid(self.page1)
self.data_grid.CreateGrid(0,0) #219,16
self.p1_sizer = wx.BoxSizer(wx.VERTICAL)
self.p1_sizer.Add(self.title,0,wx.EXPAND,5)
self.p1_sizer.Add(self.data_grid,3,wx.RIGHT |wx.LEFT |wx.EXPAND, 20)
self.p1_sizer.Add(self.btn_new,-0,wx.ALIGN_CENTER,5)
self.page1.SetSizer(self.p1_sizer)
#Page 2 - Create grids/sizers and add to notebook #<<<<<<< Need to create correct table size
self.analyze_grid = gridlib.Grid(self.page2)
self.analyze_grid.CreateGrid(0, 10)
self.p2_sizer = wx.BoxSizer(wx.VERTICAL)
self.p2_sizer.Add(self.analyze_grid,1,wx.EXPAND)
self.page2.SetSizer(self.p2_sizer)
#Page 3 - Create Change Log
self.log_grid = gridlib.Grid(self.page3)
self.log_grid.CreateGrid(0, 9)
self.log_grid.EnableEditing(False)
self.p3_sizer = wx.BoxSizer(wx.VERTICAL)
self.p3_sizer.Add(self.log_grid,1,wx.EXPAND)
self.page3.SetSizer(self.p3_sizer)
#Insert Image
self.staticbitmap = wx.StaticBitmap(self.p)
#browse = wx.Button(self.p, label='Browse')
#browse.Bind(wx.EVT_BUTTON, self.OnBrowse)
self.staticbitmap.SetBitmap(wx.Bitmap('varkey_logo2.jpg'))
self
#Create Filler text
self.lbl_filler = wx.StaticText(self.p,label="",size = (125,20))
#Create FlexGridSizers(For top half)
self.left_fgs = wx.FlexGridSizer(3,4,25,15)
self.left_fgs.AddMany([(self.lbl_user,1,wx.ALIGN_LEFT | wx.LEFT,15),(self.tc_user,1,wx.EXPAND),(self.lbl_interaction,1,wx.ALIGN_RIGHT|wx.RIGHT, 10),(self.combo_interaction,1,wx.EXPAND),
(self.lbl_password,1,wx.ALIGN_LEFT| wx.LEFT,15),(self.tc_password,1,wx.EXPAND),(self.lbl_table,1,wx.ALIGN_RIGHT|wx.RIGHT, 10),(self.combo_table),
(self.btn_login,2,wx.EXPAND),(self.btn_logout,1,wx.EXPAND),(self.lbl_filler,1,wx.EXPAND),(self.btn_load,1)])
#Create Top Sizer and add FGS
self.top_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.top_sizer.Add(self.left_fgs,proportion = 1, flag = wx.ALL|wx.EXPAND,border = 30)
#self.top_sizer.Add(self.right_fgs,proportion = 1, flag = wx.TOP|wx.BOTTOM ,border = 30)
self.top_sizer.Add(self.staticbitmap,2,wx.TOP | wx.RIGHT, border = 40) #30
self.top_sizer.Add(self.lc_change,2,wx.RIGHT|wx.EXPAND ,30)
#Create bottom sizer(For Grid)
self.bottom_sizer = wx.BoxSizer(wx.VERTICAL)
self.bottom_sizer.Add(self.nb,proportion = 5, flag = wx.LEFT |wx.RIGHT | wx.EXPAND,border = 30)
#Create statusbar and progress bar
self.gauge = wx.Gauge(self.p, range = 100, size = (400, 20),style = wx.GA_HORIZONTAL)
#self.gauge = PG.PyGauge(self.p, 0, size=(400, 25), style=wx.GA_HORIZONTAL)
#self.gauge.SetDrawValue(draw=True, drawPercent=True, font=None, colour=wx.BLACK, formatString=None)
#self.gauge.SetBackgroundColour(wx.WHITE)
#self.gauge.SetBorderColor(wx.BLACK)
self.dummylbl = wx.StaticText(self.p,label="",size = (5,20))
self.status_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.status_sizer.Add(self.gauge, 1, wx.ALIGN_CENTER|wx.ALL, 5)
self.status_sizer.Add(self.dummylbl, 0, wx.ALL, 5)
# the layout
self.mainsizer = wx.BoxSizer(wx.VERTICAL)
self.mainsizer.Add(self.top_sizer,proportion = 0, flag = wx.ALL|wx.EXPAND,border = 5)
self.mainsizer.Add(self.bottom_sizer,proportion = 1,flag = wx.ALL|wx.EXPAND,border = 5)
self.mainsizer.Add(self.status_sizer,proportion =0,flag = wx.BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, border = 15)
self.p.SetSizerAndFit(self.mainsizer)
#self.page3.Bind(wx.EVT_LEFT_DCLICK, self.dynamic_tab)
self.gauge.Hide()
self.hideWidgets()
self.onHideCommands(self)
def thread_start(self): #self,event
th = threading.Thread(target=self.populateGrid) #args=(event,), args=(self,)
th.start()
#th.join()
#result_available.wait()
#def status_thread(self): #TRIED FEEDING STATUS BAR HERE
# thr = threading.Thread(target=self.update_statusbar)
# thr.start()
#def update_statusbar(self):
#self.gauge.SetValue((round(i/self.rows)*100))
def hideWidgets(self): #Hide and disable widgets until login
if self.btn_logout.IsShown(): #Initialize and logout
self.btn_logout.Hide()
self.btn_load.Disable()
self.combo_interaction.Enable(False)
self.combo_table.Enable(False)
self.tc_user.Enable()
self.tc_password.Enable()
self.btn_login.Show()
else: #When logged in
self.btn_logout.Show()
self.combo_interaction.Enable(True)
self.combo_table.Enable(True)
self.btn_login.Hide()
self.tc_user.Disable()
self.tc_password.Disable()
def onHideCommands(self, event):
cbval = self.combo_table.GetValue()
if cbval:
self.btn_load.Enable()
self.btn_new.Enable()
else:
self.btn_load.Disable()
self.btn_new.Disable()
def onLogin(self,event):
#Get permissions from SQL table
self.tbl = 'permissions'
self.connect_mysql()
#try:
sql_query = "SELECT * FROM " + self.tbl
try:
self.cursor.execute(sql_query)
num_fields = len(self.cursor.description)
self.df_permissions = pd.read_sql(sql_query, con=self.db_con)
except:
self.stat = "ERROR"
self.msg = "ERROR: Failed to Connect. Check your internet connection and try again."
wx.MessageBox("Failed to Connect. Check your internet connection and try again.", 'CONNECTION ERROR',
wx.OK | wx.ICON_ERROR)
self.updateStatus()
return
if(len(self.tc_user.GetValue()) > 0):
id = str(self.tc_user.GetValue())
base = r'^{}'
expr = '(?:\s|^){}(?:,\s|$)'
try:
u = self.df_permissions[self.df_permissions.iloc[:,0].str.contains(base.format(''.join(expr.format(id))),na = False, case = False)].index.values[0]
#u = ((self.df_permissions[self.df_permissions.iloc[:,0].str.match(self.tc_user.GetValue())].index).values)[0] #,na=False,case=False
pwrd = (self.df_permissions.iloc[u,1])
except:
wx.MessageBox("Access denied. " + id + " is not an authorized user.", 'Access Denied',
wx.OK | wx.ICON_ERROR)
return
#If password is correct, make connection
if(self.tc_password.GetValue() == pwrd):
self.stat = "Successful"
self.msg = "Access Granted."
self.updateStatus()
self.tbl = 'tables'
sql_query = "SELECT * FROM " + self.tbl
self.cursor.execute(sql_query)
self.df_tables = pd.read_sql(sql_query, con=self.db_con)
if str(self.df_permissions.iloc[u,2])=="ALL":
self.interactionlist = self.df_tables['Interaction'].to_list()
self.interaction_filtered = self.df_tables #< For dependent combobox
else:
read_str = str(self.df_permissions.iloc[u,2])
read_str = read_str.replace(", ", ",")
read_tables = list(read_str.split(","))
self.interaction_filtered = self.df_tables[self.df_tables['Table_Name'].isin(read_tables)]
self.interactionlist = self.interaction_filtered['Interaction'].to_list()
#Remove duplicates and create lists for combobox
self.interactionlist = list(OrderedDict.fromkeys(self.interactionlist))
self.combo_interaction.SetItems(self.interactionlist)
self.hideWidgets()
else:
Access Denied." + "\n")
self.stat = "ERROR"
self.msg = "ERROR: Incorrect Password. Access Denied."
self.updateStatus()
else:
self.stat = "ERROR"
self.msg = "ERROR: Username cannot be blank!"
self.updateStatus()
self.buildChangeLog()
self.close_connection()
def onLogout(self,event):
self.hideWidgets()
self.destroy_Widgets()
def updateStatus(self):
#Update listControl
self.lc_change.Append([self.tc_user.GetValue(),self.stat,self.msg, str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + "\n"])
if self.lc_change.GetItemCount() > 0:
self.lc_change.EnsureVisible(self.lc_change.GetItemCount() - 1)
#Update Log Grid
if self.stat == "UPDATE" or self.stat == "DELETE" or self.stat == "INSERT":
self.log_grid.AppendRows(numRows = 1, updateLabels = True)
r = self.log_grid.GetNumberRows() -1
self.log_grid.SetCellValue(r,0,self.key_id.replace("'",""))
self.log_grid.SetCellValue(r,1,self.tc_user.GetValue())
self.log_grid.SetCellValue(r,2,self.action) #Action
self.log_grid.SetCellValue(r,3,self.tbl)
self.log_grid.SetCellValue(r,4,self.key_col) #'Column #target_col
self.log_grid.SetCellValue(r,5,self.target_col) #'Old Value
self.log_grid.SetCellValue(r,6,self.oVal.replace("'","")) #'New Value
self.log_grid.SetCellValue(r,7,self.nVal.replace("'","")) #'New Value
self.log_grid.SetCellValue(r,8,str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) #Timestamp
#Size the grid
self.log_grid.AutoSizeColumns(True)
#Set Font color
#index = self.lc_change.GetItemCount()
#item = self.lc_change.GetItem(index)
#self.lc_change.SetItemTextColour(index,'red')
#self.lc_change.InsertItem(index,item)
#print(index)
def destroy_Widgets(self):
#Destroy grid
self.Freeze()
self.data_grid.Destroy()
#Reset and insert blank grid
self.tbl = "elite_advocacy"
self.connect_mysql()
sql_query = "SELECT * FROM " + self.tbl
self.cursor.execute(sql_query)
num_fields = len(self.cursor.description)
self.df_data = pd.read_sql(sql_query, con=self.db_con)
rows, cols = (int(self.df_data.shape[0]),int(self.df_data.shape[1]))
self.data_grid = gridlib.Grid(self.page1)
self.data_grid.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.onCellChanged)
self.data_grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_DCLICK,self.onDeleteRecord)
self.data_grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK,self.rightClickMenu)
self.data_grid.CreateGrid(rows,cols)
self.p1_sizer.Insert(1,self.data_grid,1,wx.RIGHT| wx.LEFT| wx.EXPAND, 20)
self.p1_sizer.Layout()
#Clear Rows on log Grid
n = self.log_grid.GetNumberRows()
if n > 0:
self.log_grid.DeleteRows(0,n)
# Clear rows on analyze Grid
n = self.analyze_grid.GetNumberRows()
if n > 0:
self.analyze_grid.DeleteRows(0,n)
#Clear list listCtrl
x = self.lc_change.GetItemCount()
for i in range(x):
self.lc_change.DeleteItem(0)
#Clear textCtrl and ComboBoxes
self.tc_password.SetValue("")
self.tc_user.SetValue("")
self.title.SetLabel("")
self.combo_table.Clear()
self.combo_interaction.Clear()
self.combo_interaction.SetValue("")
self.combo_table.SetValue("")
self.close_connection()
self.Thaw()
def buildChangeLog(self):
self.tbl = 'change_log'
sql_query = "SELECT * FROM " + self.tbl
self.cursor.execute(sql_query)
num_fields = len(self.cursor.description)
#Create Grid Headers
try:
field_names = [i[0] for i in self.cursor.description]
for i,a in enumerate(field_names):
self.log_grid.SetColLabelValue(i,a)
#Size the grid
self.log_grid.AutoSizeColumns(True)
except:
pass
def onComboInteraction(self, event):
self.tables_filtered = self.interaction_filtered[self.interaction_filtered['Interaction'].str.contains(self.combo_interaction.GetValue())]
self.tableslist = self.tables_filtered['Table_Name'].to_list()
self.combo_table.SetItems(self.tableslist)
self.onHideCommands(event)
def dynamic_tab(self, event):
print('dynamic_tab()')
dynamic_page = PageDynamic(self.nb)
self.nb.AddPage(dynamic_page, "Page Dynamic")
def getTable(self):
#Determine SQL table from DataFrame
self.tbl_input = self.combo_table.GetValue()
r = ((self.df_tables[self.df_tables.iloc[:,2].str.contains(self.combo_table.GetValue(),na=False)].index).values)[0]
self.tbl = (self.df_tables.iloc[r,3])
def populateGrid(self):
t0 = time.time()
self.rows, self.cols = (int(self.df_data.shape[0]),int(self.df_data.shape[1]))
for i, seq in enumerate(self.df_data.index):
for j, v in enumerate(self.df_data.columns):
self.data_grid.SetCellValue(i, j, str(self.df_data.iloc[i,j]))
#self.gauge.SetValue(int(round(i/self.rows,2)*100)) #int(percentage*100)
self.gauge.SetValue(0)
self.gauge.Hide()
#Size the grid
self.data_grid.AutoSizeColumns(True)
self.stat = "QUERY"
self.msg = str(self.rows) + " loaded from " + self.tbl
self.updateStatus()
#Set title
self.title.SetLabel(str(self.combo_table.GetValue()))
t1 = time.time()
print(t1-t0)
def onLoadData(self,event):
if self.combo_table.GetValue():
#Establish Connection
self.connect_mysql()
#Get Table
self.getTable()
#self.testFunction()
if self.tbl:
#Get SQL Data
t0 = time.time()
self.gauge.Show()
sql_query = "SELECT * FROM " + self.tbl
self.cursor.execute(sql_query)
num_fields = len(self.cursor.description)
temp = pd.read_sql(sql_query, con=self.db_con)
self.df_data = temp[~pd.isnull(temp).all(1)].fillna('')
pd.set_option('display.max_columns', None)
#Destroy grid and insert new resized grid
rows, cols = (int(self.df_data.shape[0]),int(self.df_data.shape[1]))
self.data_grid.Destroy()
self.data_grid = gridlib.Grid(self.page1)
self.data_grid.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.onCellChanged)
self.data_grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_DCLICK,self.onDeleteRecord)
#self.data_grid.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK,self.showPopupMenu)
self.data_grid.CreateGrid(rows,cols) #self.data_grid.CreateGrid(219, 16)
self.p1_sizer.Insert(1,self.data_grid,1,wx.RIGHT| wx.LEFT|wx.EXPAND, 20)
self.p1_sizer.Layout()
#Create Grid Headers
field_names = [i[0] for i in self.cursor.description]
for i,a in enumerate(field_names):
self.data_grid.SetColLabelValue(i,a)
self.data_grid.AutoSizeColumns(True)
#Populate Table
#####START THREAD#########
self.thread_start()
else: #self.tbl variable is blank
self.stat = "ERROR"
self.msg = "ERROR: No table exists in mySQL for Table: " + "'" + str(self.combo_table.GetValue()) + "'"
self.updateStatus()
return
else:
self.stat = "ERROR"
self.msg = "ERROR: Table Combobox is empty "
self.updateStatus()
return
def connect_mysql(self):
self.db_name = 'db'
self.server = 'server'
self.user_id = 'user1'
self.pw = 'pwrd'
try:
self.db_con = MySQLdb.connect(user=self.user_id,password=self.pw,database=self.db_name,
host=self.server,charset='utf8',autocommit=True)
self.cursor = self.db_con.cursor()
except:
print("Error connecting")
def close_connection(self):
try:
self.db_con.close()
except:
pass
def onCellChanged(self, evt):
self.connect_mysql()
try:
self.key_id = str("'") + self.data_grid.GetCellValue(evt.GetRow(),0) + str("'")
self.target_col = self.data_grid.GetColLabelValue(evt.GetCol())
self.key_col = self.data_grid.GetColLabelValue(0)
self.nVal = str("'") + self.data_grid.GetCellValue(evt.GetRow(),evt.GetCol()) + str("'")
sql_update = "UPDATE " + self.tbl + " SET " + self.target_col + " = " + self.nVal + " WHERE " + self.key_col + " = " + self.key_id + ""
print(sql_update)
self.cursor.execute(sql_update)
self.stat = "UPDATE"
self.oVal = evt.GetString()
self.action = "UPDATE"
self.msg = "Changed " + str("'") + self.oVal + str("'") + " to " + self.nVal + " for " + self.key_id + " in table: " + str("'") + self.tbl + str("'")
self.updateStatus()
except:
self.stat = "ERROR"
self.msg = "ERROR: Failed to update SQL table. " + "'" + self.tbl + "'"
self.updateStatus()
self.db_con.rollback()
self.close_connection()
def onInsertRecordBelow(self, evt):
self.key_id = str("'") + self.data_grid.GetCellValue(evt.GetRow(),0) + str("'")
self.target_col = "" #self.data_grid.GetColLabelValue(evt.GetCol())
self.key_col = self.data_grid.GetColLabelValue(0)
self.del_row = evt.GetRow()
dlg = wx.TextEntryDialog(self.p,'Enter a new Key ID to insert into the ' + str("'") + self.data_grid.GetColLabelValue(0) + str("'") + ' column.', 'Insert New Record')
#dlg.SetValue("Default")
if dlg.ShowModal() == wx.ID_OK:
#print('You entered: %s\n' % dlg.GetValue())
val = dlg.GetValue()
#Check if it exists in database
self.connect_mysql()
checkRec = ("SELECT " + str(self.key_col) + "," + " COUNT(*) FROM " + str(self.tbl) + " WHERE " + str(self.key_col) + " = " + "'" + str(val)
+ "'" + " GROUP BY " + str(self.key_col) + "")
self.cursor.execute(checkRec)
results = self.cursor.fetchall()
row_count = self.cursor.rowcount
if row_count > 0:
print("Exists")
self.stat = "ERROR"
self.msg = "ERROR: INSERT FAILED. " + "'" +str(val) + "'" + " already exists in table: " + "'" + self.tbl + "'." + " Abort."
self.close_connection()
self.updateStatus()
return
else:
try:
self.connect_mysql()
sql_update = ("INSERT INTO " + str(self.tbl) + "(" + self.key_col + ")" + "VALUES (" + str("'") + str(val) + str("'") + ")")
self.cursor.execute(sql_update)
#Append row to Grid
lRow = int(self.df_data.shape[0])
lCol = int(self.df_data.shape[1])
self.data_grid.InsertRows(lRow,1)
self.data_grid.SetCellValue(lRow, 0, str(val))
#Insert into Dataframe
self.df_data.append(pd.Series(dtype='object'), ignore_index=True)
#Update status
self.key_id = val
self.stat = "INSERT"
self.msg = "INSERTED record " + "'" + str(val) + "'" + " into table: " + "'" + self.tbl + "'"
self.action = "INSERT"
self.nVal = ""
self.oVal = ""
except:
self.db_con.rollback()
self.stat = "ERROR"
self.msg = "ERROR: Failed to INSERT record '" + str(val) + "'into table: " + "'" + self.tbl + "'"
else:
print("ABORTED")
self.close_connection()
self.updateStatus()
dlg.Destroy
def onDeleteRecord(self,evt):
#Connect
self.connect_mysql()
#Delete from mySQL table
try:
self.nVal = ""
sql_delete = "DELETE FROM " + self.tbl + " WHERE " + self.key_col + " = " + self.key_id + ""
print (sql_delete)
self.cursor.execute(sql_delete)
self.db_con.commit()
self.stat = "DELETE"
self.oVal = ""
self.action = "DELETE"
self.msg = "Deleted Record ID: " + self.key_id + " from " + str("'") + self.tbl + str("'")
#Delete from Grid
self.data_grid.DeleteRows(self.del_row,1,True)
except:
self.stat = "ERROR"
self.msg = "ERROR: Failed to Delete record from table: " + "'" + self.tbl + "'"
self.db_con.rollback()
self.close_connection()
self.updateStatus()
if __name__ == "__main__":
app = wx.App(False)
MainFrame(None).Show() # MainFrame().Show()
app.MainLoop()

Keep all values added by a method in a separate variable

I want to create a method that adds a row to my variable. What I currently have is the following
class Album :
def __init__(self,nbr,nbr_songs):
self.header = 'Album ' + str(nbr) + ' (' + str(nbr_songs) + ' songs)')
def add(self,song,n):
self.line = song
self.nbre = n # This is the count of how many song there is
def __str__(self):
s = self.header
s += '\n' + "{:02}".format(self.nbre) + ': ' + str(self.line)
return s
The output wanted is the following
Album 1 (3 songs)
01: White_Wedding - Billy_Idol - 00:04:12
02: Stand_And_Deliver - Adam_&_The_Ants - 00:03:33
03: You_Spin_Me_Around - Dead_Or_Alive - 00:03:14
The issue is that when I add the three songs to an Album one after the other, it returns the following.
Album 1 (3 songs)
01: You_Spin_Me_Around - Dead_Or_Alive - 00:03:14
I know that my code is missing something but I can't figure out what.
This is by no means a perfect solution but I think it would be a definite improvement to create a separate Song class and maybe even an Artist one too, and have a list of songs in your Album class:
class Song:
def __init__(self, title, artists, duration, album, track_number):
self.title = title
self.artists = artists
self.duration = duration
self.album = album
self.track_number = track_number
def __str__(self):
return f'{self.track_number:02}: {self.title} - {self.artists} - {self.duration}'
class Album:
def __init__(self, number):
self.number = number
self.songs = []
def add_song(self, title, artists, duration):
track_number = len(self.songs) + 1
song = Song(title, artists, duration, self, track_number)
self.songs.append(song)
def __str__(self):
header = f'Album {self.number} ({len(self.songs)} songs)'
str_list = [header]
for song in self.songs:
str_list.append(str(song))
return '\n'.join(str_list)
album = Album(1)
album.add_song('White_Wedding', 'Billy_Idol', '00:04:12')
album.add_song('Stand_And_Deliver', 'Adam_&_The_Ants', '00:03:33')
album.add_song('You_Spin_Me_Around', 'Dead_Or_Alive', '00:03:14')
print(album)
Output:
Album 1 (3 songs)
01: White_Wedding - Billy_Idol - 00:04:12
02: Stand_And_Deliver - Adam_&_The_Ants - 00:03:33
03: You_Spin_Me_Around - Dead_Or_Alive - 00:03:14

Django: Form ValidationError: ['“” value has an invalid date format. It must be in YYYY-MM-DD format.']

I have a form which has few fields which will be date. The user will enter those dates in DD/MM/YYYY format. First I was using the forms.DateField() to store the value which was throwing error becuase of the date format. So changed them to CharField & try to re-format those dates to store it in the DB in YYYY-MM-DD format inside the clean methods but some weird reason it keeps raising the above error & has no information of the field which causing the error. I have spent hours trying to debug that but no luck.
dob, doj, confirmation_date, exit_date are the date fields in the Model & form
My Model:
class Employee(models.Model):
class Meta:
db_table = 'employees'
# emp types
TRAINEE = 1
CONTRACTUAL = 2
PERMANENT = 3
EMP_TYPES = (
(TRAINEE, 'Trainee'),
(CONTRACTUAL, 'Contractual'),
(PERMANENT, 'Permanent'),
)
# active status
ACTIVE = 1
RESINGED = 2
TERMINATED = 3
ABSCOND = 4
LONG_LEAVE = 5
TRN_TO_EMP = 6
EMP_STATUS = (
(ACTIVE, 'ACTIVE'),
(RESINGED, 'RESINGED'),
(TERMINATED, 'TERMINATED'),
(ABSCOND, 'ABSCOND'),
(LONG_LEAVE, 'Active'),
(TRN_TO_EMP, 'TRAINEE TO EMPPLOYEE'),
)
# probation/confirm status
PROBATION = 'p'
CONFIRMED = 'c'
# genders
MALE = 'm'
FEMALE = 'f'
TRASNGENDER = 't'
GENDERS = (
(MALE, 'Male'),
(FEMALE, 'Female'),
(TRASNGENDER, 'Transgender')
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
emp_id = models.CharField(max_length=155)
appointment_ref_id = models.CharField(max_length=255)
personal_email = models.CharField(max_length=255)
contact_number = models.CharField(max_length=50)
emergency_contact_number = models.CharField(max_length=50)
emergency_contact_relation = models.CharField(max_length=255)
dob = models.DateField()
blood_group = models.CharField(max_length=5)
identity_mark = models.CharField(max_length=255, null=True)
aadhar_no = models.CharField(max_length=16)
pan_no = models.CharField(max_length=10)
perm_address = models.TextField() # permanent address
com_address = models.TextField() # communication address
total_exp = models.DecimalField(max_digits=4, decimal_places=2)
total_gt_exp = models.DecimalField(max_digits=4, decimal_places=2)
doj = models.DateField() # date of joining
confirmation_date = models.DateField(null=True)
exit_date = models.DateField(null=True)
emp_type = models.SmallIntegerField(choices=EMP_TYPES)
designation = models.ForeignKey(Designation, on_delete=models.DO_NOTHING)
bank_name = models.CharField(max_length=255)
bank_acc_no = models.CharField(max_length=50)
prb_cnf_status = models.CharField(max_length=2,choices=(
(PROBATION, 'Probation'),
(CONFIRMED, 'Confirmed'),
), default=PROBATION)
employment_status = models.SmallIntegerField(choices=EMP_STATUS, default=ACTIVE)
location = models.ForeignKey(Location, on_delete=models.DO_NOTHING)
pf_no = models.CharField(max_length=255)
uan = models.CharField(max_length=255)
remark = models.CharField(max_length=255,null=True)
gender = models.CharField(max_length=1, choices=GENDERS)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(user.get_name())
# def save(self, *args, **kwargs):
# if not self.id:
# # calulate the confirmation date
# self.confirmation_date = DateTimeHelper.add_months(self.doj, 6)
# super(Employee, self).save(*args, **kwargs)
MY FORM:
class EmployeeForm(forms.ModelForm):
class Meta:
model = Employee
fields = [
'personal_email',
'contact_number',
'emergency_contact_number',
'emergency_contact_relation',
'dob',
'blood_group',
'identity_mark',
'aadhar_no',
'pan_no',
'perm_address',
'com_address',
'total_exp',
'total_gt_exp',
'doj',
'confirmation_date',
'exit_date',
'emp_type',
'bank_name',
'bank_acc_no',
'prb_cnf_status',
'employment_status',
'pf_no',
'uan',
'designation',
'location',
'remark',
'gender'
]
personal_email = forms.CharField(max_length=255)
contact_number = forms.CharField(max_length=10)
emergency_contact_number = forms.CharField(max_length=55)
emergency_contact_relation = forms.CharField(max_length=50)
dob = forms.CharField(max_length=12)
blood_group = forms.CharField(max_length=3)
identity_mark = forms.CharField(max_length=100, required=False)
aadhar_no = forms.CharField(max_length=12)
pan_no = forms.CharField(max_length=10)
perm_address = forms.CharField(max_length=255)
com_address = forms.CharField(max_length=255)
total_exp = forms.DecimalField(max_digits=3, decimal_places=2)
total_gt_exp = forms.DecimalField(max_digits=3, decimal_places=2)
doj = forms.CharField(max_length=12)
confirmation_date = forms.CharField(max_length=10, required=False)
exit_date = forms.CharField(max_length=10, required=False)
emp_type = forms.ChoiceField(choices=Employee.EMP_TYPES)
bank_name = forms.CharField(max_length=255)
bank_acc_no = forms.CharField(max_length=255)
prb_cnf_status = forms.CharField(max_length=2, required=False)
employment_status = forms.ChoiceField(choices=Employee.EMP_STATUS, required=False)
pf_no = forms.CharField(max_length=255)
uan = forms.CharField(max_length=255)
designation = forms.ModelChoiceField(queryset=Designation.objects.all())
location = forms.ModelChoiceField(queryset=Location.objects.all())
remark = forms.CharField(max_length=255, required=False)
gender = forms.CharField(max_length=1)
def clean_personal_email(self):
email = self.cleaned_data['personal_email']
if Employee.objects.filter(personal_email=email).exists():
raise forms.ValidationError(
'Personal email of employee already exist!')
return email
def clean_contact_number(self):
contact_number = self.cleaned_data['contact_number']
if Employee.objects.filter(contact_number=contact_number).exists():
raise forms.ValidationError(
'contact number of employee already exist!')
return contact_number
def clean_aadhar_no(self):
aadhar_no = self.cleaned_data['aadhar_no']
if Employee.objects.filter(aadhar_no=aadhar_no).exists():
raise forms.ValidationError(
'Aadhar number of employee already exist!')
return aadhar_no
def clean_pan_no(self):
pan_no = self.cleaned_data['pan_no']
if Employee.objects.filter(pan_no=pan_no).exists():
raise forms.ValidationError(
'PAN number of employee already exist!')
return pan_no
def clean_doj(self):
doj = self.cleaned_data.get('doj', None)
if doj:
return DateTimeHelper.human_readable_to_sql(doj)
raise forms.ValidationError("Invalid date format")
def clean_dob(self):
dob = self.cleaned_data.get('dob', None)
if dob:
return DateTimeHelper.human_readable_to_sql(dob)
raise forms.ValidationError("Invalid date format")
def clean_confirmation_date(self):
confirmation_date = self.cleaned_data.get('confirmation_date', None)
if confirmation_date:
return DateTimeHelper.human_readable_to_sql(confirmation_date)
return confirmation_date
def clean_exit_date(self):
exit_date = self.cleaned_data.get('exit_date', None)
if exit_date:
return DateTimeHelper.human_readable_to_sql(exit_date)
return exit_date
Date Helper Class:
class DateTimeHelper():
#staticmethod
def human_readable_to_sql(date):
d = datetime.datetime.strptime(date, '%d/%m/%Y').date()
return str(d)
DATE_INPUT_FORMATS = ("%d/%m/%Y",)
Add date input format setting.
OR
forms.DateField(
widget=forms.DateInput(format = '%d/%m/%Y',),
)
in the models.py change models.DateField to models.DateTimeField
class Employee(models.Model):
class Meta:
db_table = 'employees'
# emp types
TRAINEE = 1
CONTRACTUAL = 2
PERMANENT = 3
EMP_TYPES = (
(TRAINEE, 'Trainee'),
(CONTRACTUAL, 'Contractual'),
(PERMANENT, 'Permanent'),
)
# active status
ACTIVE = 1
RESINGED = 2
TERMINATED = 3
ABSCOND = 4
LONG_LEAVE = 5
TRN_TO_EMP = 6
EMP_STATUS = (
(ACTIVE, 'ACTIVE'),
(RESINGED, 'RESINGED'),
(TERMINATED, 'TERMINATED'),
(ABSCOND, 'ABSCOND'),
(LONG_LEAVE, 'Active'),
(TRN_TO_EMP, 'TRAINEE TO EMPPLOYEE'),
)
# probation/confirm status
PROBATION = 'p'
CONFIRMED = 'c'
# genders
MALE = 'm'
FEMALE = 'f'
TRASNGENDER = 't'
GENDERS = (
(MALE, 'Male'),
(FEMALE, 'Female'),
(TRASNGENDER, 'Transgender')
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
emp_id = models.CharField(max_length=155)
appointment_ref_id = models.CharField(max_length=255)
personal_email = models.CharField(max_length=255)
contact_number = models.CharField(max_length=50)
emergency_contact_number = models.CharField(max_length=50)
emergency_contact_relation = models.CharField(max_length=255)
dob = models.Date**Time**Field()
blood_group = models.CharField(max_length=5)
identity_mark = models.CharField(max_length=255, null=True)
aadhar_no = models.CharField(max_length=16)
pan_no = models.CharField(max_length=10)
perm_address = models.TextField() # permanent address
com_address = models.TextField() # communication address
total_exp = models.DecimalField(max_digits=4, decimal_places=2)
total_gt_exp = models.DecimalField(max_digits=4, decimal_places=2)
doj = models.Date***Time***Field() # date of joining
confirmation_date = models.Date***Time***Field(null=True)
exit_date = models.Date***Time***Field(null=True)
emp_type = models.SmallIntegerField(choices=EMP_TYPES)
designation = models.ForeignKey(Designation, on_delete=models.DO_NOTHING)
bank_name = models.CharField(max_length=255)
bank_acc_no = models.CharField(max_length=50)
prb_cnf_status = models.CharField(max_length=2,choices=(
(PROBATION, 'Probation'),
(CONFIRMED, 'Confirmed'),
), default=PROBATION)
employment_status = models.SmallIntegerField(choices=EMP_STATUS, default=ACTIVE)
location = models.ForeignKey(Location, on_delete=models.DO_NOTHING)
pf_no = models.CharField(max_length=255)
uan = models.CharField(max_length=255)
remark = models.CharField(max_length=255,null=True)
gender = models.CharField(max_length=1, choices=GENDERS)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(user.get_name())
# def save(self, *args, **kwargs):
# if not self.id:
# # calulate the confirmation date
# self.confirmation_date = DateTimeHelper.add_months(self.doj, 6)
# super(Employee, self).save(*args, **kwargs

how to use datetime objects in a class instance?

An instance of the Rabbit class is created in a for loop and given a datetime object as init variable
but all instances get the same datetime value.
I expected a time difference for each instance; what am I missing in understanding here?
from datetime import datetime
class Rabbit_birth:
num_eyes = 2 # <- Class variable
num_legs = 4
num_ears = 2
num_tails = 1
num_of_rabbits = 0
def __init__(self, name = 'Rabbit',
fur_colour = 'unknown',
eye_colour = 'unknown',
sex = 'unsexed',
breed = 'unknown',
dob = datetime.now(),
tob = datetime.now()
):
self.name = name # <- Instance variable
self.fur_colour = fur_colour
self.eye_colour = eye_colour
self.sex = sex
self.breed = breed
self.dob = str(dob.strftime("%x"))
self.tob = str(tob.strftime("%X"))
Rabbit_birth.num_of_rabbits += 1
def display_rabbit(self):
dob_time = self.dob+" at "+self.tob
return ("{0.name} is a {0.sex} rabbit"
" and has {0.fur_colour} fur and "
"{0.eye_colour} eyes, {0.name} is "
"of the {0.breed} breed of rabbits.\n"
"{0.name}'s DOB is ").format(self) + dob_time
################################################
print()
print('Number of rabbits is ',Rabbit_birth.num_of_rabbits)
rabbits=[]
def create_rabbit():
lr=[]
rabbit = ('name', 'fur colour', 'eye colour', 'sex', 'breed')
for item in rabbit:
r = input(item+' >')
lr.append(r)
r0,r1,r2,r3,r4=lr
name = Rabbit_birth(r0,r1,r2,r3,r4)
return name
for i in range(3):
name=create_rabbit()
rabbits.append(name)
print(rabbits[i].display_rabbit())
I see the mistake I have made, it's a matter of passing the datetime object in the wrong scope.
Here is the relevant corrected code:
## <- class experiment
from datetime import datetime
class Rabbit_birth:
num_eyes = 2 # <- Class variable
num_legs = 4
num_ears = 2
num_tails = 1
num_of_rabbits = 0
def __init__(self, name = 'Rabbit',
fur_colour = 'unknown',
eye_colour = 'unknown',
sex = 'unsexed',
breed = 'unknown',
dob = None, # This line changed
tob = None # This line changed
):
self.name = name # <- Instance variable
self.fur_colour = fur_colour
self.eye_colour = eye_colour
self.sex = sex
self.breed = breed
self.dob = datetime.now() # This line changed
self.tob = datetime.now() # This line changed
Rabbit_birth.num_of_rabbits += 1
def display_rabbit(self):
# This line below changed
dob_time = str(self.dob.strftime("%x"))+" at "+str(self.tob.strftime("%X"))
return ("{0.name} is a {0.sex} rabbit"
" and has {0.fur_colour} fur and "
"{0.eye_colour} eyes, {0.name} is "
"of the {0.breed} breed of rabbits.\n"
"{0.name}'s DOB is ").format(self) + dob_time
################################################

Loop initilized attributes inside an `class` definition body

How to Loop initilized attributes inside an class definition body?
Supposed a class:
class WakeUp:
def __init__(self,date,time):
self.date = str(date)
self.time = str(time)
self.brush_teeth = brushteeth
.
.
def get_wakeup_activities(self):
return 'date: ' + self.date + 'time' + self.time. + 'brush_teeth', + self.brush_teeth
I intend to avoid the verbose typing, expect to refactor the method as:
def get_wakeup_activities(self):
act_list = ()
for attr in attrs:
act_list.append(attr)
return 'date: %s time:%s brush_teeth: %s' %tuple(act_list)
When the method is called, outputs
date:2017-10-17 time:11:50:27 ...
or more abstract:
def get_wakeup_activities(self):
wakeup_dict = {k:v for k, v in self.attrs}
return wakeup_dict
While command to call:
today_wakeup = Wakeup
today_wakeup.get_wakeup_activities()
Outputs:
{date:2017-10-17, time:11:50:27,....}
class WakeUp:
def __init__(self,date,time, brushteeth):
self.date = str(date)
self.time = str(time)
self.brush_teeth = brushteeth
def get_wakeup_activities(self):
return self.__dict__
today_wakeup = WakeUp('today', '8am', 'YES!')
print(today_wakeup.get_wakeup_activities())

Resources