How to render a template when paypal order is captured? - python

I am implementing a paypal server side payment button. I managed to create the order and capture it.
Now I would like to render a success template when the order is captured, but I don't know where, because here im returning the json response but how can i render a template when the payment is successful? How should this be done?
def capture(request, order_id, mail):
if request.method == "POST":
capture_order = OrdersCaptureRequest(order_id)
environment = SandboxEnvironment(client_id=value, client_secret=value)
client = PayPalHttpClient(environment)
response = client.execute(capture_order)
data = response.result.__dict__['_dict']
letter = Letter.objects.filter(mail=mail).first()
return JsonResponse(data)
else:
return JsonResponse({'details': "invalid request"})

Here is the best front-end sample for a server-side integration: https://developer.paypal.com/demo/checkout/#/pattern/server
This capture sample correctly handles the 3 cases of retrying, showing an error, and showing a success message.
For your implementation, the success case can be to manipulate the DOM to show whatever message / "template" you want to appear.
(You could even use actions.redirect() if you must, although redirects are a poor design choice and to be avoided as much as possible.)

Related

Unable to get returned data in redirected page from previously sent form

I need some help understanding the concepts needed to get my application to work. I am running two instances of localhost, one on 5000: and one on 8000:. One is a Flask instance (backend) and the other is a VUE instance (frontend). On my frontend, I have an onSubmit() function that does two things:
Sends the form data to the Flask instance via axios.post
Redirects the frontend to a result webpage.
On my backend, my Flask instance is supposed to return the information I need.
if request.method == "GET":
#Accessing page for first time
response_object['msg'] = "Waiting for user input"
elif request.method == "POST":
#Form has been submitted
data = request.get_json()
user = parseFormData(data)
itinerary = getResults(user)
return itinerary
I am unsure / unable how to check if this is working. On the redirected page, I have the following method that is called when the page is created.
getResponse(){
const path = "http://127.0.0.1:5000";
axios.post(path)
.then((res) => {
this.tmp = res.data;
console.log(this.tmp);
})
.catch((err) => {
console.error(err);
});
},
I am unable to get anything from this page actually. Any advice on where to go from here will be appreciated!
Edit:
The problem appears to lie in the sequence of events. On my Frontend, the form is submitted then the page is immediately redirected to a result page. While this is happening, my Backend receives the data, processes it and returns the information. That information appears to be lost. I believe this is sort of an example of async but I am unfamiliar with that concept as of now.

405 Method Not Allowed When Redirecting in Flask within POST route [duplicate]

