Django Post URL from Browser - python

I'm running through the Django tutorials, and I want to figure out how to post changes to a model from the Browser. Here's the URL:
url(r'^(?P<person_id>\d+)/updatePerson/$', views.updatePerson, name='updatePerson')
)
Here's the view:
def updatePerson(request, person_id):
p = get_object_or_404(Person, pk=person_id)
# try:
# user = p.get(pk=request.POST['name'])
# except (KeyError, Person.DoesNotExist):
# Redisplay the poll voting form.
# return render(request, 'maps/detail.html', {
# 'person': p,
# 'error_message': "This person does not exist",
# })
#else:
p.lat = request.POST['lat']
p.lon = request.POST['lon']
p.task = request.POST['task']
p.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('maps:detail', args=(p.id,)))
The url I try is:
<serveraddress>/maps/1/updatePerson/?lat=20&lon=20&task=hangOut
I get this error:
MultiValueDictKeyError at /maps/1/updatePerson/
"Key 'lat' not found in <QueryDict: {}>"
Request Method: GET
Request URL: <serveraddress>/maps/1/updatePerson/?lat=20
Django Version: 1.5.2
Exception Type: MultiValueDictKeyError
Exception Value:
"Key 'lat' not found in <QueryDict: {}>"
Exception Location: D:\Python\lib\site-packages\django\utils\datastructures.py in __getitem__, line 295
Python Executable: D:\Python\python.exe
Python Version: 2.7.5
Python Path:
['C:\\GXM_LABS\\gxm_maps',
'D:\\Python\\lib\\site-packages\\setuptools-1.1.3-py2.7.egg',
'D:\\Python\\lib\\site-packages\\django_evolution-0.6.9-py2.7.egg',
'D:\\Python\\lib\\site-packages\\south-0.8.2-py2.7.egg',
'C:\\Windows\\system32\\python27.zip',
'D:\\Python\\DLLs',
'D:\\Python\\lib',
'D:\\Python\\lib\\plat-win',
'D:\\Python\\lib\\lib-tk',
'D:\\Python',
'D:\\Python\\lib\\site-packages']
Server time: Sat, 7 Sep 2013 16:42:14 -0400
Should I be doing a regex in my url definiition to catch the values? Or am I approaching this incorectly? I'm working along with the tutorials but modifying them to suit some work I'm doing on the side. I don't really want a form which users input, as in the long run I'll be posting this data from remote locations (Smartphones), and so a webpage which acually has the ability to submit this data is less interesting to me than the ability to post these changes directly.

You should read your query parameters from request.GET instead of a request.POST since you are making a GET request (see Request Method: GET on your error page).
FYI, there is also request.REQUEST dictionary available:
For convenience, a dictionary-like object that searches POST first,
then GET. Inspired by PHP’s $_REQUEST.
But, it's not a good practice to use it. Better be explicit.

Related

Twilio: Create two outgoing calls and join the conference using Python

