Django HTTP request to api - python

So i been trying to get this to work but at the same time i do not understand some of these code means. I'm sorry for making the question so long but i want to understand how these works.
I am trying to make a HTTP request to another API to do POST and GET method using django. Based on the website code example, which is this url: https://www.twilio.com/blog/2014/11/build-your-own-pokedex-with-django-mms-and-pokeapi.html
As i wanted to use HTTP Request on my API to call other API, therefore i wanted to get a better understanding of how these works and how to use it.
The code is at the bottom of the website. But i will just provide the code here so it is easier for you.
website code
from django_twilio.views import twilio_view
from twilio.twiml import Response
import requests
import json
BASE_URL = 'http://pokeapi.co'
def query_pokeapi(resource_uri):
url = '{0}{1}'.format(BASE_URL, resource_uri)
response = requests.get(url)
if response.status_code == 200:
return json.loads(response.text)
return None
#twilio_view
def incoming_message(request):
twiml = Response()
body = request.POST.get('Body', '')
body = body.lower()
pokemon_url = '/api/v1/pokemon/{0}/'.format(body)
pokemon = query_pokeapi(pokemon_url)
if pokemon:
sprite_uri = pokemon['sprites'][0]['resource_uri']
description_uri = pokemon['descriptions'][0]['resource_uri']
sprite = query_pokeapi(sprite_uri)
description = query_pokeapi(description_uri)
message = '{0}, {1}'.format(pokemon['name'], description['description'])
image = '{0}{1}'.format(BASE_URL, sprite['image'])
frm = request.POST.get('From', '')
if '+44' in frm:
twiml.message('{0} {1}'.format(message, image))
return twiml
twiml.message(message).media(image)
return twiml
twiml.message("Something went wrong! Try 'Pikachu' or 'Rotom'")
return twiml
My question is:
i have read about the request.POST and request.POST.get but i still don't get it. Isn't request.POST = POST method/create function ?
what does body.lower mean ? Cant seems to find anything about it.
I am very confuse about this part
sprite_uri = pokemon['sprites'][0]['resource_uri']
description_uri = pokemon['descriptions'][0]['resource_uri']
sprite = query_pokeapi(sprite_uri)
description = query_pokeapi(description_uri)
is pokemon['sprites'] refers to the sprites field in the api ?
What does this even means ?
frm = request.POST.get('From', '')
if '+44' in frm:
twiml.message('{0} {1}'.format(message, image))
return twiml
twiml.message(message).media(image)
return twiml
request.POST.get('From', '') Isn't POST where user enter data ? Where does 'From' come from? And what does this means ? if '+44' in frm: if +44 is found in frm ?

ALL The questions are based on very basic python concepts, I recommend you go through python docs here Python Docs
Diff in request.POST and request.POST.get()
Ex request.post has following dict {'abc_key': 'abc_value'}
than request.POST['abc_key'] will give 'abc_value'
but request.POST['xyz_key'] will throw error
so we use default value to escape this error
request.POST.get('xyz_key', "default_value")
this will not give error if xyz_key is not found
body.lower
This method returns a copy of the string in which all case-based
characters have been lowercased.
check this link lower()
pokemon['sprites'][0]['resource_uri']
this is serching in pokemon (which have dictionary values)
Ex. pokemon = {'sprites':[{'resource_uri': 'res_value'}, 1, 2, 3 ]}
so pokemon['sprites'][0]['resource_uri'] will give 'res_value'
frm = request.POST.get('From', '') same as i said in 1st point
if '+44' in frm:
this will return True if string '+44' is substring in frm
variable(string)

Related

Why do I get an error from my API but only when I use some requests?

I am using an API from this site https://dev.whatismymmr.com, and I want to specifically request for the closestRank but I just get a KeyError: 'ranked.closestRank'. but I can get the entire ['ranked'] object (which contains the closestRank) but I just end up with a lot of information I don't need.
How can I end up with just the Closest rank?
My code
import requests
LeagueName = input ("Summoner name")
base = ("https://eune.whatismymmr.com/api/v1/summoner?name=")
Thething = base + LeagueName
print (Thething)
response = requests.get(Thething)
print(response.status_code)
MMR = response.json()
print (MMR['ranked.closestRank'])
The API command
<queue>.closestRank (the queue is the game mode, it can be normal or ranked)
you can use the summoner name babada27 for testing.
Hope this is what you are looking for -
change The last line to
print (MMR["ranked"]["closestRank"])

how to use the curl POST function in Linux terminal to create a document in python

