MultiValueDictKeyError Request Method: GET (Django) - python

I have recently started to learn and work on Django i came across this error multiple times sometimes it was due to repetitive use of a name in an html and sometimes it was due the part for example "variable_name=request.POST['variable_name']"
I visited various sites regarding this error and was able to find a solution i.e, once i have typed in "variable_name=request.POST['variable_name']" in a function in views.py
the next time i tried to POST the data again "variable_name=request.POST['variable_name']" I had to do something like this "variable_name=request.POST.get('variable-name', 'blank_or_whatever_canBeFalseAlso')
The Above statement helped me solve that error I got this solution from A Thread in StackOverflow itself Quite a useful site.
Now for the Question am just Curious to know whats the difference between
Variable_Name=request.POST['Variable_Name']
Variable_Name=request.POST.get('Variable_Name','Whatever')
Code (views.py) Is given Below:
from django.shortcuts import render
from . import views
from datetime import date
from .models import Batch, Deleted_Batch
from django.utils.datastructures import MultiValueDictKeyError
# Create your views here.
today = date.today()
Date_Batch = str(today.day)+'/'+str(today.month)+'/'+str(today.year)
def Reg_Batch(request):
return render(request, 'Reg_Batch.html',{'Date_Batch':Date_Batch})
def Reg_Batch_Receive(request):
Region_Code=request.POST['Region_Code']
Branch_Code=request.POST['Branch_Code']
Batch_Number=request.POST['Batch_Number']
Farm_Code=request.POST['Farm_Code']
Farm_Status=request.POST['Farm_Status']
Farmer_Name=request.POST['Farmer_Name']
Farmer_Address=request.POST['Farmer_Address']
Farmer_Phone_Number=request.POST['Farmer_Phone_Number']
Farmer_Email=request.POST['Farmer_Email']
return render(request, 'Reg_Batch_Receive.html')
def Reg_Batch_View(request):
Region_Code=request.POST.get('Region_Code', 'Blank')
Branch_Code=request.POST.get('Branch_Code', 'Blank')
Farm_Code=request.POST.get('Farm_Code', 'Blank')
Farm_Status=request.POST.get('Farm_Status', 'Blank')
return render(request, 'Reg_Batch_View.html',{'Region_Code':Region_Code,'Branch_Code':Branch_Code,'Farm_Code':Farm_Code,'Farm_Status':Farm_Status})
def Reg_Batch_View_Receive(request):
Date_Batch= '20/08/2000'
Region_Code='586001'
Branch_Code='586001'
Batch_Number='586001'
Farm_Code='5484712'
Farm_Status='Active'
Farmer_Name='Joel Liao'
Farmer_Address='jojojojojojojo'
Farmer_Phone_Number='8088078086'
Farmer_Email='kuroneko#gmail.com'
return render(request,'Reg_Batch_View_Receive.html',{'Date_Batch':Date_Batch,'Region_Code':Region_Code,'Branch_Code':Branch_Code,'Batch_Number':Batch_Number,'Farm_Code':Farm_Code,'Farm_Status':Farm_Status,'Farmer_Name':Farmer_Name,'Farmer_Address':Farmer_Address,'Farmer_Phone_Number':Farmer_Phone_Number,'Farmer_Email':Farmer_Email})
def Reg_Batch_Delete(request):
Region_Code='586001'
Branch_Code='586001'
Batch_Number='586001'
Farm_Code='5484712'
Farm_Status='Active'
Farmer_Name='Joel Liao'
Farmer_Address='jojojojojojojo'
Farmer_Phone_Number='8088078086'
Farmer_Email='kuroneko#gmail.com'
Deleted_Batch_DataBase=Deleted_Batch({'Region_Code':Region_Code,'Branch_Code':Branch_Code,'Batch_Number':Batch_Number,'Farm_Code':Farm_Code,'Farm_Status':Farm_Status,'Farmer_Name':Farmer_Name,'Farmer_Address':Farmer_Address,'Farmer_Phone_Number':Farmer_Phone_Number,'Farmer_Email':Farmer_Email}),
return render(request,'Reg_Batch_Delete.html',{'Batch_Number':Batch_Number})
def Reg_Batch_Delete_Receive(request):
Batch_Number='586001'
return render(request,'Reg_Batch_Delete_Receive.html',{'Batch_Number':Batch_Number})

request.POST is a dictionary-like object (see docs).
So if you do
request.POST['foobar']
you can access the posted variable foobar. But if this is not being posted and therefore not set inside POST, you will get the MultiValueDictKeyError.
This is similar to access a key inside a default dictionary which is not set, e.g.
d = {}
d['foobar'] # raises Exception
In order to avoid this error, you can then do
request.POST.get('foobar', 'default-value')
in order to get the posted field and a default if it is not present.
So if foobar isn't set inside your POST-data, the received value is default-value.
This is similar to the default dictionary handling:
d = {}
d.get('foobar', 'random') # returns 'random'

Related

PAGE NOT FOUND- ERROR(404);GET request; django-python

