title: DatabaseError: Field 'school_id' doesn't have a default value
body: <p>I'm currently using mysqlalchemy, kivy, installer and main to take user input from a GUI and store it in an sql database. When trying to add data from my 'adding_data_for people'. This error occurs. I know the error is not in kivy but I bet it has something to do with the installer. Also I just want to store the data, nothing else. Sorry for the long and messy code pieces in advance. </p>
  
  <pre><code>    Traceback (most recent call last):
      File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
   cursor, statement, parameters, context
      File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
   cursor.execute(statement, parameters)
      File "/usr/lib/python3.6/site-packages/mysql/connector/cursor.py", line 515, in execute
   self._handle_result(self._connection.cmd_query(stmt))
      File "/usr/lib/python3.6/site-packages/mysql/connector/connection.py", line 488, in cmd_query
   result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
      File "/usr/lib/python3.6/site-packages/mysql/connector/connection.py", line 395, in _handle_result
   raise errors.get_exception(packet)
    mysql.connector.errors.DatabaseError: 1364 (HY000): Field 'school_id' doesn't have a default value
  
    The above exception was the direct cause of the following exception:
  
     Traceback (most recent call last):
     File "/home/cse/git/soft_161_homework/milestone_1/main.py", line 215, in &lt;module&gt;
   app.run()
     File "/usr/lib64/python3.6/site-packages/kivy/app.py", line 855, in run
   runTouchApp()
     File "/usr/lib64/python3.6/site-packages/kivy/base.py", line 504, in runTouchApp
   EventLoop.window.mainloop()
     File "/usr/lib64/python3.6/site-packages/kivy/core/window/window_sdl2.py", line 747, in mainloop
   self._mainloop()
     File "/usr/lib64/python3.6/site-packages/kivy/core/window/window_sdl2.py", line 479, in _mainloop
   EventLoop.idle()
     File "/usr/lib64/python3.6/site-packages/kivy/base.py", line 342, in idle
   self.dispatch_input()
     File "/usr/lib64/python3.6/site-packages/kivy/base.py", line 327, in dispatch_input
   post_dispatch_input(*pop(0))
     File "/usr/lib64/python3.6/site-packages/kivy/base.py", line 233, in post_dispatch_input
   listener.dispatch('on_motion', etype, me)
     File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
    File "/usr/lib64/python3.6/site-packages/kivy/core/window/__init__.py", line 1402, in on_motion
   self.dispatch('on_touch_down', me)
     File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
     File "/usr/lib64/python3.6/site-packages/kivy/core/window/__init__.py", line 1418, in on_touch_down
   if w.dispatch('on_touch_down', touch):
     File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
     File "/usr/lib64/python3.6/site-packages/kivy/uix/screenmanager.py", line 1191, in on_touch_down
   return super(ScreenManager, self).on_touch_down(touch)
     File "/usr/lib64/python3.6/site-packages/kivy/uix/widget.py", line 549, in on_touch_down
   if child.dispatch('on_touch_down', touch):
     File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
     File "/usr/lib64/python3.6/site-packages/kivy/uix/relativelayout.py", line 288, in on_touch_down
   ret = super(RelativeLayout, self).on_touch_down(touch)
     File "/usr/lib64/python3.6/site-packages/kivy/uix/widget.py", line 549, in on_touch_down
   if child.dispatch('on_touch_down', touch):
     File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
     File "/usr/lib64/python3.6/site-packages/kivy/uix/behaviors/button.py", line 151, in on_touch_down
   self.dispatch('on_press')
     File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
    File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
    File "kivy/_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
    File "/usr/lib64/python3.6/site-packages/kivy/lang/builder.py", line 64, in custom_callback
    exec(__kvlang__.co_value, idmap)
    File "/home/cse/git/soft_161_homework/milestone_1/schooltracking.kv", line 525, in &lt;module&gt;
   app.adding_data_for_people()
    File "/home/cse/git/soft_161_homework/milestone_1/main.py", line 184, in adding_data_for_people
   session.commit()
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/session.py", line 1036, in commit
   self.transaction.commit()
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/session.py", line 503, in commit
   self._prepare_impl()
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/session.py", line 482, in _prepare_impl
   self.session.flush()
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/session.py", line 2479, in flush
   self._flush(objects)
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/session.py", line 2617, in _flush
   transaction.rollback(_capture_exception=True)
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
   compat.reraise(exc_type, exc_value, exc_tb)
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
   raise value
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/session.py", line 2577, in _flush
   flush_context.execute()
     File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
   rec.execute(self)
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/unitofwork.py", line 589, in execute
   uow,
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 245, in save_obj
   insert,
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 1137, in _emit_insert_statements
   statement, params
    File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 982, in execute
   return meth(self, multiparams, params)
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/sql/elements.py", line 293, in _execute_on_connection
   return connection._execute_clauseelement(self, multiparams, params)
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1101, in _execute_clauseelement
   distilled_params,
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1250, in _execute_context
   e, statement, parameters, cursor, context
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1476, in _handle_dbapi_exception
   util.raise_from_cause(sqlalchemy_exception, exc_info)
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
   reraise(type(exception), exception, tb=exc_tb, cause=cause)
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
   raise value.with_traceback(tb)
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context
   cursor, statement, parameters, context
   File "/usr/lib64/python3.6/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute
   cursor.execute(statement, parameters)
   File "/usr/lib/python3.6/site-packages/mysql/connector/cursor.py", line 515, in execute
   self._handle_result(self._connection.cmd_query(stmt))
   File "/usr/lib/python3.6/site-packages/mysql/connector/connection.py", line 488, in cmd_query
   result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
   File "/usr/lib/python3.6/site-packages/mysql/connector/connection.py", line 395, in _handle_result
   raise errors.get_exception(packet)
   sqlalchemy.exc.DatabaseError: (mysql.connector.errors.DatabaseError) 1364 (HY000): Field 'school_id' doesn't have a default value
  [SQL: INSERT INTO person (home_id, name, grade_level) VALUES (%(home_id)s, %(name)s, %(grade_level)s)]
   [parameters: {'home_id': 1, 'name': 'qwd', 'grade_level': 8}]
   (Background on this error at: http://sqlalche.me/e/4xp6)
  </code></pre>
  
  <p><strong>main.py</strong></p>
  
  <pre><code>from kivy.app import App
  from kivy.uix.label import Label
  from kivy.modules import inspector  # For inspection
  from kivy.core.window import Window  # For inspection
  from kivy.uix.button import Button
  from kivy.uix.screenmanager import ScreenManager, Screen
  from sys import stderr
  from sqlalchemy.exc import SQLAlchemyError
  from sqlalchemy.exc import ProgrammingError
  from schooltracking import SchoolTrackingDatabase, School, Home, Person
  from kivy.uix.floatlayout import FloatLayout
  from kivy.uix.popup import Popup
  from kivy.clock import Clock
  from kivy.properties import ObjectProperty
  from sqlalchemy.orm import sessionmaker
  class SchoolTrackingApp(App):
  
  def build(self):
      inspector.create_inspector(Window, self)
  
  
  def __init__(self, **kwargs):
      super(SchoolTrackingApp, self).__init__(**kwargs)
  
      url = SchoolTrackingDatabase.construct_mysql_url('localhost', 3306, 'schooltracking', 'root', 'cse')
      self.schooltracking = SchoolTrackingDatabase(url)
      self.session = self.schooltracking.create_session()
  
  
  
  
  def database_entries(self):
  
  
      query = self.session.query(School.names).all()
      query2 = self.session.query(School.district).all()
  
      text = self.root.ids.input_screen.text
      text2 = self.root.ids.input_screen2.text
  
      list_name = []
      for i in query:
          list_name.append(i[0])
  
  
      list_district = []
      for i in query2:
          list_district.append(i[0])
  
      for names in list_name:
          if text == names:
              for districts in list_district:
                  if text2 == districts:
                      popup = Popup(title='School and District already in database',
                      content=Label(text=' Sorry, but it looks like that name and \ndistrict are already in our datbase. \nPlease create a new one.'),
                      size_hint=(None, None), size=(400, 400))
                      popup.open()
  
                      break
  
  
  def blank_entries(self):
      text = self.root.ids.input_screen.text
      text2 = self.root.ids.input_screen2.text
      text3 = self.root.ids.input_screen3.text
      text4 = self.root.ids.input_screen4.text
      text5 = self.root.ids.input_screen5.text
      text6 = self.root.ids.input_screen6.text
      text7 = self.root.ids.input_screen7.text
      text8 = self.root.ids.input_screen8.text
      text9 = self.root.ids.input_screen9.text
      text10 = self.root.ids.input_screen10.text
      text11 = self.root.ids.input_screen.text
      text12 = self.root.ids.input_screen2.text
      text13 = self.root.ids.input_screen3.text
      text14 = self.root.ids.input_screen4.text
      text15 = self.root.ids.input_screen5.text
      text16 = self.root.ids.input_screen5.text
      text17 = self.root.ids.input_screen6.text
      text18 = self.root.ids.input_screen7.text
      text19 = self.root.ids.input_screen8.text
      text20 = self.root.ids.input_screen8.text
      text21 = self.root.ids.input_screen.text
      text22 = self.root.ids.input_screen2.text
      text23 = self.root.ids.input_screen3.text
      text24 = self.root.ids.input_screen4.text
      text25 = self.root.ids.input_screen4.text
  
      if text or text2 or text3 or text4 or text5 or text6 or text7 or text8 or text9 or text10 or text11 or text12 or text13 or text14 or text15 or text16 or text17 or text18 or text19 or text20 or text21 or text22 or text23 or text24 or text25== '':
          popup = Popup(title='No input given',
          content=Label(text=' The text boxes cannot be left blank!'),
          size_hint=(None, None), size=(400, 400))
          popup.open()
  
  
  def NA_entry(self):
      text9 = self.root.ids.input_screen9.text
      if text9 != 'N/A':
          popup = Popup(title='Not N/A',
          content=Label(text=' The text box has to be N/A!'),
          size_hint=(None, None), size=(400, 400))
          popup.open()
  
  
  def check_no_school_represents_child(self):
  
      query3 = self.session.query(Person.grade_level).all()
      query4 = self.session.query(Person.name).all()
      text10 = self.root.ids.input_screen10.text
      list_grade_levels = []
      for i in query3:
          list_grade_levels.append(i[0])
  
      list_names = []
      for i in query4:
          list_names.append(i[0])
  
      for names in list_names:
          for grade_level in list_grade_levels:
              if grade_level == None:
                  popup = Popup(title='No school representing child',
                  content=Label(text=' There is no school representing ' + names + ' in this home'),
                  size_hint=(None, None), size=(400, 400))
                  popup.open()
                  break
  
  
  def adding_data_for_school(self):
      url = SchoolTrackingDatabase.construct_mysql_url('localhost', 3306, 'schooltracking', 'root', 'cse')
      schooltracking = SchoolTrackingDatabase(url)
      schooltracking.ensure_tables_exist()
  
      session = schooltracking.create_session()
      add_data(session)
      session.commit()
  
      text = self.root.ids.input_screen.text
      text2 = self.root.ids.input_screen2.text
      text3 = self.root.ids.input_screen3.text
  
  
  
      schools = School(names=text, district=text2, education_level=text3)
      session.add(schools)
      session.commit()
  
  def adding_data_for_home(self):
      url = SchoolTrackingDatabase.construct_mysql_url('localhost', 3306, 'schooltracking', 'root', 'cse')
      schooltracking = SchoolTrackingDatabase(url)
      schooltracking.ensure_tables_exist()
  
      session = schooltracking.create_session()
      add_data(session)
      session.commit()
  
      text4 = self.root.ids.input_screen4.text
      text20 = self.root.ids.input_screen20.text
      text21 = self.root.ids.input_screen21.text
      text22 = self.root.ids.input_screen22.text
      text23 = self.root.ids.input_screen23.text
      text24 = self.root.ids.input_screen24.text
      address = Home(school_id=1,first_address=text4, second_address=text20, city=text21, state_or_province=text22, postal_code=68118, country=text24)
      session.add(address)
      session.commit()
  
  def adding_data_for_people(self):
      url = SchoolTrackingDatabase.construct_mysql_url('localhost', 3306, 'schooltracking', 'root', 'cse')
      schooltracking = SchoolTrackingDatabase(url)
      schooltracking.ensure_tables_exist()
      session = schooltracking.create_session()
      add_data(session)
      session.commit()
      text5 = self.root.ids.input_screen5.text
      text6 = self.root.ids.input_screen6.text
      text7 = self.root.ids.input_screen7.text
      text8 = self.root.ids.input_screen8.text
      text9 = self.root.ids.input_screen9.text
  
      person = Person(home_id=1, name=text5, grade_level=8)
      session.add(person)
      session.commit()
  
  
   def add_data(session):
       pass (This will add the data to the database do notneed to worry about this)
  
  
   def main():
      try:
      url = SchoolTrackingDatabase.construct_mysql_url('localhost', 3306, 'schooltracking', 'root', 'cse')
      schooltracking = SchoolTrackingDatabase(url)
      schooltracking.ensure_tables_exist()
      print('Tables created.')
      session = schooltracking.create_session()
      add_data(session)
      session.commit()
      print('Records created.')
      print('Your database has been successfully created!')
  except (SQLAlchemyError) as exception:
      print('Database setup failed', file=stderr)
      print(f'Cause: {exception}', file=stderr)
      #if ProgrammingError:
          #print('Your credentials are incorrect with those matching to the database.' )
  
      exit(1)
  
  
  
  if __name__ == '__main__':
     main()
     app = SchoolTrackingApp()
     app.run()
  </code></pre>
  
  <p><strong>Installer</strong></p>
  
  <pre><code>from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKfrom 
  sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import sessionmaker, relationship
  
  Persisted = declarative_base()
  
  
  class School(Persisted):
      __tablename__ = 'schools'
      school_id = Column(Integer, primary_key=True)
      names = Column(String(256), nullable=False)
      district = Column(String(256), nullable=False)
      education_level = Column(String(256), nullable=False)
      homes = relationship('Home', uselist=True, back_populates='school')
  
  
  class Home(Persisted):
      __tablename__ = 'homes'
      home_id = Column(Integer, primary_key=True)
      school_id = Column(Integer, ForeignKey('schools.school_id', ondelete='CASCADE'), nullable=False)
      first_address = Column(String(256), nullable=False)
      second_address = Column(String(256), nullable=True)
      city = Column(String(256), nullable=False)
      state_or_province = Column(String(256), nullable=False)
      postal_code = Column(String(256), nullable=False)
      country = Column(String(256), nullable=False)
      school = relationship('School', back_populates='homes')
      person = relationship('Person', back_populates='homes')
  
  
  class Person(Persisted):
      __tablename__ = 'person'
      person_id = Column(Integer, primary_key=True)
      home_id = Column(Integer, ForeignKey('homes.home_id', ondelete='CASCADE'), nullable=False)
      name = Column(String(256), nullable=False)
      grade_level = Column(Integer, nullable=False)
      homes = relationship('Home', back_populates='person')
  
  
  class SchoolTrackingDatabase(object):
      @staticmethod
      def construct_mysql_url(authority, port, database, username, password):
          return f'mysql+mysqlconnector://{username}:{password}@{authority}:{port}/{database}'
  
      @staticmethod
      def construct_in_memory_url():
          return 'sqlite:///'
  
      def __init__(self, url):
          self.engine = create_engine(url)  # an engine is like an endpoint, something to connect to
          self.Session = sessionmaker()  # create a class for connections to that endpoint / pylint: 
          disable=invalid-name
          self.Session.configure(bind=self.engine)  # associate the class with the endpoint
  
      def ensure_tables_exist(self):
          Persisted.metadata.create_all(self.engine)  # create tables for all subclasses of Persisted
  
      def create_session(self):
          return self.Session()  # create a new session, which is like a connection to the database
  </code></pre>
  
  <p>If the kivy file is needed please tell me :)</p>