How to correctly use get and post tests? - django-rest-framework

There get and post test:
def test_post_product(self):
data = {
'title': 'Chicken Breast',
'proteins': 24.00,
'carbs': 0.00,
'fats': 3.00,
'calories': 113
}
response = self.client.post(reverse('product-list'), data=json.dumps(data), content_type='application/json')
self.assertEqual(HTTP_201_CREATED, response.status_code)
url = reverse('product-detail', kwargs={'pk':1})
response = self.client.get(url)
self.assertEqual(HTTP_200_OK, response.status_code)
self.assertEqual(ProductSerializer(data).data, response.data)
But in the line self.assertEqual(HTTP_200_OK, response.status_code) I have 404 status code.
In the similar test with only get requests all work fine:
def test_get_product(self):
product1 = Product.objects.create(title='Chicken Breast',proteins=24.00,carbs=0.00,fats=3.00,calories=113)
product2 = Product.objects.create(title='Tomatoes', proteins=0.90,carbs=3.90,fats=0.20, calories=18)
url = reverse('product-list')
response = self.client.get(url)
self.assertEqual(HTTP_200_OK, response.status_code)
self.assertEqual(ProductSerializer([product1, product2], many=True).data, response.data)
url = reverse('product-detail', kwargs={'pk':1})
response = self.client.get(url)
self.assertEqual(HTTP_200_OK, response.status_code)
self.assertEqual(ProductSerializer(product1).data, response.data)
What i do not correctly?

Related

Passing pk in a get request function

I am new to Django so I figure this question could be a bit stupid.I have an api endpoint that returns a list of Doctors(and their details) and another that returns one doctor(and his details)-this is the call am trying to make.I think the issue I am having is with how to ref the pk in the request url.
As it is, when I test on postman I get the error {
"errors": "JSONDecodeError('Expecting value: line 1 column 1 (char 0)',)",
"status": "error"
}
I am almost certain the issue is in api_services.py.I really hope someone can just point it out to me.
views.py
`class FinanceDoctorsView(GenericAPIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
#classmethod
#encryption_check
def get(self, request, *args, **kwargs):
response = {}
pk = kwargs.get("pk")
try:
result = {}
auth = cc_authenticate()
res = getDoctorInfo(auth["key"], pk)
result = res
return Response(result, status=status.HTTP_200_OK)
except Exception as e:
error = getattr(e, "message", repr(e))
result["errors"] = error
result["status"] = "error"
return Response(result, status=status.HTTP_400_BAD_REQUEST)`
api_services.py
import requests
def getDoctorInfo(auth, params):
print("getting doctorInfo from Callcenter")
try:
headers = {
"Authorization": f'Token {auth}'
}
url = f'{CC_URL}/finance/doctor-info/<int:pk>'
res = requests.get(url, headers=headers)
print("returning doctorInfo response", res.status_code)
return res.json()
except ConnectionError as err:
print("connection exception occurred")
print(err)
return err
urls.py
path(
"doctor-info/<int:pk>", views.FinanceDoctorsView.as_view(), name="doctor_info"
),
I think in the api service file, you have made a typo
url = f'{CC_URL}/finance/doctor-info/<int:pk>'
Should had be
# as in the function you have defined params,
# and I think it could have been renamed as pk
url = f'{CC_URL}/finance/doctor-info/{params}'

Unhandled Rejection (TypeError): Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body

Unhandled Rejection (TypeError): Failed to execute 'fetch' on
'Window': Request with GET/HEAD method cannot have body.
Getting the above error.
export const checkMobile = mobile => {
return ajax(`/mobiles/search`, { method: "GET", body: mobile });
};
function ajax(uri, options = {}) {
const defaultOptions = getDefaultOptions();
options.method = options.method ? options.method : defaultOptions.method;
if (!options.formType) {
options.headers = options.headers
? options.headers
: defaultOptions.headers;
}
options.credentials = options.credentials
? options.credentials
: defaultOptions.credentials;
if (options.body && !options.formType) {
options.body = buildParam(options.body);
}
uri = uri.startsWith("/") ? uri : "/" + uri;
console.log(`${CLIENT_URL}${uri}`);
return fetch(`${CLIENT_URL}${uri}`, options).then(data => data.json());
}
Why I have not been allowed to add body data. Now how will I pass the data to the back end. I am using react in front end.
Check your options object and ensure body is undefined if you're using GET.
GET requests should not be posting any data in the body. If you plan on sending data, you probably want to use POST as the method.