This question already has an answer here:
Flask 405 error with valid route when not accessing request data
(1 answer)
Closed 10 months ago.
I'm hoping to shed some light on why I am getting a 405 Method Not Allowed error.
Expected Outcome - User should be redirected to manage.html template when they attempt to add a review to a game they have already added a review to.
Actual Outcome - 405 Error (Method Not Allowed) Displayed.
Manage Route:
#app.route('/manage')
def manage():
"""Renders manage.html template."""
return render_template('manage.html')
Submit Review Route:
#app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Add users review to database.
"""
user = User.query.filter_by(username=session['username']).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
if existing_review:
flash('You have already created a review for this game')
return redirect(url_for('manage'))
...
What I Have Tried:
I've done some reading of the flask documentation, specifically around flask.redirect (docs), and searched for other examples, but I have been unable to find something that resolves my issue.
I have a hunch that when the user submits the form, and they have already have a review for that particular game, the POST request is also being redirected to the "manage" route.
I checked the network tab in dev tools and it is a GET request, which is correct for that URL.
I guess what I'm trying to say is... I have no idea why this is happening, so don't know how to search for a resolution.
Screenshot of Network -> Headers tab in dev tools:
Server Console:
[10/May/2022 18:43:49] "POST /submit_review/11198 HTTP/1.1" 302 -
[10/May/2022 18:43:49] "review-rating=0&review-heading=&liked-text=&disliked-text=&review-hours=1&game-name=Rocket+League&igdb-id=&igdb-summary=&igdb-cover-url=&action=GET /manage HTTP/1.1" 405 -
When you submit the review the method is POST. Then you redirect to the page /manage that does not accept POST. The request is still POST causing an error. Try adding the POST method to your /manage decorator.
#app.route('/manage', methods= ["GET", "POST"])
def manage():
"""Renders manage.html template."""
return render_template('manage.html')
As i can see in your console, your form uses the GET request? In this case you can use something like
redirect("/Whereever", code=307)
Firstly, Thank you #Henry for the inspiration to finding a solution.
Secondly, I have learnt that including the entire function in the original question, and not just what I feel may be relevant, may have resolved this much sooner.
The Answer.
#Henry mentioned that as per the docs for url_for() - "Variable arguments that are unknown to the target endpoint are appended to the generated URL as query arguments."
This is my take on the situation.
The submit_review() function was returning before the form data was being used, meaning that the form data was unknown to the target endpoint.
Function Before Fix:
#app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Adds users review to database.
"""
existing_game = Game.query.filter_by(igdb_id=game_id).first()
if not existing_game:
igdb_game_data = get_game_data_by_id(game_id)[0]
igdb_game_artwork = get_game_artwork(game_id)
igdb_game_cover = get_game_cover_art(game_id)
game = Game(
name=igdb_game_data['name'],
artwork=json.dumps(igdb_game_artwork),
summary=igdb_game_data['summary'],
igdb_id=igdb_game_data['id'],
cover_art=igdb_game_cover
)
db.session.add(game)
db.session.commit()
user = User.query.filter_by(username=session['username']).first()
game = Game.query.filter_by(igdb_id=game_id).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
if existing_review:
print(request)
flash('You have already created a review for this game')
return redirect(url_for('manage'))
review = Review(
user_id=user.id,
game_id=game.id,
rating=float(request.form.get('review-rating')),
heading=request.form.get('review-heading'),
liked_text=request.form.get('liked-text'),
disliked_text=request.form.get('disliked-text'),
hours=int(request.form.get('review-hours')),
)
db.session.add(review)
db.session.commit()
flash('Review added successfully')
return redirect(url_for('home'))
By moving where the form data is used, I got the expected results, functionality is correct, as the review is not added to the database if a review for that game, by the same user is present.
Function After Fix:
#app.route('/submit_review/<game_id>', methods=['POST'])
def submit_review(game_id):
"""
Adds users review to database.
"""
existing_game = Game.query.filter_by(igdb_id=game_id).first()
if not existing_game:
igdb_game_data = get_game_data_by_id(game_id)[0]
igdb_game_artwork = get_game_artwork(game_id)
igdb_game_cover = get_game_cover_art(game_id)
game = Game(
name=igdb_game_data['name'],
artwork=json.dumps(igdb_game_artwork),
summary=igdb_game_data['summary'],
igdb_id=igdb_game_data['id'],
cover_art=igdb_game_cover
)
db.session.add(game)
db.session.commit()
user = User.query.filter_by(username=session['username']).first()
game = Game.query.filter_by(igdb_id=game_id).first()
existing_review = Review.query.filter_by(user_id=user.id,
game_id=game.id).first()
review = Review(
user_id=user.id,
game_id=game.id,
rating=float(request.form.get('review-rating')),
heading=request.form.get('review-heading'),
liked_text=request.form.get('liked-text'),
disliked_text=request.form.get('disliked-text'),
hours=int(request.form.get('review-hours')),
)
if existing_review:
print(request)
flash('You have already created a review for this game')
return redirect(url_for('manage'))
db.session.add(review)
db.session.commit()
flash('Review added successfully')
return redirect(url_for('home'))

Python | Flask Url_For MissingSchema: Invalid URL Error

