0

I'm trying to program a simple test app where

  • First screen: says "hi", then below there is a "next" button to click and access to the next page

  • Second page: says "enter your email address", then below there is a text input box to write the email address, and a "validate" button below it, to send the email address to an online ElephantSQL database

I have a .py file with the python script where you have the "submit" function, which is supposed to send the email address to the online ElephantSQL database, and finally give a "thank you" message once it's done. It seems like I'm doing something wrong as I get an error which tells me the below:

 Traceback (most recent call last):
   File "C:\Users\User\Documents\Pers\Python\test\test.py", line 100, in <module>
     Yes().run()
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\app.py", line 955, in run
     runTouchApp()
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 339, in mainloop
     self.idle()
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 383, in idle
     self.dispatch_input()
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 334, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 302, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy\_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1191, in kivy._event.EventObservers._dispatch
   File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 55, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\User\Documents\Pers\Python\test\Test.kv", line 77, in <module>
     on_release: app.submit()
   File "C:\Users\User\Documents\Pers\Python\test\test.py", line 88, in submit
     cur.execute(psycopg_command, values)
 psycopg2.errors.NotNullViolation: null value in column "id" violates not-null constraint       
 DETAIL:  Failing row contains (null, [email protected]).

Below is my python .py file code:

from kivy.app import App
from kivy.uix.gridlayout import GridLayoutException
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
import os
import urllib.parse as up
import psycopg2

#define our different windows (hence our different pages in our app)
class FirstWindow(Screen):
    pass

class SecondWindow(Screen):
    pass

#define our screen manager (hence what manages the different pages in our app)
class WindowManager(ScreenManager):
    pass 

# designate our .kv design file
kv = Builder.load_file('Test.kv')

class Yes(App):
    def build(self):
        

        url = up.urlparse("DB.URL")

        # connect to the database 
        conn = psycopg2.connect("dbname='DB.NAME' user='DB.USER' host='DB.HOST' password='DB.PWD'")

        # create the database cursor
        cur = conn.cursor()
        # insert the query to create the table (if not yet
        #  created) in which the data (email addresses
        # will be stored)
        cur.execute("CREATE TABLE if not exists emails(id INT GENERATED BY DEFAULT AS IDENTITY, address text NOT NULL)")
        
        # commit changes
        conn.commit()
        # close the connection to the database
        conn.close()

        return kv
    
    # define our submit function, i.e. the function which will be
    # triggered when we click to send the email address to be
    # stored in the database    
    def submit(self):

        # database URL
        url = up.urlparse("DB.URL")

        # connect to the database 
        conn = psycopg2.connect("dbname='DB.NAME' user='DB.USER' host='DB.HOST' password='DB.PWD'")
            
        # create the database cursor
        cur = conn.cursor()
        # insert the query to submit the data,
        # i.e. email addresses to the database 
        psycopg_command = "INSERT INTO emails (address) VALUES (%s)"
        values = (kv.get_screen('second').ids.input_box.text,)
        cur.execute(psycopg_command, values)

        # add message to user once email address has been submitted
        kv.get_screen('second').ids.input_box.text = "Thanks for submitting your email address"
        # clear the input box once the email address has been submitted
        '''kv.get_screen('second').ids.input_box.text = ""'''
        # commit changes
        conn.commit()
        # close the connection to the database
        conn.close()

if __name__ == '__main__':
    Yes().run()

Below is my kivy .kv file code:

#:import NoTransition kivy.uix.screenmanager.NoTransition

WindowManager:
    FirstWindow:
    SecondWindow:

<FirstWindow>:
    name: "first"

    BoxLayout:
        orientation: "vertical"
        size: root.width, root.height

        Label:
            text: "Hi"
            font_size: 32

        Button:
            text: "Next"
            size_hint: 0.3, 0.3
            pos_hint: {"center_x":0.5}
            background_color: 0.06666666666, 0.82352941176, 0.90980392156, 1
            background_normal: ""
            on_release: 
                app.root.current = "second"
                root.manager.transition.direction = "left"

        Widget:
            size_hint: 0.3, None
            height: 6
            canvas:
                Color: 
                    rgb: 0, 0, 0, 1

