How to prevent an object's class from changing - python

I'm having trouble in a flask application with an object. The first time the function is run, it runs perfectly fine. The second time it is run, however, I get an error that 'str' object has no attribute SubmitFeedResult. I'm able to get around this by restarting the application and running the function again (which then runs fine). The object is being changed to a string after the function is run, and I am wondering if there is a way to prevent the object's class from changing to string (I am leaning towards no because it does this due to the source code in the library that I am using), or what a good way around this issue would be. For the application to run successfully for other users, I cannot have an object with class str
I asked this question a few months ago, solving it briefly but now the issue has come back. This is the link to the original post for some context: 'str' Object has no attribute 'SubmitFeedResult'
Here is the main function:
#app.route('/submission/', methods=['GET','POST'])
def feed_submission():
if request.method == 'POST':
file = request.files['file']
# Only XML files allowed
if not allowed_filetype(file.filename):
output = '<h2 style="color:red">Filetype must be XML! Please upload an XML file.</h2>'
return output
raise ValueError('Filetype Must Be XML.')
# Read file and encode it for transfer to Amazon
file_name = request.form['file_name']
f = file.read()
u = f.decode("utf-8-sig")
c = u.encode("utf-8")
feed_content = c
submit_feed_response = conn.submit_feed(
FeedType=feed_operation(file_name),
PurgeAndReplace=False,
MarketplaceIdList=[MARKETPLACE_ID],
content_type='text/xml',
FeedContent=feed_content)
feed_info = submit_feed_response.SubmitFeedResult.FeedSubmissionInfo.FeedSubmissionId
return redirect(url_for('feed_result', feed_id=feed_info))
else:
return render_template('submit_feed.html',access_key=MWS_ACCESS_KEY,secret_key=MWS_SECRET_KEY,
merchant_id=MERCHANT_ID,marketplace_id=MARKETPLACE_ID)
After this function runs, it redirects to this function to return the response of the request:
#app.route('/feed-result/<int:feed_id>')
def feed_result(feed_id):
response = MWSConnection._parse_response = lambda s,x,y,z: z
submitted_feed = conn.get_feed_submission_result(FeedSubmissionId=feed_id)
result = Response(submitted_feed, mimetype='text/xml')
return(result)
I logged the information of the types and values of submit_feed_response before the issue happens and after to see what is causing the error:
typeof1 = type(submit_feed_response)
val1 = submit_feed_response
typeof_conn1 = type(conn)
app.logger.warning("Type of submit_feed_response (original): " + str(typeof1))
app.logger.warning("Value of submit_feed_response: " + str(val1))
In the logs, when the app runs as it should, I see:
Type of submit_feed_response (original): <class 'boto.mws.response.SubmitFeedResponse'>
Value of submit_feed_response: SubmitFeedResponse{u'xmlns': u'http://mws.amazonaws.com/doc/2009-01-01/'}(SubmitFeedResult: SubmitFeedResult{}(FeedSubmissionInfo: FeedSubmissionInfo{}...
After it fails, I see (as expected) the type is string:
Type of submit_feed_response: <type 'str'>
Value of submit_feed_response: <?xml version="1.0"?>
......
Here is the traceback:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\flask\app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Python27\lib\site-packages\flask\app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "C:\Python27\lib\site-packages\flask\app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Python27\lib\site-packages\flask\app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python27\lib\site-packages\flask\app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python27\lib\site-packages\flask\app.py", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python27\lib\site-packages\flask\app.py", line 1639, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python27\lib\site-packages\flask\app.py", line 1625, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\CTS 41\Documents\Amazon-app\application.py", line 98, in feed_submission
feed_info = submit_feed_response.SubmitFeedResult.FeedSubmissionInfo.FeedSubmissionId
AttributeError: 'str' object has no attribute 'SubmitFeedResult'
It seems that the library is causing the object to return a string once it is run. Is there a good, pythonic way around this? i.e. am I able to somehow change the class of the object to ensure it stays that, or delete it from memory completely? I've tried a try except block, and that comes back with the same error.
EDIT
I have narrowed the issue down to:
response = MWSConnection._parse_response = lambda s,x,y,z: z in the function feed_result. It is there to return the XML response from boto (the call does not naturally come back in XML format, and I am not sure of another way to return it in XML, refer to How can I return XML from boto calls?).
I decided to insert
MWSConnection._parse_response = None above the line
feed_info = feed.SubmitFeedResult.FeedSubmissionInfo.FeedSubmissionId, however it is still coming back with the same error. Is there a way I can clear this function from memory after it is run once? I need this function to properly serve the response, but perhaps there is a better way?

I was able to solve this. The issue, as stated in the question, was stemming from the line response = MWSConnection._parse_response = lambda s,x,y,z: z in feed_result. This line is necessary to parse the response into XML and to serve it, which was causing the response for the submission of the feed to be parsed into an XML string after this function was called. To solve this, I checked to see if feed was not a string, and retrieved the ID as I originally did:
if type(feed) is not str:
feed_info = feed.SubmitFeedResult.FeedSubmissionInfo.FeedSubmissionId
If it is a string, it is parsed as an XML string using ElementTree to retrieve the ID:
else:
tree = et.fromstring(feed)
xmlns = {'response': '{http://mws.amazonaws.com/doc/2009-01-01/}'}
info = tree.find('.//{response}FeedSubmissionId'.format(**xmlns))
feed_info = info.text
Which now works as it should without having to restart the application.

Related

OSError: MoviePy error: the file guitar.mp4 could not be found

I'm working on a video to audio converter with react and flask/python.
I have received a 500 with this error:
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file guitar.mp4 could not be found!
Please check that you entered the correct path.
EDIT: As stated in comments, moviepy VideoFileClip is looking for a path. Per suggestion, I am now attempting to write the incoming video file to a temp directory housed in the backend of the app. The updated stack trace shows the filepath printing, however when presented to VideoFileClip it is still unhappy.
The following snippet is the onSubmit for the video file upload:
const onSubmit = async (e) => {
e.preventDefault()
const data = new FormData()
console.log('hopefully the mp4', videoData)
data.append('mp3', videoData)
console.log('hopefully a form object with mp4', data)
const response = await fetch('/api/convert', {
method: "POST",
body: data
})
if (response.ok) {
const converted = await response.json()
setMp3(converted)
console.log(mp3)
} else {
window.alert("something went wrong :(");
}
}
Here is a link to an image depicting the console output of my file upload
from within init.py
app = Flask(__name__)
app.config.from_object(Config)
app.register_blueprint(convert, url_prefix='/api/convert')
CORS(app)
from within converter.py
import os
from flask import Blueprint, jsonify, request
import imageio
from moviepy.editor import *
convert = Blueprint('convert', __name__)
#convert.route('', methods=['POST'])
def convert_mp4():
if request.files['mp3'].filename:
os.getcwd()
filename = request.files['mp3'].filename
print('hey its a file again', filename)
safe_filename = secure_filename(filename)
video_file = os.path.join("/temp/", safe_filename)
print('hey its the file path', video_file)
video_clip = VideoFileClip(video_file)
print('hey its the VideoFileClip', video_clip)
audio_clip = video_clip.audio
audio_clip.write_audiofile(os.path.join("/temp/", f"{safe_filename}-converted.mp3"))
video_clip.close()
audio_clip.close()
return jsonify(send_from_directory(os.path.join("/temp/", f"{safe_filename}-converted.mp3")))
else:
return {'error': 'something went wrong :('}
In the stack trace below you can see file printing the name of the video, my only other thought on why this may not be working was because it was getting lost in the post request, however the fact it is printing after my if file: check is leaving me pretty confused.
hey its a file again guitar.mp4
hey its the file path /temp/guitar.mp4
127.0.0.1 - - [22/Apr/2021 12:12:15] "POST /api/convert HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/jasondunn/projects/audioconverter/back/api/converter.py", line 20, in convert_mp4
video_clip = VideoFileClip(video_file)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/VideoFileClip.py", line 88, in __init__
self.reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt,
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/ffmpeg_reader.py", line 35, in __init__
infos = ffmpeg_parse_infos(filename, print_infos, check_duration,
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/ffmpeg_reader.py", line 270, in ffmpeg_parse_infos
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file /temp/guitar.mp4 could not be found!
Please check that you entered the correct path.
thanks in advance for taking a look/future advice. First official post on Stack Overflow :)
Looks like python cannot find guitar.mp4 :(
I appears that you need to save the file contents on disk before processing. Looking at the docs for MoviePy you need to pass in the file name or absolute path into VideoFileClip constructor, this object will open the file on disk and handle processing after instantiation.
Saving the file within the request should be simple enough. The code below should be able to handle this
file.save(os.path.join("/path/to/some/dir", filename))
Now you can give VideoFileClip a proper URI to the file.
video_clip = VideoFileClip(os.path.join("/path/to/some/dir", filename))
This is what I would write for convert_mp4 although it isn't tested.
#convert.route('', methods=["POST"])
def convert_mp4():
if request.files.get("mp3"):
# clean the filename
safe_filename = secure_filename(request.files["mp3"].filename)
# save file to some directory on disk
request.files["mp3"].save(os.path.join("/path/to/some/dir", safe_filename))
video_clip = VideoFileClip(os.path.join("/path/to/some/dir", safe_filename))
audio_clip = video_clip.audio # convert to audio
# you may need to change the name or save to a different directory
audio_clip.write_audiofile(os.path.join("/path/to/some/dir", f"{safe_filename}.mp3"))
# close resources, maybe use a context manager for better readability
video_clip.close()
audio_clip.close()
# responds with data from a specific file
send_from_directory("/path/to/some/dir", f"{safe_filename}.mp3")
else:
return jsonify(error="File 'mp3' does not exist!")
Whenever you are saving data to disk through flask you should use secure_filename which is built into flask from the werkzeug project. This function will clean the input name so attackers cannot create malicious filenames.
I would suggest even going a bit further, maybe create 2 endpoints. One for submitting the data to process, and the second for retrieving it. This keeps your requests fast and allows flask to handle other requests in the meantime (however you will need some background process to handle the conversion).
Update April 30th, 2021
I know we solved this on Discord but I wanted to document the solution.
Your MP4 data is not being saved to disk using the save method (see this). You can check the above code that implements this.
Once that is done, we now know where this data is and can instantiate the VideoFileClip object using the known file path, this will allow the conversion to take place and you will need to then save the converted MP3 file on a location within your filesystem.
Once the MP3 is saved to disk, you can use the flask send_from_directory function to send the data back within your response. This response cannot contain JSON content as the content type is already set to audio/mpeg based on the MP3 file contents.
I think the issue is with how you are using file = request.files['mp3'].filename.
The value assigned to file isn't a pointer to the uploaded file. It is just the name of the file, a string. Just request.files['mp3'] is an instance of the werkzeug.datastructures.FileStorage class documented here.
The libraries you are passing that string to are interpreting it as a path to the file they are supposed to open.
Since you haven't saved the file anywhere they library isn't finding anything.
I'm not familiar with the libraries you are using, but they might have a way to send the in-memory file data to them directly without having to save the file then have them open it up again.
If not, then you will probably want to save the file to some temporary location and then have the library open and read the file.

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.

Python: TypeError: 'str' object is not callable (mssql) [duplicate]

This question already has answers here:
Why does code like `str = str(...)` cause a TypeError, but only the second time?
(20 answers)
Closed 8 years ago.
I am running into an issue I cannot seem to resolve.
I have created a Python package containing amongst many things a function inside a class that sends a query to a database and retrieves the results.
I also have a seperate program that uses that function.
The whole thing looks like this:
Oddjob (seperate python module):
def query(self, query):
"""
Running a query against Oddjob and returning result
:param query: The query to run
:return:
"""
try:
qr = self.c.execute(query)
qry = self.c.fetchall()
except Exception, e:
qry = e
return qry
This ^^^ is what is being called.
The query that needs to be run is kept in a variable as such:
sAvail = "exec sp_avi #week='32'"
And gets called like this:
SAvailability(oddjob.query(str(sAvail)))
Just for information, SAvailability is this code:
def SAvailability(result):
shipped = result[0]
onhold = result[1]
percentWO = 100 / int(shipped)
percentOnHold = percentWO * int(onhold)
total = str(int(math.floor(100 - percentOnHold)))
return total
Please note however, I provide the SAvailability function only for clarification, when I use query together with another function I get the same problem:
TypeError: 'str' object is not callable
The full traceback is:
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/arthur/Dropbox/Scaramanga_Development/scaramanga/server.py", line 1062, in dashboard_HEAD
SAvailability(oddjob.query(str(sAvail))),
TypeError: 'str' object is not callable
I have tried adding str() left, right, and centre, but nothing seems to change it.
Can anyone see anything obvious I am missing?
I have tried adding str() left, right, and centre, but nothing seems to change it. Can anyone see anything obvious I am missing?
I guess you some where set str="blablabla".
print type(str) check the result, try del str if print output is str

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.

Flask : TypeError: 'str' object is not callable

I have a generated flask application that is giving me this traceback:
Traceback (most recent call last):
File "/home/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
File "/home/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/home/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/home/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
TypeError: 'str' object is not callable
but I cannot determine why or what is causing this at this point. The app starts and appears to run, but chokes on this traceback anytime I try to visit a route.
What is this and what would be causing this? I don't what object is a str and why it is not callable. This is the first I've seen something like this.
That means that self.view_functions[rule.endpoint] is a string, not a function, thus cannot be called (with (...) operator). That said, it is difficult to tell what the issue without your code: Flask expects a function to be called and it gets a string. Did you use the #app.route decorator?
Try printing the value of self.view_functions[rule.endpoint] and see what comes out.
This is, of course, one of these things that can have multiple different fixes (without seeing all of the original source code).
I got the same error in the HTML template that you did:
TypeError: 'str' object is not callable
My fix was to delete my (foolish) attempt to obtain the original request variables:
my_form = request.form
and just assign them by hand:
my_form.blah = request.form['blah']
Interestingly, the my_form = request.form executed without a problem, it only surfaced as an error in the HTML template.

Categories

Resources