Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i receive image file in django view from fetch post without using django forms

In this project i am using a different flow approach. I am not using the traditional django forms neither the django templates tags. I am using Vanilla javascript fetch for all data manipulation. All my fecth configuration are okay i have added enctype="multipart/form-data" and {% csrf_token %} to my form and this is my html corresponding the issue at hand:

<input style="cursor: pointer" type="file" placeholder="Aucun Fichier" id="image_upload" value="Choisir Fichier" name="image_upload" class="img_class" />.

My problem now is that i want to upload an image file to my server. For that purpose i have the following code:

//My event listener
submit_btn.addEventListener("click", (event) => {
    event.preventDefault();
    const user = new Users();

    user_image_upload = image_upload.value
    user_image_file_field = image_file_field.files[0]
    ...

    // My object i send to the server
    post_user_info_object = {
        obj_user_image_upload: user_image_upload,
        obj_image_file_field: user_image_file_field,
        ....
    }
}

When i post the form this is my image printed on the javascript console:

My image information appearing as an array of object with only one element: element 0

Next, when it reaches the server this is how it looks like (i'm posting the code first before the image):

@login_required

        
        
def edit_profile(request):
    if request.user.is_authenticated:
        if request.method == 'POST' or request.method == 'FILES':
            data = json.loads(request.body.decode("utf-8"))
            print("Data: ", data)
            raw_image_file = data["obj_image_file_field"]
            print('image file: ', raw_image_file)
            ...

And the following is the image of the console printout showing the result:

My image element is circled in red and is empty, yet it contains value on the javascript side

Here is the code sending to the server:

class Users {
    // Sending user info to server
    async postUserInfo (token, data_elements) {
        const options = {
            method: 'POST',
            body: JSON.stringify(data_elements),
            headers: {
                'Content-type': 'application/json; charset-UTF-8',
                'X-CSRFToken': token
            }
        }

        let result = await fetch ('http://127.0.0.1:8000/accounts/edit-profile/', options);
        let data = await result.json();

        return data;
    }
}

An here is my init code where i run everything:

submit_btn.addEventListener("click", (event) => {
    event.preventDefault();
    const user = new Users();

    user_image_file_field = image_file_field.files[0]

    post_user_info_object = {
        obj_image_file_field: user_image_file_field
    }
    user.postUserInfo(csrftoken, post_user_info_object)
    .then(user => {
        console.log(user)
        window.location.assign('http://127.0.0.1:8000/accounts/edit-profile/')
    })
    .catch(err => console.log(err));
})

I have visited virtually all the ressources talking about uploading images with django via fecth but all of the do so using forms and abstract this particular process i am trying to achieve

Please help me on how exactly i should get that image on the django view side, and also why it is empty on the django side while it has value on the javascript side

like image 779
vially Avatar asked Sep 20 '25 20:09

vially


1 Answers

I have been working on a similar problem and here's how I managed to make it work.

First of all, you should not use JSON object to send files to the server. So this part won't work

body: JSON.stringify(data_elements)

There are several ways to encode an image to be able to send it to the server (like encoding it to base64) but the easiest way that I found is just to use the FormData() object

Here's a snippet of my code

let formData = new FormData()
formData.append('image', e.target.files[0])
formData.append('account', currentAccount.username)

fetch('/api/post/add', {
    method: 'POST',
    body: formData
}).then( response => response.json())
.then( response => {
    console.log(response)
})

You can do async/await instead of promises but you get the idea.

IMPORTANT NOTE: The content type when using FormData is 'Content-Type': 'multipart/form-data' however, you should NOT define ANY content type in this particular request cause it will mess it up. Let the browser define the content type. Why? Read the reason here.

The backend Django part.

Again, we're not dealing with JSON so you can't use

data = json.loads(request.body.decode("utf-8"))

Here's how it should look like:

def add_image(request):
    if request.user.is_authenticated:
        if request.method == 'POST':
            image = request.FILES.get("image")
            account = request.POST.get("account")
like image 182
peanutbutterjelly Avatar answered Sep 22 '25 10:09

peanutbutterjelly