POST request not behaving as intended

I've been trying to get my button to send a POST request to the submitted URL, which does a write back to the database. The application looks like the POST request gets sent, but after hitting the button my URL never changes and the print at the submitted URL appears to be an empty set.
This is my jquery/ajax call for the button:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<button class="btn btn-primary my_select" type="submit">Request Access</button>
<script>
$(document).ready(function () {
$('form').on('submit', function (e) {
e.preventDefault();
var phi = $('#phi').val();
var accesslevelid = $('#accesslevelid').val();
$.ajax({
url: "{% url 'submitted' %}",
headers: { 'X-CSRFToken': '{{ csrf_token }}' },
data: {
phi: phi,
accesslevelid: accesslevelid,
},
type: 'POST',
success: function (result) {
// do something with result
},
});
});
});
</script>
I'm expecting my POST of the Application List, PHI flag, and Access Level gets sent as a POST to my submitted URL. My view for submitted is the following:
def submitted(request):
owner = User.objects.get (formattedusername=request.user.formattedusername)
checkedlist = request.POST.getlist('report_id')
coid = User.objects.filter(coid = request.user.coid).filter(formattedusername=request.user.formattedusername)
facilitycfo = QvDatareducecfo.objects.filter(dr_code__exact = coid, active = 1, cfo_type = 1).values_list('cfo_ntname', flat = True)
divisioncfo = QvDatareducecfo.objects.filter(dr_code__exact = coid, active = 1, cfo_type = 2).values_list('cfo_ntname', flat = True)
print (f"checkedlist prior to post:{checkedlist}")
selectedaccesslevel = request.POST.get('accesslevelid')
selectedphi = request.POST.get('phi')
if request.method == 'POST':
for i in checkedlist:
requestsave = QVFormAccessRequest(ntname = owner.formattedusername, first_name = owner.first_name, last_name = owner.last_name, coid = owner.coid, facility = owner.facility, title = owner.title
,report_id = i, accesslevel_id = selectedaccesslevel, phi = selectedphi , access_beg_date = '2017-01-01 00:00:00', access_end_date = '2017-01-31 00:00:00')
requestsave.save()
print (f"postlist:{checkedlist}")
print (f"accesslevel:{selectedaccesslevel}")
print (f"phi:{selectedphi}")
return JsonResponse({'is_success':True})
My post looks like it occurs when I press my button:
[]
[12/Dec/2017 08:54:45] "POST /account/submitted/ HTTP/1.1" 200 1149
However, the URL doesn't switch to submitted. My list for checkedlist appears to be an empty set. When visiting submitted and having my print statements occur, i get nothing like the POST never occurred.
My form action is the following:
<form action = "{% url 'submitted' %}" form method = "POST">
{% csrf_token %}
{{ form.as_p}}
ajax is build to do background client server operation or load part of the page dynamic to avaid heavy requests
Example
most of social medias feeds use ajax. when you scroll the view a ajax request is send to server to retrieve the next feed .
in your case the data is posted to server successfully. but change the URL is not available by server at this point but you can do this with a trick ...
in your view.py file
from django.http import JsonResponse
if request.method == 'POST':
for i in checkedlist:
requestsave = QVFormAccessRequest(ntname = owner.formattedusername, first_name = owner.first_name, last_name = owner.last_name, coid = owner.coid, facility = owner.facility, title = owner.title
,report_id = i, accesslevel_id = selectedaccesslevel, phi = selectedphi , access_beg_date = '2017-01-01 00:00:00', access_end_date = '2017-01-31 00:00:00')
requestsave.save()
print (checkedlist)
print(selectedaccesslevel)
print(selectedphi)
return JsonResponse({'is_sucess':True})
this JsonResponse object will send back the data ajax.
success: function (result) {
if(result.is_sucess){
document.location = 'you url to direct page at' //
}
},
this job can be done using direct post to url and then redirecting to other url i. will leave this for now