Am trying to add a new record into a python document and I think am stuck with an issue caused by the curl post function. I have attached the python file and the error received when posting to my url. Could anyone kindly point me towards the right direction.
I dont understand the error code to identify whether the problem comes from the python code bu I do suspect an issue with the curl url.
#!/usr/bin/python
import json
from bson import json_util
from bson.json_util import dumps
import bottle
from bottle import route, run, request, abort
#imports for database
from pymongo import MongoClient
connection = MongoClient('localhost', 27017)
db = connection['city']
collection = db['inspections']
# set up URI paths for REST service
#route('/hello', method='GET')
def get_hello():
word = '"'+request.GET.get('name', None)+'"'
string="{hello:"+word+"}"
return json.loads(json.dumps(string, indent=4, default=json_util.default))
#route('/strings', method='POST')
def run_post():
first = '"'+request.json.get('string1')+'"'
second = '"'+request.json.get('string2')+'"'
data="{first:"+first+",second:"+ second+"}"
return json.loads(json.dumps(data, indent=4, default=json_util.default))
#route('/create', method='POST')
def run_create():
myid = request.json.get('id')
print(myid)
cert_number = request.json.get('certificate_number')
bus_name = request.json.get('business_name')
date = request.json.get('date')
result = request.json.get('result')
sector = request.json.get('sector')
added_id = collection.insert({"id":myid,"certificate_number":cert_number,"business_name":bus_name,"date":date,"result":result,"sector":sector})
added_doc = collection.find_one({"_id":added_id})
return json.loads(json.dumps(added_doc, indent=4, default=json_util.default))
#url does not allow spacing when passing an argument,
#therefore i use underscores when passing the business_name and the remove them
#when creating the query
#route('/read', method='GET')
def get_read():
word = request.params.get('business_name')
word = word.replace("_"," ")
found_doc = collection.find({"business_name":{'$regex':word}}) #will still get results when user pass parameter with white space
return dumps(found_doc)
#route('/update', method='GET')
def get_update(rslt = "Violation Issued"):
myid = request.query.id
query = { "id" :myid}
new_update = { "$set":{"result":rslt}}
collection.update_one(query,new_update)
updated_doc = collection.find_one({"id":myid})
return json.loads(json.dumps(updated_doc, indent=4, default=json_util.default))
#route('/delete', method='GET')
def get_update():
myid = request.query.id
query = {"id" :myid};
print(query)
result = collection.delete_one(query)
return "document with id "+myid+" Has beed deleted from the City Collection"
if __name__ == '__main__':
run(debug=True,reloader = True)
#run(host='localhost', port=8080)
Error:
Returned HTML:
python error:
The Problem is that at one point in the json in your curl request you used “ instead of ". Therefore the json parser throws an error.
So instead of
"business_name" : “ACME Test INC."
write:
"business_name" : "ACME Test INC."
Not sure if you solved this but here we go. Jakob was correct that you used “ instead of "
Next, get the values from the document you are inserting
data = request.json (Contains parsed content)
Assign a value to the variables you need such as id
id = data['id']
Store all the values in a dictionary variable (I think it is much cleaner this way)
document = {"id":myid,"certificate_number":cert_number,"business_name":bus_name,"date":date,"result":result,"sector":sector}
Lastly, use insert_one and catch errors
try:
collection.insert_one(document)
print("CREATED NEW DOCUMENT")
except Exception as e:
print("ERROR: ", e)
Also, there are several ways to fix the "space" problem you mention for cURL requests.
One way is to simply add a %20 between spaces like so:
ACME%20TEST%20INC.
I hope that helps.

Python geocoding name 'latitude' is not defined

