I have a registration form and am trying to add student data to the database model(Student) but i get this error upon submiting the form data
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: student.email
[SQL: INSERT INTO student (username, email, image_file, password) VALUES (?, ?, ?, ?)]
[parameters: ('elijah', 'elijah#gmail.com', 'default.jpg', '$2b$12$lo4MLsE/hdI6SOnUr3lg5eg02u.u5xfRJYwKQzMn3bohXglif/73S')]
(Background on this error at: https://sqlalche.me/e/14/gkpj)
Am not sure of what's causing the error, have tried dropping and recreating my database modles again but the error persists.
This is my student model where the error is pointing to student.email
from datetime import datetime
from ..utils.db import db
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(255), nullable=True, default='default.jpg')
password = db.Column(db.String(120), nullable=False)
student_mark = db.relationship('Mark', backref='mark')
student_qn = db.relationship('StudentQuestion',backref='examinee')
def __repr__(self):
return f"Student('{self.username}', '{self.email}')"
def save(self):
db.session.add(self)
db.session.commit()
and this is the route that has the submission form which throws the error after i insert data into the form
from flask import render_template, url_for, flash, redirect, Blueprint
from .registerform import RegistrationForm
from flask_bcrypt import Bcrypt
from ..models.models import Student
from ..utils.db import db
bcrypt = Bcrypt()
register_route = Blueprint('register_route', __name__)
#register_route.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
student= Student(username=form.username.data, email=form.email.data, password=hashed_password)
db.session.add(student)
db.session.commit()
flash(f'Welcome {form.username.data} ,your can now login!')
return redirect(url_for('login_route.login'))
return render_template('register.html', title='RegisterPage', form=form)
What could be the problem and how can i avoid it!
Related
here are the files which contain my code:
this is models.py file
from . import db
from flask_login import UserMixin
from sqlalchemy import func
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
notes = db.relationship('Note')
class Note(db.Model):
time = func.now()
id = db.Column(db.Integer, primary_key=True)
data = db.Column(db.String(1000))
date = db.Column(db.DateTime(timezone=True), default=time)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
and this is views.py
from flask import Blueprint, render_template, request
from flask_login import login_required, current_user
from .models import Note
from . import db
views = Blueprint('views', __name__)
#views.route('/notes', methods=['GET', 'POST'])
#login_required
def notes():
if request.method == 'POST':
note = request.form.get('note')
new_note = Note(data=note, user_id=current_user.id)
db.session.add(new_note)
db.session.commit()
return render_template('notes.html', user=current_user)
I got the error
sqlalchemy.exc.ProgrammingError:
(mysql.connector.errors.ProgrammingError) 1054 (42S22): Unknown column
'user_id' in 'field list' [SQL: INSERT INTO note (id, data, date,
user_id) VALUES (%(id)s, %(data)s, now(), %(user_id)s)] [parameters:
{'id': 1, 'data': 'get a ', 'user_id': None}]
Any idea on where I messed
up and how to fix it ?
I just fixed a problem similar to this. My code was trying to insert one of the Column values into one of the Column names. Like the others have suggested, examine your code within the database. Here are some examples of my code before and after:
incorrect variable: self.all_output_data
self.user_tables = f"""
INSERT INTO voicechannel_{self.my_name_and_id}
(my_input, msg_from_input, self.all_output_data, my_output)
VALUES
('{self.my_input_widget}','{self.all_input_data[0]}',
'{self.all_output_data}','{self.output_to_other_nodes[0]}')
"""
correct variable: msg_to_output
self.user_tables = f"""
INSERT INTO voicechannel_{self.my_name_and_id}
(my_input, msg_from_input, msg_to_output, my_output)
VALUES
('{self.my_input_widget}','{self.all_input_data[0]}',
'{self.all_output_data}','{self.output_to_other_nodes[0]}')
"""
Change this line of code from
new_note = Note(data=note, id=current_user.id)
to
new_note = Note(data=note, user_id=current_user.id)
I've created a form which takes user's name and their email address. I get this data from the form and put it into a sqlite3 database in the following way:
#app.route('/my_form', methods=["GET", "POST"])
def form_data():
if request.method == "POST":
user_name = request.form["name"]
new_user = form_database(name=user_name)
user_email = request.form["email"]
new_user_email = form_database(email=user_email)
try:
db.session.add(new_user)
db.session.add(new_user_email)
db.session.commit()
return redirect("/my_form")
Current result: each data entry gets recorded into a new row:
1|Jack||||||||||
2||svisto#hotmail.com|||||||||
Desirable result: each data entry gets recorded into the same row:
1|Jack|svisto#hotmail.com|||||||||
Question: How can I change the code such that I get the desirable result?
Lets say you have a User class in your model like this:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer,
primary_key=True)
username = db.Column(db.String(32),
index=False,
unique=True,
nullable=False)
email = db.Column(db.String(64),
index=True,
unique=True,
nullable=False)
Then you can do this in your try block
try:
new_user = User(user_name=user_name,
email=email)
db.session.add(new_user)
db.session.commit()
Solution I found:
I fused:
new_user = form_database(name=user_name) and new_user_email = form_database(email=user_email)
together such that the code looks like this:
#app.route('/my_form', methods=["GET", "POST"])
def form_data():
if request.method == "POST":
user_name = request.form["name"]
user_email = request.form["email"]
new_user_details = form_database(name=user_name, email=user_email)#assigns 2 form inputs for both columns in the database model to the same variable
try:
db.session.add(new_user_details)#adds that variable to the database as one entry, hence in one row but different columns
db.session.commit()
I've got this message:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: user
[SQL: INSERT INTO user (username, email, password) VALUES (?, ?, ?)]
[parameters: ('test', 'test#test.com', 'password')]
(Background on this error at: http://sqlalche.me/e/e3q8)
when I tried: db.session.commit(). I'm following a tutorial and try to personalize the code but with bad results.
What I did so far is:
>>> from lagerut import db
>>> db.create_all()
>>> from models import User
>>> user_1 = User(username='test', email='test#test.com', password='password')
>>> db.session.add(user_1)
>>> db.session.commit()
Here the lagerut.py:
from datetime import datetime
from flask import Flask, render_template, url_for, flash, redirect
from flask_sqlalchemy import SQLAlchemy
from form import RegistrationForm, LoginForm
app = Flask(__name__)
app.config['SECRET_KEY'] = '2a1de6eea4126191912d6e702c6aa8f9'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///lagerut.db'
db = SQLAlchemy(app)
#app.route('/')
#app.route('/home')
def home():
return render_template ('home.html')
#app.route('/how-it-works')
def howitworks():
return render_template ('how-it-works.html', title='How it works')
#app.route('/lager-out')
def lagerout():
return render_template ('lager-out.html', title='Lager out')
#app.route('/lager-in')
def lagerin():
return render_template ('lager-in.html', title='Lager in')
#app.route("/register", methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
flash(f'Account created for {form.username.data}!', 'success')
return redirect(url_for('home'))
return render_template('register.html', title='Register', form=form)
#app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.email.data == 'admin#blog.com' and form.password.data == 'password':
flash('You have been logged in!', 'success')
return redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check username and password', 'danger')
return render_template('login.html', title='Login', form=form)
if __name__ == '__main__':
app.run(debug=True)
And here the models.py:
from datetime import datetime
from lagerut import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
def __repr__(self):
return f"User('{self.username}', '{self.email}')"
class Items(db.Model):
item_number = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(200), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
department = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
def __repr__(self):
return f"Items('{self.product}', '{self.date_posted}', '{self.content}', '{self.department}', '{self.content}')"
Should I try to write the code again? I'm just trying to learn how build a little app to my work.
Is a good way to learn programming works also with the shell?
That's because you are not creating the app context while creating the database since you are doing this via python shell you need to add the following line
with app.app_context():
Read more about this here https://flask.palletsprojects.com/en/1.0.x/appcontext/
I have started work on a project and have decided before I get too deep to get my ORM sorted out (this means going back over and re writing my classes). I believe my code is correct but I am getting a 'TypeError' whenever I try to create the database schema using Python. I load up the Python console whilst in my project directory, and type 'from app import db' which works fine. After the command 'db.create_all()' (which worked using a basic example) I am thrown the error:
'File
"C:\Users\owner\AppData\Local\Programs\Python\Python38-32\lib\site-packages\sqlalchemy\dialects\mysql\base.py",
line 2016, in visit_VARCHAR
return self._extend_string(type_, {}, "VARCHAR(%d)" % type_.length) TypeError: %d format: a number is required, not type'
I am given no clue as to where in my actual code the cause could be, and am at a total loss.
Any help would be great - a lot of code is commented out and some other code left in for now as I'm in the process of adding my ORM but it was implemented without SQLAlchemy initially. Below is my code for 'init.py':
from flask import Flask, render_template, url_for, flash, redirect, g, request, session, send_from_directory, send_file
from heychef.config import Config
from flask_sqlalchemy import SQLAlchemy
import os
import bcrypt
import uuid
import json
import ssl
from datetime import datetime
from datetime import timedelta
from heychef.models.Agency import Agency
from heychef.models.User import User
from heychef.models.Shift import Shift
from flaskext.mysql import MySQL
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
from heychef.models.Agent import Agent
#app.before_request
def before_request():
g.agent = None
g.agency = None
if 'agent' in session:
g.agent = session['agent']
if 'agency' in session:
g.agency = session['agency']
##########################################################
############# Agent Routes ################
##########################################################
#app.route("/")
def home():
return render_template('agent-views/signup.html'), 200
#app.route("/agent-signup", methods = ['POST', 'GET'])
def agentSignup():
if request.method == 'POST':
email = request.form['inputEmail']
firstName = request.form['inputFirstName']
secondName = request.form['inputSecondName']
password = request.form['inputPassword']
rPassword = request.form['inputConfirmPassword']
if(password != rPassword):
flash('Passwords do not match.', 'danger')
return render_template('agent-views/signup.html')
else:
hashedPwd = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
agent = Agent(firstName, secondName, email, hashedPwd)
agent.addAgent(self)
flash('Account created, you can log in now.', 'success')
return render_template('agent-views/signup.html')
#app.route("/agent-login", methods = ['POST','GET'])
def agentLogin():
if request.method == 'POST':
session.pop('agent', None)
email = request.form['inputEmail']
pwd = request.form['inputPassword']
connection = mysql.get_db()
cursor = connection.cursor()
result, msg = Agent.agentLogin(connection, cursor, email, pwd)
if(result):
session['agent'] = email
flash(msg, 'success')
return redirect(url_for('agentDashboard'))
else:
flash(msg, 'danger')
return render_template('agent-views/login.html')
else:
return render_template('agent-views/login.html')
#app.route("/agent-dashboard", methods = ['GET'])
def agentDashboard():
if g.agent:
return render_template('agent-views/dashboard.html'), 200
else:
msg = "Please log in"
flash(msg, 'warning')
return redirect(url_for('agentLogin'))
if __name__ == "__main__":
app.run()
and here is my Agent Class:
from heychef.models.User import User
#from heychef.models.data.AgentDb import AgentDb
from heychef import db
class Agent(db.Model):
agentId = db.Column(db.Integer, unique=True, nullable=False, primary_key=True)
firstName = db.Column(db.String(80), unique=False, nullable=False, primary_key=False)
secondName = db.Column(db.String(80), unique=False, nullable=False, primary_key=False)
email = db.Column(db.String(80), unique=False, nullable=False, primary_key=False)
level = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
agencyId = db.Column(db.Integer, unique=False, nullable=True, primary_key=False)
addressLine1 = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
addressLine2 = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
addressLine3 = db.Column(db.String(80), unique=False, nullable=True, primary_key=False)
postcode = db.Column(db.String(20), unique=False, nullable=True, primary_key=False)
passwordHash = db.Column(db.String(256), unique=False, nullable=False, primary_key=False)
def __repr__(self):
return "<Agent(firstName='%s', lastName='%s')>" % (self.firstName, self.lastName)
def __init__(self, firstName, secondName, email, hashedPwd):
self.agentId = 1001
self.firstName = firstName
self.secondName = secondName
self.email = email
self.passwordHash = hashedPwd
#staticmethod
def agentEmailExists(cursor, email):
exists = AgentDb.agentEmailExistsDb(cursor, email)
return exists
#staticmethod
def addAgent(agent):
db.session.add(self)
db.session.commit()
#staticmethod
def agentLogin(connection, cursor, email, pwd):
failMsg = 'Email or Password does not match.'
successMsg = 'Successfully logged in.'
result = AgentDb.agentLoginDb(connection, cursor, email, pwd)
if(result):
msg = successMsg
else:
msg = failMsg
return result, msg
#staticmethod
def getWork(cursor):
work = AgentDb.getWorkDb(cursor)
return work
any help would be ace as I'm really struggling!
Many thanks
The error seems to be related to a VARCHAR (String)db column and points out that it has received a Non-Integer value ,so there might be a db.string() model field with a Non-Integer or empty parenthesis in the other model Classes in your project.
I have the following code. I'm trying to insert user data into a sqlite database using SQLAlchemy it crashes when I give the following command in the python prompt. I'm trying to add the users to the database then once I commit I want to query the database and display the information to verify it got inserted into the database. For now I have it only displaying to the prompt I haven't developed any methods to render it.
from DIRT import db
db.create_all()
from DIRT import User, Post
user_1 = User(username="John Wick", email="jw#gmail.com", password="password")
user_2 = User(username="John Snow", email="js#gmail.com", password="password")
db.session.add(user_1)
db.session.add(user_2)
db.session.commit()
Below is my code for the DIRT.py
from datetime import datetime
from flask import Flask, render_template, url_for, flash, redirect
from flask_sqlalchemy import SQLAlchemy
from MyForms import RegisterForm, LoginForm
app = Flask(__name__)
# creating secret numbers to prevent modified cookie attack, or cross-site attacks
app.config['SECRET_KEY'] = '4b15463cce52d7b99874c9fb2312d580'
# database uri
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///dirt.db'
# database
db = SQLAlchemy(app)
# user model for the sql database
# class User(db.Model):
# id = db.Column(db.Integer, primary_key=True)
# username = db.Column(db.String(25), unique=True, nullable=False)
# email = db.Column(db.String(50), unique=True, nullable=False)
# image_file = db.Column(db.String(25), nullable=False, default='default.jpg')
# password = db.Column(db.String(50), nullable=False)
# posts = db.relationship('Post', backref='author', lazy=True)
# def __repf__(self):
# return f"User('{self.username}', '{self.email}', '{self.image_file}')"
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
def __repr__(self):
return f"User('{self.username}', '{self.email}')"
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Post('{self.title}', '{self.date_posted}')"
posts = [
{
'author': 'Cloud Strife',
'title': 'Where do we find Aeris..',
'content': 'So we are trying to find her',
'date_posted': 'November 12, 2019'
},
{
'author': 'Cecil Paladin',
'title': 'Where is the crystal sword',
'content': 'Trying to find the crystal bridge',
'date_posted': 'July 10, 2019'
}
]
#app.route("/")
#app.route("/home")
def home():
return render_template('home.html', posts=posts)
#app.route("/about")
def about():
return render_template('about.html', title='About')
#app.route("/register", methods=['GET', 'POST'])
def register():
form = RegisterForm()
if form.validate_on_submit():
flash(f'Account created for {form.username.data} successfully!', 'success')
return redirect(url_for('home'))
return render_template('register.html', title='Register', form=form)
# #app.route("/login", methods=['GET', 'POST'])
# def login():
# MyForm = LoginForm()
# return render_template('login.html', title='Login', form=MyForm)
#app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.email.data == 'onyxbird#hotmail.com' and form.password.data == 'sandman23':
flash(f'{form.email.data} has logged in!', 'success')
return redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check email and password', 'danger')
return render_template('login.html', title='Login', form=form)
if __name__ == '__main__':
# app.run(host='0.0.0.0', port='8080')
# above is production mode
app.run(debug=True)
This is the errors I'm getting:
*db.session.commit()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Users\onyxb\PycharmProjects\DIRT\venv\lib\site-packages\sqlalchemy\orm\scoping.py", line 162, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "C:\Users\onyxb\PycharmProjects\DIRT\venv\lib\site-packages\sqlalchemy\orm\session.py", line 1027, in commit
self.transaction.commit()
File "C:\Users\onyxb\PycharmProjects\DIRT\venv\lib\site-packages\sqlalchemy\orm\session.py", line 492, in commit
self._assert_active(prepared_ok=True)
File "C:\Users\onyxb\PycharmProjects\DIRT\venv\lib\site-packages\sqlalchemy\orm\session.py", line 288, in _assert_active
raise sa_exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: (sqlite3.IntegrityError) NOT NULL constraint failed: user.image_file
[SQL: INSERT INTO user (username, email, password) VALUES (?, ?, ?)]
[parameters: ('John Wick', 'jw#gmail.com', 'password')]
(Background on this error at: http://sqlalche.me/e/gkpj) (Background on this error at: http://sqlalche.me/e/7s2a)*