Why i am getting UnboundLocalError in Flask? - python

this is my app.py code but i am receiving unbound local error after adding another path for delete and creating the function delete.
from crypt import methods
from email.policy import default
from flask import Flask, render_template, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Todo(db.Model):
sno = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
desc = db.Column(db.String(200), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self) -> str:
return f"{self.sno} - {self.title}"
#app.route('/', methods=['GET', 'POST'])
def hello_world():
if request.method == 'POST':
title = request.form["title"]
desc = request.form["desc"]
todo = Todo(title=title, desc=desc)
db.session.add(todo)
db.session.commit()
mytodo = Todo.query.all()
return render_template('index.html', mytodo=mytodo)
#app.route('/delete/<int:sno>')
def delete(sno):
todo = Todo.query.filter_by(sno==sno).first()
db.session.delete(todo)
db.session.commit()
return redirect('/')
if __name__ == "__main__":
app.run(debug=True, port=8000)
Below i've added the screenshot of the errors i am getting even when i just visit the root url.

Problem
If the server receive a GET /, then you won't define te title variable, but would try to use it at Todo(title=title, desc=desc) so an error
Fix
All the creation code should be in the if POST branch
#app.route('/', methods=['GET', 'POST'])
def hello_world():
if request.method == 'POST':
title = request.form["title"]
desc = request.form["desc"]
todo = Todo(title=title, desc=desc)
db.session.add(todo)
db.session.commit()
mytodo = Todo.query.all()
return render_template('index.html', mytodo=mytodo)

Related

AttributeError: 'scoped_session' object has no attribute 'get'