Lately I have been trying to use the GET request in django-python. However I run into a 404 error when I do so. I want the program to print the parameter given to it.
URL PATTERN :
path('add<int:hello>/',views.add,name = 'Add')
VIEWS.PY:
def add(request,num1):
val1 = request.GET["num1"]
return HttpResponse(request,"Hello")
WHAT I AM SEARCHING ON BROWSER:
http://127.0.0.1:8000/add?1
A couple of things are strange or broken here.
Given path('add<int:hello>/', views.add, ...),
Django expects that function views.add has the following signature:
def add(request, hello):
The pattern 'add<int:hello>/' expects urls with "add" followed by an integer, such as:
http://127.0.0.1:8000/add1
http://127.0.0.1:8000/add2
http://127.0.0.1:8000/add3
...
and so on.
request.GET["num1"] expects urls that have num1=... in their query string, such as:
http://127.0.0.1:8000/add1?num1=...
HttpResponse expects a string type as its first parameter,
not an HttpRequest type as in the posted code.
Fixing the problems
This might be close to what you want, and it will work:
path('add<int:num1>/', views.add, name='Add')
def add(request, num1):
return HttpResponse(f"Hello {num1}")
# visit http://127.0.0.1:8000/add1
Another variation:
path('add', views.add, name='Add')
def add(request):
num1 = request.GET['num1']
return HttpResponse(f"Hello {num1}")
# visit http://127.0.0.1:8000/add?num1=123
http://127.0.0.1:8000/add?hello=1
This should work. you need to add the query param name as well.
To get the value you need to use this code:
request.GET["hello"]

How to pass an HTTP request as a parameter of a python function?

I'm calling a python function and passing an HTTP request as a parameter but it's not working. I created the function in a View and called it in another, but the parameter fails.
Here's the function I'm calling
def load_colmeias(request):
apiario = request.GET.get('apiario')
if apiario != "":
colmeias = Colmeia.objects.filter(apiario=apiario)
return render(request, 'colmeias_choices.html', {'colmeias': colmeias})
else:
return render(request, 'colmeias_choices.html')
Here I call her
load_colmeias(request)
But the following error occurs
NameError: name 'request' is not defined
I already imported the "urlib" and "requests" libraries but it always gives the same error:
AttributeError: module has no attribute 'GET'
Can someone help me ?? I'm new to Python/Django and I'm still learning how to do things
Check if you have requests installed:
import requests
r=requests.get("https://automatetheboringstuff.com/files/rj.txt")
print(len(r.text))
Now, check:
In load_colmeias(request), make sure the parameter is actually request and not requests throughout.
Your filename is not requests.py; otherwise you would be importing your own file.
request and requests are two different things, one without 's' is a parameter and with 's' is a method. to use requests you have to import requests library this is a third party library to fetch data from an API.
if you want to call this function you have to make a request through an API. create an API for this function and then make a request.
your views.py file:
def load_colmeias(request):
apiario = request.GET.get('apiario')
if apiario != "":
colmeias = Colmeia.objects.filter(apiario=apiario)
return render(request, 'colmeias_choices.html', {'colmeias': colmeias})
else:
return render(request, 'colmeias_choices.html')
Your urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('load_colmeias', views.load_colmeias)
]
Now your API is:
http://127.0.0.1:8000/load_colmeias?apiario=1234
make sure you have used the correct port in the api and have started the server before making the request and pass the correct value of apiario.
There is another way to call this function by using requests library:
import requests
res = requests.get('http://127.0.0.1:8000/load_colmeias?apiario=1234')
print(res.text)
you can use this in any file and call your function like this using this library again the server must be running and pass the correct value of apiario.
Well if you are passing a request parameter then you have to make the request. You can't call it the way you have shown.
I SOLVED THE PROBLEM !! Basically, I just created a function that calls another function and passed the same argument to both... As can be seen below:
def load_colmeias(request):
return carregar_colmeia(request)
I don't know if it's recommended, but it solved my problem of having to rewrite the same code in multiple views.

Throw Exception When Parameter Missing Django Rest Framework

