Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django and post request to an external API in different views

I want to create a Django App where my users can post data through a form and make a post request to an external API, but getting the response in the same page/view.

For example, I have my view

class Home(TemplateView):
    template_name: 'home/index.html'

And i have my index.html:

<form id="formdata" >
    <select id="options">
        <option id="sku">Option 1</option>
        <option id="sku2">Option 2</option>
    </select>    
    
    <input name="number" type="text"  id="number">
    
    <select id="price">
        <option id="price1">$5</option>
        <option id="price2">%10</option>
    </select>    
    
    <button type="button" data-loading-text="enviando..." onclick="submitInfo()">Send</button>
</form>

Let's ignore the fact HTML may be wrong, it is a basic structure of a form with selects and input field, but note that I need to pass "product", "number" and "price" as parameters in the post request.

The thing is that when the user clicks on the submit button, they make a post request to an external API, I know I can do it with JavaScript using fetch, but the thing is that I need to pass my personal Token Key in the body params, also I'd like to hide the real API URL hiding it with an URL of my web site, for example: www.myurl.com/my-api-call

So I'm thinking about creating a "external_api_view" with post request, something like this:

import requests
import time
from rest_framework import status
from rest_framework.response import Response

def external_api_view(request):
    if request.method == "POST":
        attempt_num = 0  # keep track of how many times we've retried
        while attempt_num < MAX_RETRIES:
            url = 'www.apiexternal.com/endpoint'
            payload = {'Token':'My_Secret_Token','product':'product_select_in_form','price':'price_selected_in_form'}
            response = requests.post(url, data = payload)
            if r.status_code == 200:
                data = r.json()
                return Response(data, status=status.HTTP_200_OK)
            else:
                attempt_num += 1
                # You can probably use a logger to log the error here
                time.sleep(5)  # Wait for 5 seconds before re-trying
        return Response({"error": "Request failed"}, status=r.status_code)
    else:
        return Response({"error": "Method not allowed"}, status=status.HTTP_400_BAD_REQUEST)

But not I have the problem that I don't know how to pass inputs of the form into that view, so I can make the post request and get the response through JavaScript on my index.html file (adding obviously the JavaScript needed).

I don't even know if this is possible, I was thinking in doing something like so with rest framework, but also I have no idea how to.

Any help would be really appreciated :)

like image 903
dldamian Avatar asked Sep 20 '25 17:09

dldamian


1 Answers

First add an action attribute and method attribute to your form. Then add a csrf token for security. Also add name attributes to the select elements.

<form method="post" action="/external" id="formdata" >
  {% csrf_token %}
<select name="options" id="options">
    <option id="sku">Option 1</option>
    <option id="sku2">Option 2</option>
</select>    

<input name="number" type="text"  id="number">

<select name="price" id="price">
    <option id="price1">$5</option>
    <option id="price2">%10</option>
</select>    

<button type="button" data-loading-text="enviando..." onclick="submitInfo()">Send</button>

Next add the url path for the action you added. urls.py:

from django.urls import path
from . import views

app_name = "main"   

urlpatterns = [
    ...
    path("external", views.external_api_view, name="home")

]

Then get the input values in views.py

import requests
import time
from rest_framework import status
from rest_framework.response import Response

def external_api_view(request):
    if request.method == "POST":
        attempt_num = 0  # keep track of how many times we've retried
        while attempt_num < MAX_RETRIES:
            url = 'www.apiexternal.com/endpoint'
            payload = {'Token':'My_Secret_Token','product':request.POST.get("options"),'price':request.POST.get("price")}
            r = requests.post(url, data = payload)
            if r.status_code == 200:
                data = r.json()
                return Response(data, status=status.HTTP_200_OK)
            else:
                attempt_num += 1
                # You can probably use a logger to log the error here
                time.sleep(5)  # Wait for 5 seconds before re-trying
        return Response({"error": "Request failed"}, status=r.status_code)
    else:
        return Response({"error": "Method not allowed"}, status=status.HTTP_400_BAD_REQUEST)

like image 118
ordinarycoders Avatar answered Sep 22 '25 06:09

ordinarycoders