I am trying to delete data from my database but my web application returns this error:
File "C:\Users\q\Pyc\Flask\basic_of_flask\SQL Database with flask\Database in view\adoption_sit.py", line 78, in del_pup
pup = db.session.get(id)
AttributeError: 'scoped_session' object has no attribute 'get'
have a look at my code below
import os
from flask import Flask, redirect, render_template, url_for
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from form import AddForm, DelForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
#######################################
#### SQL DATABASE SECTION #############
#######################################
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Migrate(app, db)
########################################
######## Models ########################
########################################
class Puppy(db.Model):
__tablename__ = 'puppies'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text)
def __init__(self, name):
self.name = name
def __repr__(self):
return f"Puppy name is {self.name}."
#############################################
##### VIEW FUNCTIONS -- HAVE FORM ###########
#############################################
#app.route('/')
def index():
return render_template('home.html')
#app.route('/add', methods=['GET', 'POST'])
def add_pup():
form = AddForm()
if form.validate_on_submit():
name = form.name.data
new_puppy = Puppy(name)
db.session.add(new_puppy)
db.session.commit()
return redirect(url_for('list_pup'))
return render_template('add.html', form=form)
#app.route('/list_pup')
def list_pup():
puppies = Puppy.query.all()
return render_template('list.html', puppies=puppies)
#app.route('/delete', methods=['GET', 'POST'])
def del_pup():
form = DelForm()
if form.validate_on_submit():
id = form.id.data
pup = db.session.get(id)
db.session.delete(pup)
db.session.commit()
return redirect(url_for('list_pup'))
return render_template('delete.html', form=form)
db.create_all()
if __name__ == '__main__':
app.run(debug=True)
and here is my form.py file
# form.py
from flask_wtf import FlaskForm
from wtforms import SubmitField, StringField, IntegerField
class AddForm(FlaskForm):
name = StringField('Name of puppy:')
submit = SubmitField('Submit puppy')
class DelForm(FlaskForm):
id = IntegerField("Id number of puppy to be remove:")
submit = SubmitField("Remove puppy")
i guess you are doing things the wrong way in del_pup() function
[..]
pup = db.session.get(id) # here
you need to get the Puppy object with the given id like:
#app.route('/delete', methods=['GET', 'POST'])
def del_pup():
form = DelForm()
if form.validate_on_submit():
id = form.id.data
# pup = db.session.get(id) # wrong way
pup = Puppy.query.filter_by(id=id).first()` # here
db.session.delete(pup)
db.session.commit()
return redirect(url_for('list_pup'))
return render_template('delete.html', form=form)

App.route doesn't work in Flask for one method

Here's my code:
from flask import Flask, render_template, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
app._static_folder = 'static/'
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:test#localhost/Scheduling'
db = SQLAlchemy(app)
class CPR_INFO(db.Model):
DEAL_ID = db.Column(db.String(50), primary_key=True)
POG_NUM = db.Column(db.String(50))
OPOG_START_DT = db.Column(db.Date())
OPOG_END_DT = db.Column(db.Date())
def __repr__(self):
return 'Deal_ID ' + str(self.DEAL_ID)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/posts', methods=['GET', 'POST'])
def posts():
if request.method == 'POST':
post_id = request.form['DEAL_ID']
post_title = request.form['POG_NUM']
post_content = request.form['OPOG_START_DT']
new_post = CPR_INFO(DEAL_ID = post_id, POG_NUM=post_title, OPOG_START_DT=post_content)
db.session.add(new_post)
db.session.commit()
return redirect('/posts')
else:
all_posts = CPR_INFO.query.all()
return render_template('posts-2.html', posts=all_posts)
#app.route('/posts/new', methods = ['GET', 'POST'])
def new_post():
if request.method == 'POST':
post_id = request.form['DEAL_ID']
post_title = request.form['POG_NUM']
post_content = request.form['OPOG_START_DT']
new_post = CPR_INFO(DEAL_ID=post_id, POG_NUM=post_title, OPOG_START_DT=post_content)
db.session.add(new_post)
db.session.commit()
return render_template('posts-2.html', posts=all_posts)
else:
return render_template('new_post_2.html')
#app.route('/posts/delete/<string:DEAL_ID>')
def delete(DEAL_ID):
post = CPR_INFO.query.get_or_404(DEAL_ID)
db.session.delete(post)
db.session.commit()
return redirect('/posts')
#app.route('/posts/edit/<string:DEAL_ID>', methods = ['GET', 'POST'])
def edit(DEAL_ID):
post = CPR_INFO.query.get_or_404(DEAL_ID)
if request.method == 'POST':
post.DEAL_ID = request.form['DEAL_ID']
post.POG_NUM = request.form['POG_NUM']
post.OPOG_START_DT = request.form['OPOG_START_DT']
db.session.commit()
return redirect('/posts')
else:
return render_template('edit-2.html', post = post)
if __name__ == "__main__":
app.run(debug=True)
This part of my code fails. The URL is not rendered because the DEAL_ID is not read:
#app.route('/posts/delete/<string:DEAL_ID>')
def delete(DEAL_ID):
post = CPR_INFO.query.get_or_404(DEAL_ID)
db.session.delete(post)
db.session.commit()
return redirect('/posts')
I get the following error message on my HTML page:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Add methods parameter at your #app.route('/posts/delete/<string:DEAL_ID>')

SQLAlchemy and flask (sqlalchemy.exc.OperationalError:)

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/

ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'FileStorage'

I just want to write a filename from data to my model.
How to get filename from filestorage?
I'm using Flask for my web app. I create form that include FileField.
It is important for me to get the same filename.
Form:
class TableForm(FlaskForm):
file = FileField('Add file', validators=[FileAllowed(['xlsx', 'xls', 'csv'])])
submit = SubmitField('Add file')
Model:
class Table(db.Model):
__table_args__= {'schema': 'app'}
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(240), nullable=False)
table_file = db.Column(db.String(80), nullable=False)
Routes:
#app.route("/projects/<int:project_id>", methods=['GET', 'POST'])
#login_required
def project_data_source(project_id):
tables = Table.query.filter_by(project_id=project_id)
if project.author != current_user:
abort(403)
form = TableForm()
if form.validate_on_submit():
table = Table(name=form.file.data, table_file=form.file.data)
db.session.add(table)
db.session.commit()
return redirect(url_for('project_data_source'))
There's a pretty good example on their docs. Here's how you get the file name:
from werkzeug.utils import secure_filename
f = form.file.data
filename = secure_filename(f.filename)
So your code would need to be:
from werkzeug.utils import secure_filename
#app.route("/projects/<int:project_id>", methods=['GET', 'POST'])
#login_required
def project_data_source(project_id):
tables = Table.query.filter_by(project_id=project_id)
if project.author != current_user:
abort(403)
form = TableForm()
if form.validate_on_submit():
filename = secure_filename(form.file.data.filename)
table = Table(name=filename, table_file=filename) # not sure why you save it twice here
db.session.add(table)
db.session.commit()
return redirect(url_for('project_data_source'))

flask using POST, PUT, DELETE

I keep getting an error on the url when I try to implement POST in my API. I keep getting the error in the URL saying METHOD not Allowed for this URL. Am I missing something? Does POST not work directly when u try to open the server?? I'm soooo lost.
from flask import Flask, jsonify,json, request, abort
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_pyfile('Config.py')
db = SQLAlchemy(app)
db.create_all()
class JsonModel(object):
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class User(db.Model, JsonModel):
User_ID = db.Column(db.Integer, primary_key = True)
FirstName = db.Column(db.String(20))
LastName = db.Column(db.String(20))
def __init__(self,FirstName, LastName):
self.FirstName = FirstName
self.LastName = LastName
class Todo(db.Model, JsonModel):
todo_ID = db.Column(db.Integer, primary_key = True)
UserID = db.Column(db.Integer, db.ForeignKey('User_ID'))
details = db.Column(db.String(30))
def __init__(self,details):
self.details = details
#app.route('/', methods = ['GET'])
def index():
return json.dumps([u.as_dict() for u in User.query.all()+Todo.query.all()])
#app.route('/todo/<int:UserID>', methods = ['GET'])
def get(UserID):
return (list[Todo.query.get(UserID)])
#app.route('/p/', methods = ['POST'])
def create_dev():
if not request.json or not 'name' in request.json:
abort(400)
dev = Todo(request.json.details,request.json.get('details',''))
db.session.add(dev)
db.session.commit()
return json.dumps([{'dev': dev}]), 201
if __name__ == '__main__':
app.run()
You should add GET method to list of allowed methods. When You try to load page, You first need to get page itself using GET method. Then, after filling something on the page, You use POST method to pass some data to the app. In the app, You should check with which method function is called. Something like this:
#app.route('/p', methods=['GET', 'POST'])
def create_dev():
if request.method == 'GET':
return render_template('p_page.html')
# If You get to this line, it means it is POST method
do_something_here()

Categories

Resources