Django returning status code 400 with error message from view

I have a view that receives a form submit request via ajax. Sometimes it returns bad request based on certain criteria or in case an exception is raised. Now, sending back simple HttpResponse(status=400) is plain simple. Can I send a reason along with it a reason that I can access using xhr.responseText?
If I understand you right, you can return 400 with some context:
context = {
'reason': 'your reason'
}
response = render(request, '400.html', context)
response.status_code = 400
return response
and for cases with ajax, you just return HttpResponse:
context = {
'status': '400', 'reason': 'you can access this view only via ajax'
}
response = HttpResponse(json.dumps(context), content_type='application/json')
response.status_code = 400
return response
and in your js code:
$.ajax({
// ...
// ...
}).fail(function(data){
var status = data.status;
var reason = data.reason;
});

Django view with cross-domain Ajax

I have a Django view that I want to integrate with an Ajax call. The call is happening cross domain. I have this code running by itself and making the request cross-domain.
def myview(_request):
response = HttpResponse(json.dumps({"key": "value", "key2": "value"}))
response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
response["Access-Control-Max-Age"] = "1000"
response["Access-Control-Allow-Headers"] = "*"
return response
I am wondering how to integrate this into my existing view. You will see what I have tried in the code below:
def american_time(request):
#Calling the HTML Source from the URL
sock = urllib.urlopen("http://apps.cbp.gov/bwt/index.asp")
htmlSource = sock.read()
sock.close()
#create a soup object
soup = BeautifulSoup(htmlSource)
#find the tags we need and their content
bridge = soup.findAll('td', limit=215)[194]
tunnel = soup.findAll('td', limit=250)[208]
#new variables to be passed
contents_of_tunnel = tunnel.getText(', ')
contents_of_bridge = bridge.getText(', ')
#check to see if there is a delay for the bridge
if 'no delay' in contents_of_bridge:
time_to_cross_the_bridge = 0
else:
inside_of_bridge = re.split(r', ', contents_of_bridge)
number_inside_of_bridge = inside_of_bridge[1]
list_for_time_to_cross_the_bridge = re.findall(r"\d+", number_inside_of_bridge)
time_to_cross_the_bridge = list_for_time_to_cross_the_bridge[0]
if 'no delay' in contents_of_tunnel:
time_to_cross_the_tunnel = 0
else:
inside_of_tunnel = re.split(r', ', contents_of_tunnel)
number_inside_of_tunnel = inside_of_tunnel[1]
list_for_time_to_cross_the_tunnel = re.findall(r"\d+", number_inside_of_tunnel)
time_to_cross_the_tunnel = list_for_time_to_cross_the_tunnel[0]
response = HttpResponse(json.dumps({"bridge_time": time_to_cross_the_bridge, "tunnel_time": time_to_cross_the_tunnel}))
response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
response["Access-Control-Max-Age"] = "1000"
response["Access-Control-Allow-Headers"] = "*"
#finally, return as Ajax
return HttpResponse(response)
AJAX:
$.get( "http://localhost:8000/us", function(json){
$('#timeone').html(json.bridge_time + "min delay");
$('#timetwo').html(json.tunnel_time + "min delay");
})
.fail(function(){
alert('We can\'t get data right now! Please try again later.');
})
.done(function(){
alert('Success!');
});
However, I am still getting the message XMLHttpRequest cannot load http://localhost:8000/us. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. in the console. How can I integrate this header into my view?
Try add this middleware.
How to add see documentation https://docs.djangoproject.com/en/dev/topics/http/middleware/

Resources