I'm a new in django. I want to
bulid a webapp to search map by address.(Geocoding) This is my view.py, I want to response to my html file to show the map for the input address. My code shows it has name error at/map/. I dont know the reason. Thanks for kindly reply.
from django.shortcuts import render
import urllib
from urllib.request import urlopen
import json
def searchMap(request):
if request.method == "POST":
global latitude
global longitude
city_name = request.POST.get('address')
city_name_Url="https://maps.googleapis.com/maps/api/geocode/json?
address"+city_name
city_name_Url_Quote=urllib.parse.quote(city_name_Url,':?=/')
response=urlopen(city_name_Url_Quote).read().decode('utf-8')
response_json = json.loads(response)
latitude = response_json.get('results')[0]['geometry']['location']['lat']
longitude = api_response_dict('results')[0]['geometry']['location']['lng']
return render(request,'WebPage1.html',{'Latitude':latitude,'Longitude':longitude})
The error message:
NameError at /map/
name 'latitude' is not defined Request Method: GET
Request URL: http://127.0.0.1:8000/map/ Django Version: 1.8.13
Exception Type: NameError Exception Value: name 'latitude' is not
defined Exception
Location: C:\Users\alienware\Desktop\DjangoWebProject12\DjangoWebProject12\HelloWorld\views.py
in searchMap, line 26 Python
Executable: C:\Users\alienware\Desktop\DjangoWebProject12\DjangoWebProject12\env_DjangoWebProject2\Scripts\python.exe
Python Version: 3.6.3 Python Path:
['C:\Users\Desktop\DjangoWebProject12\DjangoWebProject12',
'C:\Users\Desktop\DjangoWebProject12\DjangoWebProject12',
'C:\Users\Desktop\DjangoWebProject12\DjangoWebProject12\env_DjangoWebProject2\Scripts\python36.zip',
'C:\Users\AppData\Local\Programs\Python\Python36\DLLs',
'C:\Users\AppData\Local\Programs\Python\Python36\lib',
'C:\Users\AppData\Local\Programs\Python\Python36',
'C:\Users\Desktop\DjangoWebProject12\DjangoWebProject12\env_DjangoWebProject2',
'C:\Users\Desktop\DjangoWebProject12\DjangoWebProject12\env_DjangoWebProject2\lib\site-packages']
Server time: Mon, 5 Feb 2018 21:57:22 +0800
I assume (from the error traceback) that your real code looks like this:
def searchMap(request):
if request.method == "POST":
# XXX totally unrelated but : __NEVER__ use mutable globals
# in a django app.
global latitude
global longitude
city_name = request.POST.get('address')
city_name_Url="https://maps.googleapis.com/maps/api/geocode/json?
address"+city_name
city_name_Url_Quote=urllib.parse.quote(city_name_Url,':?=/')
response=urlopen(city_name_Url_Quote).read().decode('utf-8')
response_json = json.loads(response)
latitude = response_json.get('results')[0]['geometry']['location']['lat']
longitude = api_response_dict('results')[0]['geometry']['location']['lng']
return render(request,'WebPage1.html',{'Latitude':latitude,'Longitude':longitude})
Now ask yourself what happens when the request's method is not POST... Yes, everything in the if block is ignored, and only the last statement (return render(...)) is executed. At this point, neither latitude nor longitude have been defined, hence your error.
The first thing to fix is the use of a POST request for a search. POST is used to update the server's state. A search does not change the server's state (at least it should not, and your's doesn't indeed) so the correct verb here is GET. As an added bonus, it will make your search result page bookmarkable.
So first change your template code to use GET as value for your form's method attribute. Then in your view, don't test on the request method at all and look for querystring args in request.GET. Also, you'll want to handle the case where the user didn't actually send anything:
def searchMap(request):
context = {}
city_name = request.GET.get('address', '').strip()
if city_name:
# hint: use the `python-requests` module instead,
# it will make you life much easier
city_name_Url="https://maps.googleapis.com/maps/api/geocode/json?
address"+city_name
city_name_Url_Quote=urllib.parse.quote(city_name_Url,':?=/')
response=urlopen(city_name_Url_Quote).read().decode('utf-8')
response_json = json.loads(response)
context["Latitude"] = response_json.get('results')[0]['geometry']['location']['lat']
context["Longitude"] = api_response_dict('results')[0]['geometry']['location']['lng']
else:
# here you want to display an error message to
# the user - don't forget to check the case
# in your template. Note that it would be simpler
# using a Django Form...
context["error"] = "Some errorr message here"
return render(request,'WebPage1.html',context)

python self.session doesn't save data correctly