I am new to Python, Django and the Django Rest Framework - although I am loving the learning curve!
I would like to know what is the standard (most common) way of raising an exception when an API's parameter is not provided ?
Obviously if conditions in the view's body is not the way to go. Are there an decorators that I can pass parameter names to ?
# urls.py
urlpatterns = [
url(r'test', test),
url(r'errand/make', errand.make),
url(r'errand/preview', errand.preview)
]
# views/errand.py
#api_view(['GET'])
#renderer_classes((JSONRenderer, ))
def preview(request):
e = Errand.objects.get(pk=request.GET['errand_id'])
return Response({'data': e.get_preview_data()})
In order for this line
e = Errand.objects.get(pk=request.GET['errand_id'])
To run fine, errand_id needs to be available. How can I check for certain request keys ?
You'll get a TypeError on any function call where a parameter does not have a default value.
As long as you aren't passing in defaults, you'll get an exception, even if the parameter is never used inside the function.
In your example, since you use dict.get, by default if the key is not found it will return None
If you wanted an exception there, you could try directly accessing the key, which would result in a KeyError when it isn't found. Like so:
...
e = Errand.objects.get(pk=request['errand_id'])
...
Otherwise another solution would be to create a schema that represents the desired structure of the request, and validate the request either in the function or using a decorator.
Something like this would be a start:
def errand_id_required(func):
def func_wrapper(request):
if not request.get('errand_id', False):
raise KeyError('errand_id not present in request')
return func(request)
return func_wrapper
#errand_id_required
def preview(request):
e = Errand.objects.get(pk=request.GET['errand_id'])
return Response({'data': e.get_preview_data()})
I would generally only do this if I had a sophisticated way of validating dictionary schemas, otherwise it's very much overkill to write a decorator to check a single key.
You could try the schema library on pypi, and define something like this:
import schema
errand_schema = {
schema.Optional('some_key'): str,
'id': int,
'errand_id': int,
}
Errand = schema.Schema(errand_schema, ignore_extra_keys=True)
and you could use Errand.validate(request) instead of the if.. raise KeyError that I put in the decorator.
But I'll leave that up to you to decide upon...

Pyramid route matching and query parameters

I have a Pyramid web service, and code samples are as follows:
View declaration:
#view_config(route_name="services/Prices/GetByTicker/")
def GET(request):
ticker = request.GET('ticker')
startDate = request.GET('startDate')
endDate = request.GET('endDate')
period = request.GET('period')
Routing:
config.add_route('services/Prices/GetByTicker/', 'services/Prices/GetByTicker/{ticker}/{startDate}/{endDate}/{period}')
Now I know this is all screwed up but I don't know what the convention is for Pyramid. At the moment this works inasmuch as the request gets routed to the view successfully, but then I get a "Dictionary object not callable" exception.
The URL looks horrible:
#root/services/Prices/GetByTicker/ticker=APPL/startDate=19981212/endDate=20121231/period=d
Ideally I would like to be able to use a URL something like:
#root/services/Prices/GetByTicker/?ticker=APPL&startDate=19981212&endDate=20121231&period=d
Any Pyramid bods out there willing to take five minutes to explain what I'm doing wrong?
from you sample code, i think you use the URL Dispatch
so it should be like this
config.add_route('services/Prices/GetByTicker/', 'services/Prices/GetByTicker/')
then the URL like:
#root/services/Prices/GetByTicker/?ticker=APPL&startDate=19981212&endDate=20121231&period=d
will match it
--edit--
you don't have to use a name like "services/Prices/GetByTicker" for route_name,and you can get the GET params use request.params['key']
View declaration:
#view_config(route_name="services_Prices_GetByTicker")
def services_Prices_GetByTicker(request):
ticker = request.params['ticker']
startDate = request.params['startDate']
endDate = request.params['endDate']
period = request.params['period']
Routing:
config.add_route('services_Prices_GetByTicker', 'services/Prices/GetByTicker/')
The query string is turned into the request.GET dictionary. You are using parenthesis to call the dictionary instead of accessing items via the brackets. For a url such as
#root/services/Prices/GetByTicker/?ticker=APPL&startDate=19981212&endDate=20121231&period=d
request.GET['ticker'] # -> 'APPL' or an exception if not available
request.GET.get('ticker') # -> 'APPL' or None if not available
request.GET.get('ticker', 'foo') # -> 'APPL' or 'foo' if not available
request.GET.getall('ticker') # -> ['APPL'] or [] if not available
The last option is useful if you expect ticker to be supplied multiple times.
request.params is a combination of request.GET and request.POST where the latter is a dictionary representing the request's body in a form upload.
Anyway, the answer is that request.GET('ticker') syntactically is not one of the options I mentioned, stop doing it. :-)

Unable to view item in browser based on its key in Python GAE

I'm using python GAE with webapp.
I have a form for a user to create a object in the database, something like:
class SpamRecord(db.Model):
author = db.ReferenceProperty(Author, required=True)
text = db.StringProperty()
After it's created, the user is redirected to a page whose URL contains that object's key... using code such as:
spam = SpamRecord(author=author, text=text)
spam.put()
new_spam_key = spam.key()
self.redirect("/view_spam/%s" % new_spam_key)
And this mostly works, with me being able to view items at:
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQYy8oJDA
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQY_boJDA
However, there's an occasional key that won't work. Here are 2 recent examples of pages that won't load and return HTTP 404 not found errors:
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQY-5MJDA
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQY-boJDA
My html-mappings.py contains the following mapping:
(r"/view_spam/(\w+)", ViewSpamPage)
And the ViewSpamPage looks something like:
class ViewSpamPage(webapp.RequestHandler):
def get(self, spam_id):
self.response.out.write("Got here")
Can anyone offer any insight as to why this is occurring and how it may be prevented?
Thanks very much!
In regular expressions, \w doesn't match hyphens. (It will match underscores.) For that second pair of keys, this'll result in only passing part of the key to your handler.
In your URL pattern, try r"/view_spam/(.*)" instead.

Categories