im having an issues while trying to scrape the html from the current page the user is on.. Essentially the user is building a list of exercises to create a workout routine, the user is picking from a Select field, and each time they click the "add" button, it will populate a list of what they have chosen so far. Then I will grab the Text from that list and match it to what I have in my database
My issue is coming up in requests.get(url_for('createARoutine')).
requests.exceptions.MissingSchema: Invalid URL '/createaroutine': No schema supplied. Perhaps you meant http:///createaroutine?
when testing it with the direct url "http://127.0.0.1:5000/createaroutine" my error changes to werkzeug.routing.BuildError: Could not build url for endpoint 'http://127.0.0.1:5000/createaroutine'. Did you mean 'createARoutine' instead?
#app.route("/createaroutine", methods=["GET", "POST"])
def createARoutine():
"""
present form to creatine new routine, each time user clicks to
add an exercise, show the exercise to the side"""
form = CreateRoutineForm()
query = Exercises.query.all()
choices = [(c.id, c.name) for c in query]
form.exercises.choices = choices
# collect all exercises and add to routine,
# also add routine to users favorites
if request.method == 'POST':
this_html = requests.get(url_for('createARoutine')) <----ERROR
soup = BeautifulSoup(this_html, 'html.parser')
p = soup.find_all("li", {"id": "exerciseChoices"})
print(p)
return redirect(url_for('showWorkoutRoutines'))
return render_template("createRoutine.html", form=form)
`
This will not work, as requests needs a fully qualified url, including the server where you are running.
On the other hand, I'm strugling to understand why you are doing what you are doing! You are calling your own site with a get, instead of accessing the data from where you are. This is a terrible idea. You have all the data you need in the exact function. If you need the html, it's in the template. You should never, ever do what you are doing here.

How to open window with html or dialog box in middle view django

I have the following scenario:
In a view I do a GET request to an external API with the data that the user provides me via form, with this GET request I get a series of images, the user then needs to write the code of the image he wants and send it to me, I need to then capture the answer and make a new GET request and finally finish my view.
Note: I cannot close my view before user interaction because I have a session object that cannot be lost, if this occurs the code entered will not actually match the image
if request.POST['action'] == 'get_images':
name = request.POST.get('name')
birthday = request.POST.get('birthday')
gender = request.POST.get('gender')
preferences = preferences.Preferences(gender, birthday, name)
preferences.login_page()
preferences.add_page()
images = preferences.get_images() #get images
#need display dialog box with image in di
response = #input user in dialog box
resp = preferences.search_page(response)#new get to know some info user
print(resp)
Following can be one method in which you do this,
Once the user enters data in the first form, send the form data via AJAX to another view in the background and then this AJAX View will call the GET Images API and send the response back.
Using this response you can open an HTML modal on click of the send button of the first form and then populate the response data from GET Images API.
The User can type in the code from this modal into your main page and then submit back to your main view. You can then handle the last bit of logic in your main view.

Google App Engine (Python) redirect not working

I am trying to execute a redirect but it does not seem to be happening. The XHR outputs that the page has finished loading but my page is not redirected at all. The database has the correct data that I queried for and all.
def post(self):
modcode = self.request.get("code")
email = users.get_current_user().email()
query = db.GqlQuery("SELECT * from ModuleReviews where code =:1 and email =:2", modcode, email).get()
if query != None:
self.redirect('/errorR')
else:
module = ModuleReviews(code=self.request.get("code"),text=self.request.get("review"))
module.text = self.request.get("review")
module.code = self.request.get("code")
module.ratings = self.request.get("ratings")
module.workload = self.request.get("workload")
module.diff = self.request.get("diff")
module.email = users.get_current_user().email()
module.put()
self.redirect('/display')
If you're using XHR, you will have to get your Javascript handler to do the redirect via window.location. However, since you always want a redirect, you should consider whether using Ajax is the right thing at all: just submitting via a normal POST would provide exactly the functionality you want without any Javascript needed.

Categories