I am trying to create a conferencing app with max 2 speakers using Twilio using Python/Django. However, in the docs I found out that you can do this by having inbound calls. but, my business model doesnt work like that. Is there a way for this to work like:
My Twilio number calls number 1
My Twilio number calls number 2
Twilio brings two channels to a new conference
I've tried this solution:
Twilio how to make two outbound calls and join(conference) them using node js
but it didn't help me much..
Here's my code:
#csrf_exempt
def conference(request):
print("success")
response = VoiceResponse()
dial = Dial()
dial.conference('Rooxm 1234')
response.append(dial)
print(response)
return HttpResponse('')
def call(number):
client = Client(TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN)
call = client.calls.create(
url='https://<blahblah_removed_purposefully>.ngrok.io/conf/',
to='+' + str(number),
from_='<removed_my_twilio_num>'
)
print(call.sid)
def index(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CallForm(request.POST)
# check whether it's valid:
if form.is_valid():
#print(dir(form.data.values))
call(form.cleaned_data['inline'])
call(form.cleaned_data['outline'])
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = CallForm()
return render(request, 'CallForm.html', {'form': form})
This gave me an error message during the call which is:
"An application error has occurred. Goodbye"
And I also get this in the debugger:
"Error on line 1 of document : Premature end of file. "
Any idea?
Okay so, I figured this out. The only thing that was needed to make that setup work is I had to modify the response, add the xml string there and then set the content_type of the returned object.
return HttpResponse(str(response),content_type='application/xml')

Django (DRF) not showing CORS POST-ed data (from React frontend)

I am using a React frontend, communicating with a DRF (Django Rest Framework) backend.
Currently both are running on their own development server, so they are running on separate domains.
I am sending data from the frontend to the backend, using the POST method, using Axios to send the request.
The code I use can be seen below.
The problem:
Django doesn't seem to be receiving the POST-ed data.
As you can see in the code below, I try to print out the received data, but this is what I see in the console:
[12/Jun/2018 13:33:17] "OPTIONS /order/create HTTP/1.1" 200 0
request.POST:
<QueryDict: {}>
[12/Jun/2018 13:55:47] "POST /order/create HTTP/1.1" 200 2
(it seems to be normal that the printed information comes first in the console, and the line for that POST request after that. Even though the print statement is executed by the POST request, not by the OPTIONS request. This confused me a bit initially.)
What I have tried already:
I've tried to add the following header:
headers: {'Content-Type': 'application/json'}
I've tried adding:
withCredentials: true
(commented out in my code, at the bottom if this post)
Initially this gave me an error about the response to the preflight request not containing an Access-Control-Allow-Credentials' header with the value of 'true'. And this error I resolved by adding the following:
CORS_ALLOW_CREDENTIALS = True
(from the django-cors-headers Django app, set this in settings.py) https://github.com/ottoyiu/django-cors-headers
and then manually adding the header to my response: 
response['Access-Control-Allow-Credentials'] = 'true'
I have already researched parts about CORS before, but again I have read the page below. It doesn't seem to give an answer.
https://www.html5rocks.com/en/tutorials/cors/
The axios code:
checkoutCart: function(submittedValues, products) {
  console.log("checkoutCart")
  console.log(submittedValues)
  console.log(products)
  // let data = {
  //   formData: submittedValues,
  //   productData: products,
  // }
  return axios({
    method: 'post',
    url: 'http://127.0.0.1:8000/order/create',
    data: {
      formData: submittedValues,
      productData: products,
    },
    headers: {'Content-Type': 'application/json'},
    //withCredentials: true,
  })
    .then(function(response) {
      console.log(response)
    })
    .catch(function(error) {
      console.log("error", error)
    })
}
The Django view:
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
#csrf_exempt
def handle_order(request):
    if request.method == 'POST':
        print("request.POST:")
        print(request.POST)
    response = JsonResponse({})
    response['Access-Control-Allow-Credentials'] = 'true'
    return response
You can fetch the post data with:
request.body
After you fetch the post data you need to decode it with
request.body.decode('utf-8')
If you wish to parse this dict of data you can use the json library to convert the string into a iterable dict using:
json.loads(your_post_data)
Heres an entire working snippet:
def handle_order(request):
if request.method == 'POST':
unparsed_json = request.body.decode('utf-8') #Get the data and decode it
postData = loads(unparsed_json) #Convert it to [dict]
for keys in postData:
print(keys) #print all the values in the dict

Why does Django trigger GET after POST?

I have the following view which takes either a URL or an uploaded text file, creates a Word Cloud and finally displays the generated image to the user.
def create(request):
"""
Displays the generated WordCloud from the
given URI or uploaded file
"""
response = HttpResponse(content_type="image/png")
# in order to avoid KeyError
myfile = request.FILES.get('myfile', None)
if request.POST['uri'] == '' and myfile is None:
return render(request, 'nube/index.html', {
'error_message': NOTHING_TO_PROCESS
})
try:
if myfile:
cloud = WordCloud(myfile, type="upload")
else:
cloud = WordCloud(request.POST['uri'], type="internet")
except (MissingSchema):
return render(request, 'nube/index.html', {
'error_message': URI_COULD_NOT_BE_PROCESSED
})
else:
# img is a PIL.Image instance
img = cloud.get_word_cloud_as_image()
img.save(response, 'PNG')
return response
The image is displayed with no problems; the POST request is processed properly, as can be seen from the log:
[16/Jan/2018 22:53:25] "POST /nube/create HTTP/1.1" 200 216961
However, even though the server didn't crash, I noticed an Exception was raised every time immediately after:
Internal Server Error: /nube/create
Traceback (most recent call last):
File "C:\repos\phuyu\venv\lib\site-packages\django\utils\datastructures.py", line 77, in __getitem__
list_ = super().__getitem__(key)
KeyError: 'uri'
After debugging the code I noticed that my create view was being called once again, but this time as a GET request, and of course, the parameters uri and myfile didn't exist this time, thus raising the exceptions.
To make sure, I changed create into a class based view and only defined its post method. As suspected, now I got the following line in the logs after the successful POST:
Method Not Allowed (GET): /nube/create
[16/Jan/2018 22:44:41] "GET /nube/create HTTP/1.1" 405 0
What would be the correct way to handle this? I'm fairly new to Django.
As #usman-maqbool suggested, the problem was actually in my WordCloud clode, especifically, in get_word_cloud_as_image(), a trailing semicolon:
def get_word_cloud_as_image(self):
return self.img;
After removing it, there's no more sneaky GET requests. I'm not sure why it had that effect. I'd appreciate if someone could clarify.

Returning error indication when flask POST Request fails

I'm trying to create a simple flask application that takes a string from an iOS application and stores it in a local data base. I'm a bit confused whats happening in the return portion of the submitPost() function. I'm trying to return a dictionary that contains a BOOL that indicates whether the Post request executed fully. However, i'm not sure how to variate between returning a 0 or a 1.
//Function that handles the Post request
#app.route('/submitPost/', methods=['POST'])
def submitPost():
post = Post.from_json(request.json)
db.session.add(post)
db.session.commit()
return jsonify(post.to_json), {'Success': 1}
Try the below. This way if an exception is thrown when trying to insert data it will be caught and the transaction will be rolled back as well as a response being send back.
you could also replace the zero and one with True & False depending on your preference
Below code hasn't been tested
#app.route('/submitPost/', methods=['POST'])
def submitPost():
try:
post = Post.from_json(request.json)
db.session.add(post)
db.session.commit()
return jsonify({'Success': 1})
except Exception: # replace with a more meaningful exception
db.session.rollback()
return jsonify{'Failure': 0}

Picture property format using run with friends fb app

I am editing the Runwithfriends FB sample app to build one of my own. It was working fine and I was making a few changes here and there. I took a break from it for about a fortnight but now when I try to access the app, I get a strange python error:
C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ROOT\app\main.py in init_facebook(self=<main.RecentRunsHandler object>)
316 user_id=facebook.user_id, friends=friends,
317 access_token=facebook.access_token, name=me[u'name'],
=> 318 email=me.get(u'email'), picture=me[u'picture'])
319 user.put()
320 except KeyError, ex:
<..some portion clipped..>
class 'google.appengine.api.datastore_errors.BadValueError'>: Property picture must be a str or unicode instance, not a dict
args = ('Property picture must be a str or unicode instance, not a dict',)
message = 'Property picture must be a str or unicode instance, not a dict'"
I know this is a very generic error but its pointing to the following code. This code has always been there and I have never touched it. I really do not know where else to look now - I have searched exhaustively but couldnt find a clue. Sorry, if this is still too broad but I would be glad if you can tell me what other info can I provide to debug this :-(
def init_facebook(self):
"""Sets up the request specific Facebook and User instance"""
facebook = Facebook()
user = None
# initial facebook request comes in as a POST with a signed_request
if u'signed_request' in self.request.POST:
facebook.load_signed_request(self.request.get('signed_request'))
# we reset the method to GET because a request from facebook with a
# signed_request uses POST for security reasons, despite it
# actually being a GET. in webapp causes loss of request.POST data.
self.request.method = u'GET'
self.set_cookie(
'u', facebook.user_cookie, datetime.timedelta(minutes=1440))
elif 'u' in self.request.cookies:
facebook.load_signed_request(self.request.cookies.get('u'))
# try to load or create a user object
if facebook.user_id:
user = User.get_by_key_name(facebook.user_id)
if user:
# update stored access_token
if facebook.access_token and \
facebook.access_token != user.access_token:
user.access_token = facebook.access_token
user.put()
# refresh data if we failed in doing so after a realtime ping
if user.dirty:
user.refresh_data()
# restore stored access_token if necessary
if not facebook.access_token:
facebook.access_token = user.access_token
if not user and facebook.access_token:
me = facebook.api(u'/me', {u'fields': _USER_FIELDS})
try:
friends = [user[u'id'] for user in me[u'friends'][u'data']]
user = User(key_name=facebook.user_id,
user_id=facebook.user_id, friends=friends,
access_token=facebook.access_token, name=me[u'name'],
email=me.get(u'email'), picture=me[u'picture'])
user.put()
except KeyError, ex:
pass # ignore if can't get the minimum fields
self.facebook = facebook
self.user = user
Might have to do with the October 2012 Breaking Changes, quote:
/picture connection will return a dictionary when a callback is specified
We will start returning a dictionary containing the fields url, height, width, and is_silhouette when accessing the /picture connection for an object and specifying a callback property. Currently we just return the picture URL as a string.
So at this point in your code, where you are currently using picture=me[u'picture'], try accessing the url property of the picture dictionary instead. (If it has one; I can’t tell you for sure if this is applicable, since I don’t know if your code would be considered as having specified a callback property.)
If my assumption is correct, you could also enable the migration as described in the roadmap; but that will only make your app work in the old way until Oct. 3rd, so probably better to try and fix it right away.
This is the way to get the picture:
picture=me[u'picture'][u'data'][u'url']

Categories

Resources