Goal: Pull video_id from assessment_obj, assign to variable
DB Type: SQLAlchemy
Model: Assessment holds video_id in a Many-to-One relationship (multiple assessments can use a video)
1.) I am trying to use dot.notation to pull the video_id from the assessment 2.) so that I can use the retrieve method to pull the video information (such as url).
Purpose: The video url will be used to enter into a video player src via a JINJA2 template/HTML code. (I apologize if I am using jargon incorrectly as I am new and am trying to better understand the concepts.)
I was trying to follow a OOP dot.notation tutorial, but was uncertain on how to pull the data from a table and assign to a variable without accidently reassigning the variable.
views.py
The form view config.
#view_config(route_name='save_assessment_result', renderer='templates/completedpage.jinja2')
def save_assessment_result(request):
with transaction.manager:
assessment_id = int(request.params['assessment_id'])
assessment_obj = api.retrieve_assessment(assessment_id) # the assessment
assessment_obj.video_id = video # this right?
thevid = api.retrieve_video(video) #retrieves the video via ID
template_video = int(request.params['video'])
# how do I get the retrieved video 'thevid' into the template?
# more code
transaction.commit()
return HTTPCreated()
template: templates/assessment_form.jinja2
<div class="embed-responsive embed-responsive-16by9">
<iframe width="640" height="360" class="embed-responsive-item" allowfullscreen name='video' src="{{ url }}"></iframe>
</div>
NEW: Return for assessment_obj. New View_Config.
Note: 'videoname': video.videoname, 'length': video.length, 'url': video.url
#view_config(route_name='assessment', request_method='GET', renderer='templates/assessment_form.jinja2')
def assessment_form_view(request):
with transaction.manager:
assessment_id = int(request.matchdict['id'])
assessment = api.retrieve_assessment(assessment_id)
if not assessment:
raise HTTPNotFound()
video_id = int(request.matchdict['id']) # <--- this gives the assessmnet_id and not the video
video = api.retrieve_video(video_id)
return {'assessment_id': assessment_id, 'assessment_name': assessment.name, 'assessment_text': assessment.text, 'user_id': assessment.user_id, 'video_id':assessment.video_id, 'categories': ','.join([str(i) for i in assessment.categories]), 'video_id':video_id, 'videoname': video.videoname, 'length': video.length, 'url': video.url}
In the line assessment_obj.video_id = video - where does the video variable come from?
Seeing that you're trying "pull the data from a table and assign to a variable" I'm wondering if you actually tried to assign assessment_obj.video_id to a variable called video. In this case it should be another way round:
video = assessment_obj.video_id
Then you code almost starts to make sense. To pass the data to the template you simply return a dictionary from your view function:
#view_config(route_name='save_assessment_result', renderer='templates/assessment_form.jinja2')
def save_assessment_result(request):
with transaction.manager:
assessment_id = int(request.params['assessment_id'])
assessment_obj = api.retrieve_assessment(assessment_id) # the assessment
video_id = assessment_obj.video_id
thevid = api.retrieve_video(video_id)
template_video = int(request.params['video'])
return {
'thevid': thevid,
'template_video': template_video
}
Then in your template you can reference those variables and their members:
<iframe ... src="{{ thevid.url }}"></iframe>
Per Sergey's amazing guidance I created a new view configuration that loaded the assessment and the video. I then returned the values needed.
Working code:
#view_config(route_name='assessment', request_method='GET', renderer='templates/assessment_form.jinja2')
def assessment_form_view(request):
with transaction.manager:
assessment_id = int(request.matchdict['id'])
assessment = api.retrieve_assessment(assessment_id)
if not assessment:
raise HTTPNotFound()
video = assessment.video_id
print 'test_video_id', video
video_obj = api.retrieve_video(video)
print 'test_video_obj', video_obj
return {'assessment_id': assessment_id, 'assessment_name': assessment.name, 'assessment_text': assessment.text, 'user_id': assessment.user_id, 'categories': ','.join([str(i) for i in assessment.categories]), 'url': video_obj.url, 'video_id':video_obj.video_id, 'videoname': video_obj.videoname, 'length': video_obj.length}
Related
This is the thing, I was trying to make a crud for a rest api for a movie app, I was able to successfully perform the functionalities with flask to create a movie within the json, to delete a movie, and to list them, but I have problems with being able to edit one of the movies inside the JSON since I don't know how to access a sector of it to be able to modify it, this is what I was trying:
def __init__(self, idpelicula, nombre, descripcion, elenco, restriccionedad, fecha, calificacion):
self.idpelicula = idpelicula
self.nombre = nombre
self.descripcion = descripcion
self.elenco = elenco
self.restriccionedad = restriccionedad
self.fecha = fecha
self.calificacion = calificacion
movies_list = [
Peliculas(1, "Shrek", "Pelicula de Ogro", "Shrek, Fiona", "+APTA", "2001", "10"),
Peliculas(2, "Shrek2", "Otra Pelicula de Ogro", "Shrek, Fiona", "+APTA", "2005", "10"),
]
#app.route("/movies")
def list_movies():
return jsonify([pelicula.__dict__ for pelicula in movies_list])
#app.route("/movies/<id_search_movie>")
def obtener_pelicula(id_search_movie):
for pelicula in movies_list:
if pelicula.idpelicula == int(id_search_movie):
return jsonify(pelicula.__dict__)
return "Pelicula no encontrada", 404
#app.route("/movies", methods=['POST'])
def create_movie():
movie_data = request.get_json()
new_movie = Peliculas(movie_data["idpelicula"], movie_data["nombre"], movie_data["descripcion"],
movie_data["elenco"], movie_data["restriccionedad"], movie_data["fecha"],
movie_data["calificacion"])
movies_list.append(new_movie)
return "OK", 200
#app.route("/movies/<id_delete_movie>", methods=['DELETE'])
def delete_movie(id_delete_movie):
for pelicula in movies_list:
if pelicula.idpelicula == int(id_delete_movie):
movies_list.remove(pelicula)
return "OK", 200
This is what I dont know how to do, (I know its wrong, and that this isn't even the logic to do this), but this is what I tried:
#app.route("/movies", methods=['PUT'])
def edit_movie():
movie_data = request.get_json()
new_movie = Peliculas(movie_data["idpelicula"], movie_data["nombre"], movie_data["descripcion"],
movie_data["elenco"], movie_data["restriccionedad"], movie_data["fecha"],
movie_data["calificacion"])
movies_list.append(new_movie)
return "OK", 200
Any help, even from the point of view of the logic behind doing this will come handy. Thanks to you all.
There is a ton of problems with the way you are coding this at the moment, but here i will show you how you can edit an object in the way you are currently doing it.
So with your approach the edit view should be like this:
#app.route("/movies", methods=['PUT'])
def edit_movie():
# Accessing data from request
movie_data = request.get_json()
# Accesing Object from the movie-list by ID
for movie in movies_list:
if movie.idpelicula == movie_data["idpelicula"]:
edited_movie = movie
# Modifying the object attributes
for name, value in movie_data.items():
if hasattr(edited_movie, name):
setattr(edited_movie, name, value)
return "OK", 200
The problem here is that you were creating a new instance instead of editing an existing one.
in the future you could explore the usage of SQLAlchemy models so you can persist the data in a database, and still be managing objects.
PD1: Finally i recommend you be coherent with the naming, by this i mean if you are calling your variables and classes in spanish Pelicula, peliculas, try to use the same naming throught all your code, same if you use english.
PD2: Study some basic python usage of classes and variable assignment, so you can improve your code.
Greetings from Chile.
I am using flask and web3.eth on pythonanywhere and connecting to a contract, but am having issues returning a value for one of the smart contract functions. No errors are being logged. I have placed several print statements to see where the app is stopping and found that it stops when I call a smart contract function.
Also I should mention that I am able to run this exact code locally without issues.
This is the function that is most likely failing:
def getDataFromTokenID(tokenid, contract):
print('getting uri')
uri = contract.functions.tokenURI(tokenid).call() # This is where it stops printing
print('PRINT:',uri)
html = requests.get(uri)
name, img_url = html.json()['name'], html.json()['image']
code = name[-5:]
return name, img_url, code
The function above is called in the following blueprint:
#TokenInfo.route('/rarity/<int:tokenid>', methods=['GET'])
def sendTokenInfo(tokenid):
contract_address = ' ' # left empty for posting purposes
w3 = Web3(Web3.WebsocketProvider(' ')) # left empty purposefully as well
contract = w3.eth.contract(address=contract_address, abi=contract_abi.abi)
model = Shape_classifier()
model.load_state_dict(load(os.getcwd()+'/mysite/app/state_dict.pth'))
uri = current_app.config['MONGO_URI']
mongo.init_app(current_app, uri)
gs = mongo.db.gantomstone_info
try:
id_exists = [{"$match": {'_id': tokenid}}, {"$count": "count"}]
list(gs.aggregate(id_exists))[0]
except:
print('getting data from token id')
name, img_url, serial = getDataFromTokenID(tokenid, contract) ## Stops printing here
print('opening image')
img = Image.open(requests.get(img_url, stream=True).raw)
shape = getImageShape(img, model)
colors = getColors(getCounts(img))
rgb_count = getCounts(img)
serialTF = getCodeInfo(serial)
to_db = {'_id': tokenid, 'name': name, 'img_url': img_url, 'serial': serial,
'shape': shape, 'colors': colors, 'serialTF': serialTF, 'rgb_count': rgb_count}
gs.insert_one(to_db)
rarity = getRarity(gs, tokenid)
gs.update_one({'_id': tokenid}, {
'$set': {'rarity_values': rarity}}, upsert=True)
to_json = list(gs.find({'_id': tokenid}))[0]
return jsonify(to_json)
I have tried moving contract address around (both out of TokenInfo view function and into the functions file) to no avail. I have also tried changing the function inputs to receive the get request args instead of the int in the URL, which made no difference either.
If the code uses websockets it won't currently work in web apps on PythonAnywhere.
I would like to check and improve the codes I wrote because it takes time... slow
probably I could wrote better...
here are the codes at views.py
def price_detail(request):
if request.method == "POST":
flight_date = request.POST.get('flight_date')
direction = request.POST.get('direction')
suburb = request.POST.get('suburb')
no_of_passenger = request.POST.get('no_of_passenger')
def price_cal():
if direction == 'Drop off To airport':
return int(suburbs.get(suburb)) + ((int(no_of_passenger) * 10) - 10)
else:
return int(suburbs.get(suburb)) + (int(no_of_passenger) * 10)
price_cal()
price = str(price_cal())
p = Post(flight_date=flight_date, direction=direction, suburb=suburb,
no_of_passenger=no_of_passenger, fare=price)
p.save()
data = {
'flight_date': flight_date,
'direction': direction,
'suburb': suburb,
'no_of_passenger': no_of_passenger,
'price': price,
}
message = '''
Flight date: {}
Direction: {}
Suburb: {}
No of passenger: {}
Price: {}
'''.format(data['flight_date'], data['direction'],
data['suburb'], data['no_of_passenger'], data['price'])
send_mail(data['flight_date'], message, '', ['sungkam3#gmail.com'])
return render(request, 'basecamp/price_detail.html',
{'flight_date': flight_date, 'direction': direction, 'suburb': suburb,
'no_of_passenger': no_of_passenger, 'price': price},
)
else:
return render(request, 'basecamp/price_detail.html', {})
User put some information on html and inquiry about the price... views get objects from templates, work out the price and after that, save all the information into database and email to me the details user inquiried. After all this donw, views.py send information to other page (html) to show the results to User.
it works fine... but the problem is only time... too slow
Is it because of Python or my codes?
your code is fine, the problem is with sending an email, sending in an email could take a lot of time.
so you could refactor your code to send the email in a different thread or you could even use celery.
I 'ld like for a user to drop a random search in a search form for a book title and find get results if the book is in the db. Below is part of the code block.
I 'm having some issues searching for a single document in my mongodb using a search field and search strings. Below is the code. I'm trying to get the search result via the find_book route.
The code above with the /find_book/<book_id> returns errors.
Below is a part of my code in the app.py file and the search form.
I get the following errors.
werkzeug.routing.BuildError
werkzeug.routing.BuildError: Could not build url for endpoint 'find_book'. Did you forget to specify values ['book_title']?
Traceback (most recent call last)
# create an instance of py_mongo with app as argument
mongo = PyMongo(app)
#app.route('/')
def home():
return render_template('home.html')
# define the various menu options
#app.route('/get_books')
def get_books():
return render_template('books.html', books=mongo.db.books.find())
# Add a book
#app.route('/add_book')
def add_book():
return render_template('add_book.html',
faculties=mongo.db.faculties.find())
# Add submit button for Books
#app.route('/insert_book', methods=['POST'])
def insert_book():
book = mongo.db.books
book.insert_one(request.form.to_dict())
return redirect(url_for('get_books'))
# wire the edit button
#app.route('/edit_book/<book_id>')
# description task, name, due date, is urgent fields will be
# pre-populated based on the information returned in the task.
def edit_book(book_id):
a_book = mongo.db.books.find_one({"_id": ObjectId(book_id)})
# category names will be prepolulated based on the collection
# # of categories returned in the categories cursor
all_faculties = mongo.db.faculties.find()
return render_template('edit_book.html',
book=a_book, faculties=all_faculties)
#app.route('/update_book/<book_id>', methods=['POST'])
def update_book(book_id):
# access the database collection
book = mongo.db.books
# call the update function, specify an id
book.update({'_id': ObjectId(book_id)},
{
'faculty_name': request.form.get('faculty_name'),
'subject_name': request.form.get('subject_name'),
'book_title': request.form.get('book_title'),
'book_author': request.form.get('book_author'),
'book_description': request.form.get('task_description'),
'lender_name': request.form.get('lender_name'),
'due_date': request.form.get('due_date'),
'is_available': request.form.get('is_urgent')
})
return redirect(url_for('get_books'))
# specify the form fields to match the keys on the task collection
# delete a book
#app.route('/delete_book/<book_id>')
def delete_book(book_id):
mongo.db.books.remove({'_id': ObjectId(book_id)})
return redirect(url_for('get_books'))
# find a book by text search
#app.route('/find_book/<book_title>', methods=['GET'])
def find_book(book_title):
book_title = mongo.db.books
book_title.find_one(
{
'book_title': request.form.get('book_title'),
})
return render_template('find.html', book_title=book_title)
# categories function
#app.route('/get_faculties')
def get_faculties():
return render_template('faculties.html',
faculties=mongo.db.faculties.find())
if __name__ == '__main__':
app.run(host=os.environ.get('IP'),
port=int(os.environ.get('PORT')),
debug=True)
<form action="{{ url_for('find_book') }}" method="GET">
<input type="text" placeholder="Book Title" id="book_title" name="book_title" >
<button type="submit"><i class="fa fa-search">Search</i></button>
</form>
Your find_book route is expecting an argument book_title
But you are not passing that in {{ url_for('find_book') }}
You could just change this route to #app.route('/find_book') and get the value from request.form or if you are using this route in another place of your application you could use the approach from this question and use this way:
#app.route('/find_book/', defaults={'book_title': None})
#app.route('/find_book/<book_title>')
def find_book(book_title):
books = mongo.db.books
if book_title is None:
book_title = request.form.get('book_title')
book = books.find_one({
'book_title': book_title
})
return render_template('find.html', book=book)
I could not run this snippet of code now, so let me know if dont work.
I am trying to write a controller method and a corresponding view which will call the controller on web2py using Ajax. The idea is to make a small update on the database and return a simple updated message on a target div using Ajax. Below is contoller method:
def deleteajax():
recid1 = request.vars.recid
reptype1 = request.vars.reptype
if recid1 == None:
out = 'Missing Param : recid'
return out
if reptype1 == None:
reptype1 = 'pr'
if reptype1 == 'pr':
row = db2(db2.prs_mailed.id==recid1).select().first()
return str(row.id)
elif reptype1 == 'tb':
row = db2(db2.tbs_mailed.id==recid1).select().first()
else:
return 'Please provide the parameter : rep'
if row['action'] == 'D':
out = 'Already deleted'
return out
else:
row.update_record(action='D')
out = 'Deleted Successfully!'
return out
and this is how I am calling the same from view:
<form>{{
response.write('<input type="hidden" name="recid" value="'+str(response._vars['prs']['id'][k])+'"/>',escape=False)}}
<input type ='button' name="del" value = "D" onclick="ajax('deleteajax', ['reid'], 'target')" />
<div id="target"></div>
</form>
I have tested the controller individually using a POST call and that works. Even the AJAX call works and displays error messages like 'Missing Param : recid' on the target div. I even tried modifying the controller to show more messages after finishing each statement. However, post any database operation, no commands from the controller are getting executed, nor is anything showed on the target div. Where am I going wrong?
First, instead of this:
{{response.write('<input type="hidden" name="recid" value="' +
str(response._vars['prs']['id'][k])+'"/>',escape=False)}}
Just do this:
<input type="hidden" name="recid" value="{{=prs['id'][k])}}"/>
There's no need to use response.write or to access the "prs" object through response._vars (all the items in response._vars are available globally in the view environment).
Regarding the Ajax problem, your input element name is "recid", but your ajax() call refers to "reid". Change the latter to "recid" and see if it works.
UPDATE:
To create multiple unique recid's, you could do:
name="{{='recid%s' % prs['id'][k]}}"
Then, in the controller, check for request.vars that start with "recid":
recid = [v for v in request.post_vars if v.startswith('recid')]
if recid:
recid = int(recid[0][5:])
[code to delete record with id==recid]