Django response send file as well as some text data - django-rest-framework

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.

Related

drf custom response to override Response()

I'm using DRF and to return response, I used Response() which located at from rest_framework.response import Response
To make custom response, first, I copied all of the source to custom file.
And in my views, I changed Response() to my own file.
But when I running django server and access via web, it through errors.
AssertionError: .accepted_renderer not set on Response
I just copied original Repsonse() and re-use it.
Why it occur errors?
Purpose of custom response is I want to add more argument that something likes cursor for pagination.
As you know that in original Response, takes 6 arguments.
def __init__(self, data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None):
And return it in def rendered_content(self), line of ret = renderer.render(self.data, accepted_media_type, context)
So my scenario is, add cursor to __init__ and pass through it to renderer.render().
Any problem with my way?
Thanks.

Django testing - test the view which handles an ajax call

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)

Scrapy check if image response is 404

I want to process image URLs, I enabled and configured as Scrapy Docs; but what happens if the image URL returns 404 or is redirected. I want to log that, save the failed URLs and the HTTP error/redirect code. Where can I put the code to do that?
It is completely wrong to handle that in the pipleline, because the response would go throw all the middlewares back to your spider then to your pipleline, while your purpose is just logging the failure.
You should build your own middleware to handle any HTTP response code.
By default, scrapy allows responses with statues codes between 200 and 300. You can edit that by listing the statue codes that you would like to receive like this:
class Yourspider(spider):
handle_httpstatus_list = [404, 302] #add any other code you need
Then you should build your middleware and add it to your configuration like this:
DOWNLOADER_MIDDLEWARES = {
'myProject.myMiddlewares.CustomSpiderMiddleware': SELECT_NUMBER_SUITS_FOR_YOU,
}
in your CustomSpiderMiddleware check the status like this:
process_spider_input(response, spider):
if response.status == 404
#do what ever you want
You have to create your custom pipeline, inherit it from the Imagepipeline, then override the item_completed method, as mentioned in the documentation
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item['image_paths'] = image_paths
return item
and lastly in the settings.py add your custom pipeline
ITEM_PIPELINES = {
'myproject.mypipeline': 100,
}

Django POST data dictionary is empty when posting from test client

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 :)

how can i make django file upload work with valums/file-uploader

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)

Resources