<SecondWindow>:
    name: "second"

    BoxLayout:
        orientation: "vertical"
        size: root.width, root.height


        Label:
            id: word_label
            text: "Enter your email address"
            font_size: 32

        Widget:
            size_hint: 0.3, None
            height: 6
            canvas:
                Color: 
                    rgb: 0, 0, 0, 1

        TextInput:
            id: input_box
            size_hint: (0.3, 0.2)
            pos_hint: {"center_x":0.5}
            multiline: False
            valign: "center"
            halign: "center"
            text:""

        Widget:
            size_hint: 0.3, None
            height: 6
            canvas:
                Color: 
                    rgb: 0, 0, 0, 1

        Button:
            text: "Validate"
            size_hint: 0.3, 0.3
            pos_hint: {"center_x":0.5}
            background_color: 0.06666666666, 0.82352941176, 0.90980392156, 1
            background_normal: ""
            on_release: app.submit()
                

        Widget:
            size_hint: 0.3, None
            height: 6
            canvas:
                Color: 
                    rgb: 0, 0, 0, 1

        Button:
            text: "Home"
            size_hint: 0.3, 0.3
            pos_hint: {"center_x":0.5}
            background_color: 0.06666666666, 0.82352941176, 0.90980392156, 1
            background_normal: ""
            on_release:
                app.root.current = "first"   
                root.manager.transition = NoTransition()

        Widget:
            size_hint: 0.3, None
            height: 6
            canvas:
                Color: 
                    rgb: 0, 0, 0, 1

I tried to add "NOT NULL" or "NULL" at several places in my python .py file code (in the creation table line after "id INTEGER PRIMARY KEY" or "address text" or also in the cur.execute line after "psycopg" or "values"), but it's still not working...

Anyone may explain to me what I'm doing wrong and what is the correction?

Thanks

7
  • 3
    Your id column is not defined as auto incrementing in the db, so the db is expecting you to send an id value when you insert, but you are not - hence it is complaining about null value in a not null field. You need to create the table like this stackoverflow.com/a/74997579/202168 in order to get an auto id Commented Feb 13, 2023 at 10:45
  • Thanks for your comment. So I need to create the table with "id INTEGER NOT NULL" instead of "id INTEGER PRIMARY KEY NOT NULL" and then alter the table created with the the code lines found in the link your provided. Isn't there another way to proceed? I inspired myself from this tuto here ==> youtube.com/watch?v=jIhpYTq2jLI and he hasn't altered his postgres table at any point... Commented Feb 13, 2023 at 11:46
  • You can directly create the table in the desired state. See postgresqltutorial.com/postgresql-tutorial/… Commented Feb 13, 2023 at 12:53
  • Ok so I tried some tweaks here and there, thanks to your postgresql tuto link, but with no success. And now I have re-read the error message and it actually states that the NotNollViolation error comes from line 88, which is "cur.execute(psycopg_command, values)". I thought the error came from the creation of my table but seems like it is not the case here. Any additional comment on this issue? I'm quite lost at this time... Commented Feb 16, 2023 at 15:49
  • I also had a look at this tuto tutorialsteacher.com/postgresql/…. which is complementary (if not the same) to the one you provided. From my understanding, I feel like my "psycopg_command" value, in my submit function, is not right but I'm having a hard time to find how to correct it. And I'm not even sure if this is really the issue here... Commented Feb 16, 2023 at 16:09

1 Answer 1

0

Change this part of your code to:

# insert the query to create the table (if not yet
# created) in which the data (email addresses
# will be stored)
cur.execute("CREATE TABLE if not exists emails(id int generated always as identity, address text)")
# commit changes
conn.commit()

You can see this working here: https://extendsclass.com/postgresql/694ab89

Sign up to request clarification or add additional context in comments.

11 Comments

Hi, I already tried to modify this line as you wrote, and it is not working. In the submit function, I added the line "OVERRIDING SYSTEM VALUE" as per in postgresqltutorial.com/postgresql-tutorial/… but it is also not working. Finally, I tried to use the "generated by default as identity" so I don't have to use the overriding system value, but it is still not working... I edited my code above, and the resulting error so everything is displayed... Scratching my head right now...
what error do you get? which version of Postgres are you using?
If you are not specifying the id value when you INSERT then you don't need to use OVERRIDING SYSTEM VALUE and it's fine to use GENERATED ALWAYS.
So, I edited the content of my question above, which reflects the code I use (i.e. id INT GENERATED BY DEFAULT AS IDENTITY), and the error I get
I use PostgresQL 15 btw
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.