I am trying to test and AJAX view in my Django Project. When submit the post from JQuery the data is correctly accessible in the Django View but when I try to make queries for the Django test client it is emplty.
Here is the code I use:
The view
def add_item(request):
if request.is_ajax() and request.method == 'POST':
post_data = request.POST
print post_data ## <----- THIS IS EMPTY
name = post_data.get('name')
# Render the succes response
json_data = json.dumps({"success":1})
return HttpResponse(json_data, content_type="application/json")
else:
raise Http404
And the test
class TestAddItem(TestCase):
def test_some_test(self):
data = {
'description':"description",
}
response = self.client.post('theurl', data, content_type='application/json')
Any Idea what I might be doing wrong?
I tried also without content type and also using plain url like thurl/?name=name without succes.
Any help will be appreciated.
Olivier
After trying different combinations of parameter formating, content types, etc..
I found one solution that works :
response = self.client.post(reverse('theurl'), data,
**{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'})
And I get the following dictionary on the POST parameters of the request:
<QueryDict: {u'name': [u'name']}>
Edit I love testing :)
Related
Currently I am send a zip file in response from my Django-Rest controller, the zip file will get downloaded in front-end and this feature is working fine but now I want to send some data as well with the zip file in response, is there any way?
This is my Django-REST controller code
response = HttpResponse(byte_io.getvalue(),content_type='application/x-zip-compressed')
response['Content-Disposition'] = f'attachment;filename{my-sample-zip-file}'
return response
How can I send some data with this zip file on front-end?
You can do it with HTTP Request-Response module of django.
Refer: https://docs.djangoproject.com/en/2.2/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment
If you want to do it in production like code, you might also want to handle case where file is not available, set error and return neat. Also, better put that in a common file and then define download_file like below:
from common_library import FileResponse
from django.http import JsonResponse
def download_file( self ):
if self.error_response:
response = JsonResponse( { "error" : self.error_response } )
else:
response = FileResponse(self.report_file_abs_path, self.report_filename)
response['Content-Type'] = 'application/xlsx'
response['Content-Disposition'] = 'attachment; filename=' + self.report_filename
return response
NOTE: FileResponse is a user defined wrapper function which you can define.
In testing Django, the view is returning 200 code but not sending any error message related.
def ajax_view(request):
msg = ''
if request.is_ajax():
username = request.POST['username']
user = User.objects.get(username=username)
msg = 'user exists'
return HttpResponse(msg)
In tests.py
response = self.client.post(reverse('ajax_view'), data={'username': 'hello'})
self.assertEqual(200, response.status_code)
self.assertContains(response, 'exist')
It seems it is not going through the request.is_ajax().. How can I mock the ajax call in Django testing?
The docs on the test client mention this; you need to pass the HTTP_X_REQUESTED_WITH header, which you can do as a keyword argument.
Also, if you pass content_type as 'application/json', Django will automatically serialize to JSON. So:
response = self.client.post(
reverse('ajax_view'),
data={'username': 'hello'},
content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
Not entirely sure this will resolve the entire issue but your method may be expecting the data in a json format:
json_data = json.dumps({'username': 'hello'})
response = self.client.post(reverse('ajax_view'), data=json_data)
The django rest framework forms related fields sometimes leak things I don't want. I want to write a test for it.
I tried this:
class CVRequestAPITests(APITestCase):
def test_disallow_read_access(self):
url = reverse('cvrequest-list')
response = self.client.get(url, headers={
'Accept': 'text/html,application/xhtml+xml'
})
But it still gives JSON.
I want to make valums/file-uploader run with django upload, using it with model fields (FileField)
basic django model:
class Image(models.Model):
user = models.ForeignKey(User)
url = models.FileField(upload_to='%Y/%m/%d')
basic view, working with non ajax upload:
def ajax_upload(request):
if request.method == 'POST':
newfile = Image()
newfile.user = request.user
file_content = ContentFile(request.FILES['file'].read())
file_name = request.FILES['file'].name
newfile.url.save(file_name, file_content)
results = {'url': newfile.url, 'id': newfile.id}
return HttpResponse(json.dumps(results))
raise Http404
The problem is that valums uploader does not put the files in "request" files, it put it in the POST, and django get it as a querydic.
Using it with the top code django says:
"Key 'file' not found in "
If i change:
file_content = ContentFile(request.POST)
django says:
expected read buffer, QueryDict found
I can make it work but i still want to hold on django's native file upload, it's much cleaner.
Use request.body (or request.raw_post_data if older than 1.4)
I am using this
def ajax_create( request ):
if request.is_ajax():
form = SourceForm()
template = 'ajax_form.html'
data = {
'form': form,
}
return render_to_response( template, data,
context_instance = RequestContext( request ) )
I get this error
ajax_create didn't return an HttpResponse object
Are you sure your request is an ajax call ? It doesn't look like it.
Try:
if request.is_ajax():
...
else:
# If the request is not an ajax call, it will return a 400 Error.
return HttpResponseBadRequest()
Perhaps if request.is_ajax(): is returning False, if that's your entire view function?
Typically, you should follow this pattern when making Django view functions:
def my_view(request):
if request.method == 'POST':
form = MyForm(data=request.POST, files=request.FILES)
if form.is_valid():
# do something with form...
else:
initial = {...}
form = MyForm(initial=initial)
context = {'form':form, ...}
return render_to_response('path/to/template.html', context, context_instance=RequestContext(request))
It's not entering to your "if" scope. it returns None
https://docs.djangoproject.com/en/1.3/ref/request-response/#django.http.HttpRequest.is_ajax
Check your ajax call and make sure it returns something in case the request is not ajax