Search code examples
pythontkinter

TypeError: simple_query() takes 2 positional arguments but 3 were given


Code:

from tkinter import *
import tkinter as tk
import mysql.connector

def main():
    root = tk.Tk()
    app = MainWindow(root)
    root.mainloop()

class mySQL:
    def __init__(self):
        #MySQL Credentials
        self.db = mysql.connector.connect(
        host="XXXX-XX99",
        user="root",
        passwd="TEST",
        database="technical")
        #Cursor
        self.cursor = self.db.cursor()

    def simple_query(self,sql):
        self.cursor.execute(sql)


class MainWindow:
    def __init__(self,master):
        self.master = master
        self.master.state('zoomed')
        self.master.geometry('400x700')
        self.frame = Frame(self.master)
        self.frame.pack(fill="both", expand=True)
        #Entries and text-box
        self.nameLabel = Label(self.frame, text = "Name of Person Making Request:")
        self.nameEntry = Entry(self.frame)
        # Buttons
        self.btn = Button(self.frame, text = "Submit", command = self.sendData)
        # Organizing above^
        self.nameLabel.pack()
        self.nameEntry.pack()
        self.btn.pack()

    def sendData(self):
        x = mySQL()

        #Values
        values = (
        self.nameEntry.get(),
        )

        #Insert Command
        x.simple_query("INSERT INTO document_control (person) values ('%s')", values)


if __name__ == '__main__':
    main()

Goal:

Inside my class mySQL and function simple_query(self,sql) is used in my class MainWindow at function sendData(self). (see x.query("INSERT...") I am trying to make this work, simply insert values into MySQL.

When I press the button submit- (activates function sendData(self)) error comes up with:

TypeError: simple_query() takes 2 positional arguments but 3 were given

I am not quite sure why the output is TypeError.

Where Im I going wrong here? Which section of the code do I need to change? And what needs changing?


Solution

  • def simple_query(self, sql):
         self.cursor.execute(sql)
    

    and

    x.simple_query("INSERT INTO document_control (person) values ('%s')", values)
    

    Here you are passing 2 arguments to simple_query (the query string and values) but it only accepts one, sql (self is the instance, in this case x, and is passed implicitly).


    Other answers make your code work, but they also make it vulnerable to SQL injection.

    For example, if someone were to enter the string a'); delete from document_control; -- in the GUI then the executed query will be

    INSERT INTO document_control (person) values ('a'); delete from document_control; -- ')
    

    Not so good...


    Instead of using string interpolation you should use a parameterized query. It can be done by allowing simple_query to accept an optional arguments tuple.

    def simple_query(self, sql, args=None):
        if not args:
            self.cursor.execute(sql)
        else:
            self.cursor.execute(sql, args)
    

    Keep in mind that args should be a tuple or a list.