WTForm not submitting to mysql - flush error - python

I'm completely stuck with the following error when submitting form data form into a mysql database, very grateful for any clues
I get this error:
"sqlalchemy.orm.exc.FlushError FlushError: Instance has a NULL identity key. If this is an auto-generated
value, check that the database table allows generation of new primary
key values, and that the mapped Column object is configured to expect
these generated values. Ensure also that this flush() is not
occurring at an inappropriate time, such aswithin a load() event."
the code is:
from flask import Flask, request,redirect,render_template,flash
from wtforms import Form, TextField, BooleanField
from wtforms.validators import Required
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:#127.0.0.1/Jungle'
class Sighting(db.Model):
__tablename__ = 'Animals'
animal_name = db.Column(db.String, primary_key = True)
animal_type = db.Column(db.String)
scary = db.Column(db.String)
class LoginForm(Form):
animal_name = TextField('Animal')
animal_type = TextField('Type')
scary = BooleanField('Scary')
#app.route('/login',methods = ['GET','POST'])
def login():
form = LoginForm()
if request.method == 'POST':
newanimal = Sighting(animal_name=form.animal_name.data,animal_type=form.animal_type.data,scary=form.scary.data)
db.session.add(newanimal)
db.session.commit()
return redirect('/thanks')
elif request.method == 'GET':
return render_template('login.html', form = form)
#app.route('/thanks',methods= ['GET'])
def thanks():
return render_template('thanks.html')
if __name__ == '__main__':
app.run(debug=True)
If I run something like this in the above code it works and successfully commits into the database:
#app.route('/submit',methods =['GET'])
def submit():
newanimal = Sighting(animal_name='frog',animal_type='amphibian', scary='No')
db.session.add(newanimal)
db.session.commit()
return render_template('thanks.html')
So it seems to be something to do with the form data. The MySQL table is:
CREATE TABLE `Animals` (
`animal_name` varchar(100) DEFAULT NULL,
`animal_type` varchar(100) DEFAULT NULL,
`scary` varchar(100) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8
The database table seems to auto-increment even when one of the failed submissions happens - when you put in a row manually that works its id is a few higher than than the previous one. There's also one row in the table with every field a null.
many thanks in advance!!
(forgive the odd naming schema - its adapted from a tutorial)
sqlalchemy.orm.exc.FlushError
FlushError: Instance <Sighting at 0x10c6552d0> has a NULL identity key. If this is an auto-generated value, check that the database table allows generation of new primary key values, and that the mapped Column object is configured to expect these generated values. Ensure also that this flush() is not occurring at an inappropriate time, such aswithin a load() event.
Traceback (most recent call last)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/tomhalloran/TomDev/FlaskSkint/learnv3.py", line 29, in login
db.session.commit()
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/scoping.py", line 149, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 765, in commit
self.transaction.commit()
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 370, in commit
self._prepare_impl()
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 350, in _prepare_impl
self.session.flush()
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 1879, in flush
self._flush(objects)
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 1997, in _flush
transaction.rollback(_capture_exception=True)
File "/Library/Python/2.7/site-packages/sqlalchemy/util/langhelpers.py", line 57, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 1967, in _flush
flush_context.finalize_flush_changes()
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 387, in finalize_flush_changes
self.session._register_newly_persistent(other)
File "/Library/Python/2.7/site-packages/sqlalchemy/orm/session.py", line 1389, in _register_newly_persistent
% state_str(state)
FlushError: Instance <Sighting at 0x10c6552d0> has a NULL identity key. If this is an auto-generated value, check that the database table allows generation of new primary key values, and that the mapped Column object is configured to expect these generated values. Ensure also that this flush() is not occurring at an inappropriate time, such aswithin a load() event.
The debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.
To switch between the interactive traceback and the plaintext one, you can click on the "Traceback" headline. From the text traceback you can also create a paste of it. For code execution mouse-over the frame you want to debug and click on the console icon on the right side.
You can execute arbitrary Python code in the stack frames and there are some extra helpers available for introspection:
dump() shows all variables in the frame
dump(obj) dumps all that's known about the object

You created the form, but unless I misread your code, you missed the step that actually populates the form with data from the POST (i.e. from request.form).

Related

Identifying Location of Error: TypeError: 'NoneType' object is not subscriptable (Python)

I am relatively new to Python, and I am attempting to follow a tutorial on how to build a web application. All my code checks out, however, when I attempt to access the app via localhost, I get the following error: "TypeError: 'NoneType' object is not subscriptable." I'm not sure what the error is referring to in my code, and I would appreciate any pointers as to how to identify and resolve this error.
Code:
Service.py
from models import ToDoModel
class ToDoService:
def __init__(self):
self.model = ToDoModel()
def create(self, params):
self.model.create(params["Title"], params["Description"])
models.py
import _sqlite3
class Schema:
def __init__(self):
self.conn = _sqlite3.connect('todo.db')
self.create_user_table()
self.create_to_do_table()
# Why are we calling user table before to_do table?
# What happens if we swap them?
def create_to_do_table(self):
query = """
CREATE TABLE IF NOT EXISTS "Todo" (
id INTEGER PRIMARY KEY,
Title TEXT,
Description TEXT,
_is_done boolean,
_is_deleted boolean,
CreatedOn Date DEFAULT CURRENT_DATE,
DueDate Date,
UserId INTEGER FOREIGNKEY REFERENCES User(_id)
);
"""
self.conn.execute(query)
def create_user_table(self):
query = """
CREATE TABLE IF NOT EXISTS "User" (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT,
CreatedOn Date default CURRENT_DATE
);
"""
self.conn.execute(query)
class ToDoModel:
TABLENAME = "TODO"
def __init__(self):
self.conn = _sqlite3.connect('todo.db')
def create(self, Title, description):
query = f'insert into {self.TABLENAME} ' \
f'(Title, Description) ' \
f'values ("{Title}","{description}")'
result = self.conn.execute(query)
return result
app.py
from flask import Flask, request, jsonify
from Service import ToDoService
from models import Schema
app = Flask(__name__)
#app.route("/todo", methods=["GET", "POST"])
def create_todo():
return jsonify(ToDoService().create(request.get_json()))
if __name__ == "__main__":
Schema()
app.run(debug=True)
Error:
Traceback (most recent call last):
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/micahwilcox/PycharmProjects/todo-flask/venv/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/micahwilcox/PycharmProjects/todo-flask/app.py", line 10, in create_todo
return jsonify(ToDoService().create(request.get_json()))
File "/Users/micahwilcox/PycharmProjects/todo-flask/Service.py", line 10, in create
ToDoModel().create(params["Title"], params["Description"])
TypeError: 'NoneType' object is not subscriptable
I am interfacing with the program using Python Shell with the following code:
requests.post("http://localhost:5000/todo",
json={"Title":"my first todo",
"Description":"my first todo"})
requests.get("http://localhost:5000/todo",
json={"Title":"my first todo",
"Description":"my first todo"})
The error comes when I attempt to go to localhost:5000/todo on my browser.
Thanks in advance for any help I receive.
Based on your comment:
The error comes when I attempt to go to localhost:5000/todo on my browser
The error happens when your browser calls the endpoint with a GET request with no body. Then request.get_json() method will return None, and thus params is None and you're trying to do None["Title"] which is obviously an error.

Returning All Query Results to Alexa Skill

I am developing a Web Service using python that would operate as the backend logic for a custom Alexa Skill. I am using the flask, flask-ask(Alexa Skill Kit), and MySQL extensions to develop this Web Service.
This Alexa Skill would allow users to reserve parking spots, check if lots are full, and find parking spots.
I also have a local database where all parking related information is stored.
I'm having an issue where I am only able to return the first result of a query.
Here is the code for one of my intents:
'''This is a Web Service for the *** Parking skill'''
author__ = '*****'
import logging
from flaskext.mysql import MySQL
from flask import Flask, render_template
from flask_ask import Ask, statement, question
mysql = MySQL()
app = Flask(__name__)
app.config.from_object(__name__)
app.config['MYSQL_DATABASE_USER'] = '*****'
app.config['MYSQL_DATABASE_PASSWORD'] = '*****'
app.config['MYSQL_DATABASE_DB'] = '*****'
app.config['MYSQL_DATABASE_HOST'] = '*****'
mysql.init_app(app)
ask = Ask(app, "/")
logging.getLogger("flask_ask").setLevel(logging.DEBUG)
#ask.intent('AvailableParking')
def available(occupancy):
#converts the inputted occupancy variable into all caps, to match the DB schema
occupancy = occupancy.upper()
#creates cursor variable that connects to DB
cursor = mysql.connect().cursor()
#connects to db and executes SQL query that displays all garages where the OCCUPANCY field matches the users slot input (OPEN OR CLOSED)
cursor.execute("SELECT GARAGE_NAME FROM GARAGES WHERE OCCUPANCY = %s", (occupancy,))
#returns the first row of the query results
data = cursor.fetchone()
data = data[0]
return statement(data)
This works as intended. Alexa says "Lot A" when triggering the intent, even thought there are 3 parking lots in total.
I thought to use the MySQL method cursor.fetchall() in place of cursor.fetchone, like so:
data = cursor.fetchall()
return statement(data)
But I receive the error:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python2.7/dist-packages/flask_ask/core.py", line 767, in _flask_view_func
result = self._map_intent_to_view_func(self.request.intent)()
File "/home/ngrok/ngrok/FETCHALLRETURN", line 46, in available
return statement(data)
File "/usr/local/lib/python2.7/dist-packages/flask_ask/models.py", line 188, in __init__
super(statement, self).__init__(speech)
File "/usr/local/lib/python2.7/dist-packages/flask_ask/models.py", line 51, in __init__
'outputSpeech': _output_speech(speech)
File "/usr/local/lib/python2.7/dist-packages/flask_ask/models.py", line 402, in _output_speech
xmldoc = ElementTree.fromstring(speech)
File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1311, in XML
parser.feed(text)
File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1651, in feed
self._parser.Parse(data, 0)
TypeError: Parse() argument 1 must be string or read-only buffer, not tuple
{"context": {"System": {"apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLmY2NDViYTgxLTZmM2QtNDZlNi04MDM1LTI1MTBlYTg5ODNkYiIsImV4cCI6MTUzMTE1MzIxMiwiaWF0IjoxNTMxMTQ5NjEyLCJuYmYiOjE1MzExNDk2MTIsInByaXZhdGVDbGFpbXMiOnsiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUhFRzdPQ0RLN01TNkdFWkhYTUlTUlFXRkNNTktKVUxHTk1GTkdSVFlWSFk0WFZMSkVWUzRZTFFGSjVFSDVRR0YyREVYQTVVVjI0UzJHNFJNU0tYWFpHVjZFRDY0RktJWkpHVVQyWURVRlZZTzVLVUZLSENDUzVPWUdPTDI3NUU1QjRGRU1XTk5VRVAzUkxPSENFNzRUVTdLSDZBIiwidXNlcklkIjoiYW16bjEuYXNrLmFjY291bnQuQUg0T1FZSVBSQ1NRVEZaR1pIWkVRSFpCU1RISDI1VUE2MjYyNFY1WTdDWTdCSzZDWU9RWjdJN1BMV0s0Tzc0RFpVSzRBMkw0MlpQUjRQV1lFRlJIVzY2MlRPVlVEM1BCT1c0UkxRSjNFSFpVWllTTzM2VkM0NkMzRVdHT1ZPRFlVSVNWNzNPRVRHUkJEUkFTRjc0NEg3VFcyR0pYM01FN0kyWVNGQkFTNjNOUUFGNzNCVUJHUlRSSU5ZQ0tIM0dPWjZZVjNVS0tRM0xZMlFJIn19.WPKBopJc_WAxHJdHsYg6bgqYhEahsIzwCsBm3EUPWdKmqzSmjPTudJH-58a0VndsGc32CxARDhmShy1RxsSGUwacXr-Hb1sMlkHcrKV-I6dUFA9JXgGOHP92WyDBe4NcmZd2evEHGSAlWr7mW3cPpjUKax7INsSWqbziNGneP5DWV7T6FA6S3G-h5BBiX5rVx2SBcfYZ-1ixCom5GvQa8Xe77CGg2zwugd9oIvib6Q9JLfYQrmWcg9qBYfnKfaQsQNYg6I_OJ5fL5YcCmfq5FtfPpPL-k3UWvSiZwFqwch-AUNzu35csmLw9BF3JbVXPxPr-o70OlVWxmOeVEnYAzA", "apiEndpoint": "https://api.amazonalexa.com", "application": {"applicationId": "amzn1.ask.skill.f645ba81-6f3d-46e6-8035-2510ea8983db"}, "device": {"deviceId": "amzn1.ask.device.AHEG7OCDK7MS6GEZHXMISRQWFCMNKJULGNMFNGRTYVHY4XVLJEVS4YLQFJ5EH5QGF2DEXA5UV24S2G4RMSKXXZGV6ED64FKIZJGUT2YDUFVYO5KUFKHCCS5OYGOL275E5B4FEMWNNUEP3RLOHCE74TU7KH6A", "supportedInterfaces": {}}, "user": {"userId": "amzn1.ask.account.AH4OQYIPRCSQTFZGZHZEQHZBSTHH25UA62624V5Y7CY7BK6CYOQZ7I7PLWK4O74DZUK4A2L42ZPR4PWYEFRHW662TOVUD3PBOW4RLQJ3EHZUZYSO36VC46C3EWGOVODYUISV73OETGRBDRASF744H7TW2GJX3ME7I2YSFBAS63NQAF73BUBGRTRINYCKH3GOZ6YV3UKKQ3LY2QI"}}}, "request": {"error": {"message": "An exception occurred while dispatching the request to the skill.", "type": "INVALID_RESPONSE"}, "locale": "en-US", "reason": "ERROR", "requestId": "amzn1.echo-api.request.a7699e3a-71b3-4cf5-8d23-63e45c86a957", "timestamp": "2018-07-09T15:20:12Z", "type": "SessionEndedRequest"}, "session": {"application": {"applicationId": "amzn1.ask.skill.f645ba81-6f3d-46e6-8035-2510ea8983db"}, "new": false, "sessionId": "amzn1.echo-api.session.7c96f3f4-c78f-4c10-9535-9e1e9fe8a21e", "user": {"userId": "amzn1.ask.account.AH4OQYIPRCSQTFZGZHZEQHZBSTHH25UA62624V5Y7CY7BK6CYOQZ7I7PLWK4O74DZUK4A2L42ZPR4PWYEFRHW662TOVUD3PBOW4RLQJ3EHZUZYSO36VC46C3EWGOVODYUISV73OETGRBDRASF744H7TW2GJX3ME7I2YSFBAS63NQAF73BUBGRTRINYCKH3GOZ6YV3UKKQ3LY2QI"}}, "version": "1.0"}
{}
127.0.0.1 - - [09/Jul/2018 15:20:12] "POST / HTTP/1.1" 200 -
Query results are returned in a tuple which apparently is not able to be returned straight to Alexa without some formatting.
Does anyone know how I can return ALL results of a query to Alexa ?
I'm writing an app with same extensions as you except for sqlalchemy and using sqlite. My queries come back as objects so I either :
Have a method that loops through the query object to construct a statement for alexa (great for complex msg)
Pass the object to the flask-ask templates.yaml and use a jinja for loop (good for a simple query)

Python SQLalchemy TypeError: 'list' object is not callable [duplicate]

This question already has an answer here:
"TypeError": 'list' object is not callable flask
(1 answer)
Closed 6 years ago.
*this question is not a duplicate of another question and I have already tried the answer given in that question and it did not solve
my problem. Thanks.
I'm a beginner in Python and learning how to use SQLalchemy.
I am trying to retrieve all rows from my database table
returning the results as a list of objects
my js code will read the list of objects and display into view
However I have been getting this list object is not callable error. Can someone give me a guide on this please thank you.
#mod_core.route('/getDatatable', methods=['GET'])
def datatable_get():
# Query 'user' table.
_user = User.query.all()
_results = []
for user in _user:
print user.get_all()
_results.append(user.get_all())
return _results
127.0.0.1 - - [22/Jan/2017 17:10:46] "GET /getDatatable HTTP/1.1" 500 -
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2000, in call
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask_restful/init.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1642, in full_dispatch_request
response = self.make_response(rv)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1746, in make_response
rv = self.response_class.force_type(rv, request.environ)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/wrappers.py", line 847, in force_type
response = BaseResponse(*_run_wsgi_app(response, environ))
File "/usr/local/lib/python2.7/dist-packages/werkzeug/wrappers.py", line 57, in _run_wsgi_app
return _run_wsgi_app(*args)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/test.py", line 871, in run_wsgi_app
app_rv = app(environ, start_response)
TypeError: 'list' object is not callable
UPDATE 1 : I have also tried changing User to Json before returning and still gets the same error:
#mod_core.route('/getDatatable', methods=['GET'])
def datatable_get():
# Query 'user' table.
_user = User.query.all()
results = []
for user in _user:
results.append(user.to_json())
print results
return results
User class
def to_json(self):
"""
Return a JSON response for RESTful API GET request.
"""
_user_in_josn = {'login_id': self.login_id,
'fullname': self.fullname,
'nickname': self.nickname,
'matric': self.matric_no,
'email': self.email,
'alt_email': self.alt_email
}
return _user_in_josn
UPDATE 2 : Tried to cast to JSON before returning results
User object at 0x7f88f80b14d0> is not JSON serializable
PLease guide me along. Thank you for your kind attention and help.
I'm not sure exactly where your problem is coming from, but I do see a confusing thing you're doing with your user objects. You've obtained a user in your loop, but you're still calling user.get_all(). I'm not sure what that is supposed to do because, at that point, user is just one user object. Do you want the user's database ID? Some other piece of data like the username?
Try changing that line to something like this:
_results.append(user.id)
That will add the user's ID to your list. Or you could append whatever other data you have stored in your user object. If you want to return a full list of all users in your database, then do this:
return _user
I might also suggest renaming those variables _user and _results. Using the leading underscore is usually just for hidden variables, and there doesn't seem to be any need for that here. Also, since _user stores many user objects, a name like users would probably be more appropriate to indicate what the variable contains.

How can I select only one column using SQLAlchemy?

I want to select (and return) one field only from my database with a "where clause". The code is:
from sqlalchemy.orm import load_only
#application.route("/user", methods=['GET', 'POST'])
def user():
user_id = session.query(User, User.validation==request.cookies.get("validation")).options(load_only("id"))
session.commit()
return user_id
This fails and the traceback is:
File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1478, in full_dispatch_request
response = self.make_response(rv)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1577, in make_response
rv = self.response_class.force_type(rv, request.environ)
File "/Library/Python/2.7/site-packages/werkzeug/wrappers.py", line 841, in force_type
response = BaseResponse(*_run_wsgi_app(response, environ))
File "/Library/Python/2.7/site-packages/werkzeug/wrappers.py", line 57, in _run_wsgi_app
return _run_wsgi_app(*args)
File "/Library/Python/2.7/site-packages/werkzeug/test.py", line 867, in run_wsgi_app
app_rv = app(environ, start_response)
TypeError: 'Query' object is not callable
How can I select and return just the "id" column? I have tried several other ways too but also with failure. Is "load_only" the correct option?
A Query object accepts entities to query as positional arguments, so just pass it User.id:
user_id = session.query(User.id).\
filter(User.validation == request.cookies.get("validation")).\
scalar()
scalar() returns the first element of the first result or None, if no rows were found. It raises MultipleResultsFound exception for multiple rows.
load_only() indicates that only the given column-based attributes of an entity should be loaded and all others, expect the identity, will be deferred. If you do need the whole User model object later, this can be the way to go. In that case your original query has to change to:
user = session.query(User).\
filter(User.validation == request.cookies.get("validation")).\
options(load_only("id")).\
one()
one() returns exactly one result or raises an exception (0 or more than 1 result). If you accept None as a valid return value for "no user found", use one_or_none().
Note that predicates, the criteria of the WHERE clause, should not be passed to the Query object as entities, but added with filter().
To top it off, views in Flask expect that you return one of:
a valid response object
a string
a (response, status, headers) tuple
a WSGI application
The machinery will treat anything other than a response object, a string or a tuple as a WSGI application. In your original code you returned a Query object because of the missing call to scalar() or such and this was then treated as a WSGI app.
Note: If you call Model.query(params) you would see the following error
ERROR: 'BaseQuery' object is not callable
You need to call query(params) on session
example:
rows = session.query(Model.name).filter(Model.age >= 20).all()
Alternative:
You can do this using with_entities
example: To fetch names & age where age is greater than 20
rows = Model.query.with_entities(Model.name, Model.age).filter(Model.age >= 20).all()
To query the content of one column instead of the entire table flask-sqlalchemy, which I suppose can give you a hint about sqlalchemy itself would work gets you to query the session as you are doing, with a different syntax.
If your table looks something like:
class User(...):
id = db.Column(db.Integer, primary_key=True)
...
You can query it with:
user_ids = session.query(User.id)
all_ids = user_ids.all()
This returns a list of all User Ids.
You would have to do something along these lines:
session.query(Table.col1).filter(User.name=='Name')
The problem has nothing to do with queries and db connection. Inside #application.route("/user", methods=['GET', 'POST']) statement you return a user_id which is a result of a select from database. In Flask you should return something appropriate.

sqlalchemy.orm.exc.UnmappedInstanceError in flask

I have been reading the SQLAlchemy docs, but I don't understand them. The error (UnmappedInstanceError) says something isn't mapped. What isn't mapped? I really don't get sqlalchemy and I want to go back to using naked sqlite, but so many people recommend this, so I thought I should learn it. Here is the traceback:
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\flask\app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\Me\repos\mandj2\app\views.py", line 170, in add_manentry
db.session.add(q)
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\sqlalchemy\orm\scoping.py", line 149, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "C:\Users\Me\repos\mandj\venv\lib\site-packages\sqlalchemy\orm\session.py", line 1452, in add
raise exc.UnmappedInstanceError(instance)
UnmappedInstanceError: Class '__builtin__.unicode' is not mapped
Here is the applicable code:
#app.route('/addm', methods=['POST'])
def add_mentry():
if not session.get('logged_in'):
abort(401)
form = MForm(request.form)
filename = ""
if request.method == 'POST':
cover = request.files['cover']
if cover and allowed_file(cover.filename):
filename = secure_filename(cover.filename)
cover = cover.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
q = request.form['name']
# do for 12 more fields
db.session.add(q)
db.session.commit()
flash('New entry was successfully posted')
return redirect(url_for('moutput'))
When you are adding a non-model-object into the session, you will be getting UnmappedInstanceError.
In your case, q was probably an unicode string, not a model object. (It appears that you are using Python 2.x because in Python 3.x, it will say str), this was the line of the root cause for UnmappedInstanceError: Class '__builtin__.unicode' is not mapped:
File "C:\Users\Me\repos\mandj2\app\views.py", line 170, in add_manentry
db.session.add(q)
q = request.form['name']
# do for 12 more fields
db.session.add(q)
request.form['name'] will return a unicode value. Then, you do...
db.session.add(q)
The goal of the session is to keep track of Entities (Python objects), not individual unicode values as you seem to be trying to do it (See here for more on what the session does). Thus, you should be adding objects that have a mapping (such as a User object as shown in the "Mapping" section of the ORM tutorial), but you're actually passing a simple unicode value
What you're using is just one part of SQLAlchemy: the ORM (Object-Relational Mapper). The ORM will try to do things like allow you to create a new python object and have the SQL automatically generaeted by "adding" the object to the session..
a = MyEntity()
session.add(a)
session.commit() # Generates SQL to do an insert for the table that MyEntity is for
Keep in mind that you can use SQLAlchemy without using the ORM functionality. You could just do db.execute('INSERT...', val1, val2) to replace your already "naked" SQL. SQLAlchemy will provide you connection pooling, etc (although if you're using SQLite, you probably don't care about connection pooling).
If you want to understand Flask-SQLAlchemy, I would first recommend understanding how SQLAlchemy works (especially the ORM side) by trying it out using simple scripts (as shown in the tutorials. Then you'll understand how Flask-SQLAlchemy would work with it.
If you are changing database see:
You have to address to what item in the object you want to change. See below:
client = session.query(Clients).filter_by(id=client_id).one()
if request.method == 'POST':
new_name = request.form['form_name']
client.name = new_name
session.add(client)
session.commit()
As you can see in the 'client' object, we have "name" among other info inside the object. We want to directly change 'name' only, therefore you need to address to it. (client.name)
If you are adding new thing to database:
Here when you add a new value to the database with orm, you need to specify the item in the object that is receiving the data.
in this case (Client.name)
if request.method == 'POST':
new_name = request.form['form_name']
name = Clients(name=new_name)
session.add(name)
session.commit()
Hope that helps.
I came across a problem like this. In the following code below, I tried to delete some posts:
#app.route('/categorydeletion', methods=['POST'])
def deletecategory():
name_of_category = request.form['categoryname']
category_to_be_deleted = Category.query.filter_by(name=name_of_category).first()
accompained_post = Posts.query.filter_by(category_id=category_to_be_deleted.id).all()
if category:`enter code here`
db.session.delete(category_to_be_deleted)
db.session.delete(accomapained_post)
db.session.commit()
return 'successful
But I was getting the same error sqlalchemy.orm.exc.UnmappedInstanceError
So my fix was this below:
#app.route('/categorydeletion', methods=['POST'])
def deletecategory():
name_of_category = request.form['categoryname']
category_to_be_deleted = Category.query.filter_by(name=name_of_category).first()
accompained_post = Posts.query.filter_by(category_id=category_to_be_deleted.id).all()
if category:
db.session.delete(category_to_be_deleted)
def delete_accomapained_post():
for i in accompained_post:
db.session.delete(i)
delete_accomapained_post()
db.session.commit()
return 'successful'
As #devy pointed out, you work with python objects; with the first scenario I was working with a python list.
But in the second scenario, I had to create a function delete_accomapained_post() to loop through the list to access the Python objects that I want to work with.

Categories

Resources