How to send Image to to Rest API using json - django-rest-framework

I am getting an image from a form and sending it to rest api using requests modules which I want to save later in the models. but the issue is I am getting the image from form but when It reached the API it is autmatically a string and I dont know how to get that image in the API.
image.py (here I am getting the image in the image variable
image_file= request.FILES.get('image')
if request.method == "POST":
headers={"Content-Type": 'multipart/form-data','Authorization': 'Token {}'.format(token) }
url = f"http://127.0.0.1:8000/api/pay-committee/"
data = {
"mem_id": 4,
"payment_proof" :image_file
}
response = post_url(url,request,data)
here I am getting the image but when I check the type it is not the image instead it is only string name
def post(request):
payment_proof = (request.data['payment_proof'])

Related

Cannot send HTML string through axios

I'm working on a blog like website and have being adding this rich text editor feature to it. This app is built with Vue for the front and Laravel, and this text editor is a dependency called vue-quill.
I use axios to post all the data and nothing more. Im using it to create posts with Raw html tags from this editor, it actually works fine creating and updating posts locally, but only fails on my server whenever you try to update any post, it returns empty response and status 200.
It does not happen when you create a post. Im not using any kind of image upload service but I'm using my own solution, which consists on transforming images from base 64 to file objects and then send them to a controller via axios. On update action it is similar but the images that were already uploaded on the post are fetched, then converted to base64 again and then converted to file objects again (in order to preserve previous images) for new images I convert them from base64 to file object as I do on my create action.
Here is the code I use to create from base 64 to file object :
dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
And this would be my axios action:
axios
.post("/api/posts", formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response)=>{
this.submit = false;
this.title= '';
this.showAlert("success", 'Post created successfully.' , '')
})
.catch((error) =>{
// etc
});
The formData object only store the raw html, images and a string, nothing more than that, but I'm not sure if the headers of the axios are ok, the laravel action is like this:
public function updatePost(Request $request)
{
$request->validate([
'files.*' => 'required|mimes:jpg,jpeg,png|max:2048'
]);
$post = Post::find($request->postId);
$images = $request->file('files');
// creamos el post primero
$post->title = $request->title;
$post->body = $request->body;
$post->save();
// the rest of the code for storing images
return response()->json(['post' => $post]);
I think something is preventing it to reach to this action, because the response is empty.
Edit: I had a problem later where the request was giving status 301, after searching here and there I found out that everything was okay but in the server. The host has to be configured as stated here in this quick guide for 301 troubles : https://medium.com/#mshanak/laravel-return-empty-response-690f8a308d9a.

Django response send file as well as some text data

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.

How to do AJAX in Django CMS Admin

I have 2 models in Django CMS - a Map (which has name and an image attributes), and a Location, which one of it's attributes is a Map. I want, when the user changes the Map, to perform an AJAX request to get the map details for that item so that I can add the Map image to the page to do some further jQuery processing with it. But I'm new to Django and I can't seem to figure it out. Anything I find seems unrelated - in that it talks about using AJAX on front end forms.
I have my jQuery file ready to go but I don't know what to put for the URL of the AJAX call and how/where to set up the endpoint in Django.
Your question seem related to custom Django admin url.
First, update your MapAdmin to provide an endpoint to search location
from django.contrib import admin
from django.http import JsonResponse
class MapAdmin(admin.ModelAdmin):
def get_urls(self):
admin_view = self.admin_site.admin_view
info = self.model._meta.app_label, self.model._meta.model_name
urls = [
url(r'^search_location$', admin_view(self.search_location), name=("%s_%s_search_location" % (info))),
]
return urls + super(VideoAdmin, self).get_urls()
def search_location(self, request, *args, **kwargs):
map = request.GET.get('map')
# Do something with map param to get location.
# Set safe=False if location_data is an array.
return JsonResponse(["""..location_data"""], safe=False)
Next, somewhere in your template file, define the URL point to search location endpoint. And use that URL to fetch location data
once map is changed.
var searchLocationUrl = "{% url 'admin:appName_mapModel_search_location' %}";

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