I'm developing a webapp using Google App Engine and Python.
I'm facing a strange problem and i don't know how to solve it and what causes it.
When I fill a form I send the data for checking them. If they aren't complete and some fields are missed the server send the form back with an advice "FILL ALL THE FIELDS!".
That's work pretty well.
What I'm trying to do is sending the form back with the "description" and "title" fields filled with what the user has written before submitting the form, so he must to fill only the unfilled fields (and he doesn't need to rewrite everything from the beginning).
That's the code:
class SaleAnnCheck(BaseHandler):
def post(self):
title = self.request.POST.get('title')
cat = self.request.POST.get('cat')
description = self.request.POST.get('description')
AcqOpt = self.request.POST.get('AcqOpt')
lat = self.request.POST.get('lat')
lng = self.request.POST.get('lng')
image1 = self.request.POST.get("file1", None)
image2 = self.request.POST.get("file2", None)
image3 = self.request.POST.get("file3", None)
logging.info("info sale announcment")
logging.info(title)
logging.info(cat)
logging.info(description)
logging.info(AcqOpt)
logging.info(lat)
logging.info(lng)
logging.info(image1)
logging.info(image2)
logging.info(image3)
self.session["ECommerceUser"]["description"]=description
self.session["ECommerceUser"]["title"]=title
logging.info('session')
logging.info(self.session["ECommerceUser"])
if title == '' or cat == None or description == '' or AcqOpt == None or lat == '' or lng == '':
error = 'empty'
urlR='/CreateSaleAnn?'+urllib.urlencode({'error':'empty'})
self.redirect(urlR)
class Create(BaseHandler):
def get(self):
error = self.request.get('error')
if error == 'empty':
logging.info('sbagliato')
logging.info(self.session["ECommerceUser"])
template = JINJA_ENVIRONMENT.get_template('templates/CreateAnnouncement.html')
w = self.response.write
w(template.render({'error':'FILL ALL THE MANDATORY FIELDS!', 'description': self.session["ECommerceUser"]["description"], 'title': self.session["ECommerceUser"]["title"]}))
else:
logging.info('giusto')
logging.info(self.session["ECommerceUser"])
template = JINJA_ENVIRONMENT.get_template('templates/CreateAnnouncement.html')
w = self.response.write
w(template.render({'description': self.session["ECommerceUser"]["description"], 'title': self.session["ECommerceUser"]["title"]}))
When I submit the form the content is checked by making an HTTP post request to a certain URL, handled by SaleAnnCheck.
Description and Title are saved in the session correctly (i checked it by printing the content of self.session["ECommerceUser"] in the logs). Then, if a field isn't filled, the server redirect again to the form page, by a GET request to a related URL.
The requests to that URL is handled by Create. But when i try to render the HTML template of the form (using jinja2) with the previous typed values of Description and Title the related text areas are not filled with that values.
It happens because self.session["ECommerceUser"]["description"] and self.session["ECommerceUser"]["title"] are empty, but they weren't when i checked them before (in SaleAnnCheck).
Why it happens? Any explanation? It's a weird problem and there aren't any tips or suggestion about on internet
This is because 'self.session' is not a Session, it's just a class variable and will not be readable outside the class. If you really want to use persistent sessions for storing variables, try something like this:
From the docs:
http://docs.python-requests.org/en/master/user/advanced/
s = requests.Session()
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get('http://httpbin.org/cookies')

Django AngularJS JSONResponse view in rendering json output

i am developing one of my site with the python django where i have been using angularjs in one of my page where i have given the user option to search (specific request). Here is my model..
class Request(models.Model):
description = models.TextField(blank=True,null=True)
category = models.ForeignKey(Category)
sub_category = models.ForeignKey(SubCategory)
In my views I am returning through the following code:
def some(code, x):
exec code
return x
def search_request(request):
page = request.GET.get('page')
term = request.GET.get('term')
i = 0
terms = "x = Request.objects.filter("
for t in term.split(" "):
i=i+1
if(len(term.split(" "))>i):
terms = terms +"Q(name__icontains='"+t+"')|"
else:
terms = terms +"Q(name__icontains='"+t+"'))"
junk = compile(terms,'<string>', 'exec')
spit = Request.objects.filter(name__icontains=term)
requests = some(junk,spit)
output = HttpResponse()
output['values']=[{'requests':r,'category':r.category,'subcategory':r.sub_category} for r in requests]
return JSONResponse(output['values'])
In my HTML code when I return using AngularJS:
$scope.search = function(){
$scope.results = $http.get("{% url 'search-requests-show' %}?term="+$scope.term).then(
function(result){
return result.data;
}
);
}
The result on the HTML Output comes as in {[{results}]}:
"[{'category': <Category: The New Category>, 'requests': <Request: Need a Table>, 'subcategory': <SubCategory: Testsdfsdfsad>}]"
The problem is that I am not being able to access using results.category because the output is in "string", so the ng-repeat="result in results" brings the result as
[ { ' c a .....
I am probably doing something wrong in view. If anybody has any suggestion then please answer.
JSONResponse is probably using standard python json encoder, which doesn't really encode the object for you, instead it outputs a string representation (repr) of it, hence the <Category: The New Category> output.
You might need to use some external serializer class to handle django objects, like:
http://web.archive.org/web/20120414135953/http://www.traddicts.org/webdevelopment/flexible-and-simple-json-serialization-for-django
If not, you should then normalize object into simple python types inside the view (dict, list, string.., the kind that json module has no problem encoding). So instead doing:
'category':r.category
you could do:
'category': {'name': r.category.name}
Also as a sidenote: using exec is super bad idea. Don't use it in production!
You should return json strings for Angular:
import json
def resource_view(request):
# something to do here
return HttpResponse(json.dumps(your_dictionary))
for better usage i recommend djangorestframework.
Off Topic:
$http.get("{% url 'search-requests-show' %}?term="+$scope.term);
you can pass 'param' object:
$http.get("{% url 'search-requests-show' %}", {param : {term:$scope.term}});

Categories

Resources