Problem with media and media_root

I’ve strange behavior on my current project (media and media_root folders) didn’t create and also the image path is strange it is like(“C:\fakepath\v6 wallpaper.jpg”), but it saved successfully to database …
I’ve many forms saved together at the same time … I tried many things to fix this issue but I failed I know that I miss something but I don’t know what is it?,
I tried one of my old projects that I developed on Windows OS to compare if I miss something but it is the same except in my old project I save (one image at once) but in my current project (I save list of images at once) also I use AJAX here but on my old project I haven’t used it .
I tried to save and upload images to its database (it works normally) I removed the (media_root folder) and it creates itself again normally .
Here are lines of my code on my current project
MY MODELS

def get_filename_ext(filepath):
    base_name = os.path.basename(filepath)
    name, ext = os.path.splitext(base_name)
    return name, ext


def photo_path(instance, filename):
    file_name, ext = get_filename_ext(filename)
    file_ext = "{ext}".format(ext=ext)
    pro_id = str(instance.product_id)
    code = str(instance.photo_code)

    image_path = "images/{0}/{1}{2}".format(
        pro_id, (code[:7] + "_"), file_ext
    )
    return image_path


class ProductImage(models.Model):
    photo = ImageField(
        upload_to=photo_path,
    )

    product = models.ForeignKey(
        "products.Product", 
        related_name="%(app_label)s_%(class)s_product", 
        on_delete=models.CASCADE, 
    )
    photo_code = models.UUIDField(
        primary_key=False,
        default=uuid.uuid4,
        editable=False,
        unique=True,
    )

    def __str__(self):
        return f"{self.product}"

    class Meta:
        app_label = "products"
        verbose_name = "product_image"
        verbose_name_plural = "Product_Images"

MY FORMS.py

class ProductImageForm(forms.ModelForm):
    class Meta:
        model = ProductImage
        fields = [
            'photo',
        ]

    def __init__(self, *args, **kwargs):
        super(ProductImageForm, self).__init__(*args, **kwargs)
        self.fields['photo'] = forms.ImageField(
            required=False, widget=forms.ClearableFileInput()
        )

MY VIEWS.py

       form = ProductForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="pro", 
            initial=pro_data
        )
        price_form = ProductPriceForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="price",
            initial={'essential_unit':''}
        )
        extension_form = ProductExtensionForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="extension"
        )
        cat_form = ProductCategoryForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="cat"
        )
        
        uom_form = UOMForm(
            request.POST or None, 
            request.FILES or None,
            prefix="uom", 
            initial={
                'unit': UnitNames.objects.first(),
                'value': 0,
                "uom_unit": UnitNames.objects.first(),
                "main_uom": False,
                'uom_options': choices.UNITS[0][0],
                'uom_value': 0,
                'unit_price': 0.0,
            }
        )
        img_form = ProductImageForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="img"
        )

     images_list = request.POST.getlist("images-list[]")   # from ajax request

    if img_form.is_valid():
            # for obj in img_form:
            # img_save_form = img_form.save(commit=False)
            # img_save_form.product_id = save_form.id
            # img_save_form.save()
            product_image = [
                ProductImage.objects.create(
                    product_id=save_form.id,
                    photo=obj,
                ) for obj in images_list
            ]

The result of printing

print(
       'IMAGES-LIST: ', images_list,
      'IMG-CLEANED_DATA:: ', img_form.cleaned_data,
      'IMG-FORM-VALIDITY: ', img_form.is_valid(),
)

IMAGES-LIST:  ['C:\\fakepath\\berger.jpeg', 'C:\\fakepath\\pepsi.jpeg'] 
IMG-CLEANED_DATA::  {'photo': None}
IMG-FORM-VALIDITY:  True

Ajax file

let imageValues = $('.image-value').map(function() {
                return $(this).val();
            }).get();
data :{
     // for image form
     'img-photo': $('#id_img-photo').val(),
      'images-list': imageValues,

}

Any suggestions …

I think we’d need to see the rest of the page and JavaScript that you are running here. I don’t see enough yet to begin to diagnose this, and it’s not really clear to me exactly what you’re trying to do.

If you’re attempting to upload files and not just file names, see File Uploads | Django documentation | Django for details as to how Django expects to see uploaded file data. What was helpful for me to learn how it works was to create a very simple example of a file upload, and then look at the data being posted in the browsers developer tools as well as looking what was received by Django in the request object. (request.POST and request.FILES)

If you’re doing the file uploads using AJAX, you could also consider creating a JSON object with the file data to submit.

views add_product() function

def add_product(request):
    data = {}
    data['pro_id'] = None 
    data['error'] = 'ERROR !!!'
    data['type'] = 'error'
    products = Product.objects.values_list('name', flat=True)
    unit_names = (
        UnitNames.objects.select_related("user").filter(is_deleted=False).only()
    )
    
    #* An important info here without (request.is_ajax()) no message appears as toast message
    if request.accepts('text/html') and request.method == "POST":
        pos_station = request.POST.get('pos_station')#: $('#id_pro-pos_station option:selected').val(),
        pro_data = {
            'expire_ref': choices.DAY,
            'hint_ref': choices.DAY,
            # 'pos_station': PosStation.objects.get(name=pos),
        }

        form = ProductForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="pro", 
            initial=pro_data
        )
        price_form = ProductPriceForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="price",
            initial={'essential_unit':''}
        )
        extension_form = ProductExtensionForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="extension"
        )
        cat_form = ProductCategoryForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="cat"
        )
        
        #* unit conversions
        conv_form = UnitConversionsForm(request.POST or None)
    
        uom_form = UOMForm(
            request.POST or None, 
            request.FILES or None,
            prefix="uom", 
            initial={
                'unit': UnitNames.objects.first(),
                'value': 0,
                "uom_unit": UnitNames.objects.first(),
                "main_uom": False,
                'uom_options': choices.UNITS[0][0],
                'uom_value': 0,
                'unit_price': 0.0,
            }
        )
        img_form = ProductImageForm(
            request.POST or None, 
            request.FILES or None, 
            prefix="img"
        )
        
        branch = request.POST.get('pro-branch')
        pos = request.POST.get('pro-pos_station')

        #* The next line give a right list from ajax request
        unit_list = request.POST.getlist("unit-list[]")
        option_list = request.POST.getlist("option-list[]")
        value_list = request.POST.getlist("value-list[]")
        uom_value_list = request.POST.getlist('uom-value-list[]')
        unit_label_list = request.POST.getlist("unit-label-list[]")
        unit_price_list = request.POST.getlist("unit-price-list[]")
        
        #* 
        cat_main = request.POST.get('cat-main')
        cat_parent = request.POST.get('cat-parent') 
        cat_child = request.POST.get('cat-child')
        
        #* 
        switch_price = request.POST.get('price-switch_price')
        origin_price = request.POST.get('price-origin_price')
        purchasing_price = request.POST.get('price-purchasing_price')
        price_value = request.POST.get('price-value')
        price_percentage = request.POST.get('price-percentage')

        images_list = request.POST.getlist("images-list[]")

        print(
            'IMAGE-PHOTO: ' , request.FILES.getlist('images-list[]'),
            'OUR-OBJ::: ', [obj for obj in request.FILES.getlist('img-photo',[])]
        )
        for pf in (img_form):
            print(
                'PRODUCT-IMAGE-FORM FIELDS: ', 
                pf.name, pf.errors,
                # 'UNIT-FORM FIELDS: ', uf.name, uf.errors,
            )
        for pf in (cat_form):
            print(
                'PRODUCT-CAT-FORM FIELDS: ', 
                pf.name, pf.errors,
                # 'UNIT-FORM FIELDS: ', uf.name, uf.errors,
            )
        for pf in (price_form):
            print(
                'PRODUCT-PRICE-FORM FIELDS: ', 
                pf.name, pf.errors,
                # 'UNIT-FORM FIELDS: ', uf.name, uf.errors,
            )
        for pf in (uom_form):
            print(
                'PRODUCT-UOM-FORM FIELDS: ', 
                pf.name, pf.errors,
            )
        print(
            'CATEGORY-FORM-FIELDS:::', cat_main, 
            cat_parent, cat_child,
            'purchasing_price::', purchasing_price,
            'origin_price::', origin_price,
            'price_value::', price_value,
            'price_percentage::', price_percentage,
            'switch_price:: ', switch_price,

            'unit_list: ', unit_list,       
            'option_list: ', option_list,
            'value_list: ', value_list,
            'unit_label_list: ', unit_label_list,
            'unit_price_list: ', unit_price_list,
            'UOM-FORM-VALIDITY: ', uom_form.is_valid(),
            'IMG-FORM-VALIDITY: ', img_form.is_valid(),
            # 'PRODUCT-FORM: ', form.is_valid(),
            # 'POS_STATION: ', pos, 'AJAX-VAR: ',pos_station,
            # 'BRANCH: ', branch,
            'UOM-CLEANED_DATA:: ',uom_form.cleaned_data,
            'IMAGES-LIST: ', images_list,
            'IMG-CLEANED_DATA:: ', img_form.cleaned_data,
            # uom_form.cleaned_data,
        )

        pro_name = request.POST.get("pro-name")
        pro_name_ar = request.POST.get("pro-name_ar")
        # print("UNIT-CHECK: ", unit_check, "UNIT: ", unit, value)
        match_name = Product.objects.filter(name=pro_name).exists()
        match_name_ar = Product.objects.filter(name=pro_name_ar).exists()

        #* checking for important information first 
        if cat_main == '' or cat_main == None:
            data['pro_id'] = None 
            data['error'] = 'Main category must not be empty,'
            data['type'] = 'info'
            return JsonResponse(data)
        
        #* check for UOM form
        check_option_list = [True for obj in option_list if obj == 'main']
        if option_list == [] or unit_list == [] or value_list == []:
            data['pro_id'] = None 
            data['error'] = 'Enter UOM data please ...'
            data['type'] = 'info'
            return JsonResponse(data)
        
        check_value_list = [
            True for i in value_list 
                if (i.startswith('-')) or (Decimal(i).is_zero())
        ]
        # zero_in_value_list = [True for i in value_list if int(Decimal(i)) == 0]
        # or Decimal(i).is_zero()
        print('check_value_list', check_value_list)
        if True in check_value_list: # or True in check_value_list:
            data['pro_id'] = None 
            data['error'] = 'Unit values must not be negative or zero...'
            data['type'] = 'info'
            return JsonResponse(data)
        
        if not match_name: # and not match_name_ar 
            save_form = None # form.save(commit=False)
            save_uom_form = None #uom_form.save
            save_price_form = None # price_form.save
        else:
            data['pro_id'] = None 
            data['error'] = 'Product Name is already exists, Try to change the product name '
            data['type'] = 'error'
            return JsonResponse(data)
        
        #* product form 
        if form.is_valid():
            save_form = form.save(commit=False)
            save_form.user = request.user
            save_form.updated_user = request.user
            save_form.pos_station = pos_station 
            save_form.save()
        elif not form.is_valid():
            data['pro_id'] = None 
            data['error'] = 'Product form is not valid, There are some fields need to be filled'
            data['type'] = 'error'
            form = ProductForm(
                request.POST or None,
                prefix="pro"
            )
            
            return JsonResponse(data)
            
        if cat_form.is_valid():
            main_cat = cat_form.cleaned_data['main']
            parent_cat = cat_form.cleaned_data['parent']
            child_cat = cat_form.cleaned_data['child']
            cat_save_form = cat_form.save(commit=False) 
            cat_save_form.product_id = save_form.id

            cat_save_form.save() 
            
        else:
            print('Product Category Form is invalid')
            data['pro_id'] = None 
            msg = [
                (key, value[0]['message']) for key, value in (
                    cat_form.errors.get_json_data().items()
                )
            ]
            data['error'] = msg
            data['type'] = 'info'
            form = ProductCategoryForm(request.POST or None, prefix="cat")
            return JsonResponse(data)

        if price_form.is_valid():
            save_price_form = price_form.save(commit=False)
            save_price_form.product_id = save_form.id
            save_price_form.save()
        elif not price_form.is_valid():
            data['pro_id'] = None 
            msg = [
                (key, value[0]['message']) for key, value in (
                    price_form.errors.get_json_data().items()
                )
            ]
            data['error'] = msg
            # data['error'] = 'Product price form is not valid, There are some fields need to be filled'
            data['type'] = 'info'
            form = ProductPriceForm(request.POST or None, prefix="price")
            return JsonResponse(data)

        if uom_form.is_valid():
            print('UOM-CLEANED-DATA: ', [obj for obj in uom_form.cleaned_data])
            #* the next code for saving model with multiple rows 
            uom = [
                UOM.objects.create(
                    product_id=save_form.id,
                    uom_options= opt,
                    main_uom=True if opt == 'main' else False,
                    unit_id= int(un),
                    value= int(Decimal(val)),
                    uom_value=int(Decimal(uom_val)),
                    uom_unit=uom_unit,
                    unit_price=price
                ) for opt, un, val, uom_val, uom_unit, price in zip(
                        option_list, unit_list, value_list,
                        uom_value_list, unit_label_list, unit_price_list
                    )
            ]

        print('IMAGE-FORM-VALIDITY: ', 
            [obj for obj in img_form.cleaned_data ],
            'IMAGE-FORM-CLEANED-DATA-AFTER-THUMBNAIL::: ', img_form.cleaned_data
        )
        if img_form.is_valid():
            
            product_image = [
                ProductImage.objects.create(
                    product_id=save_form.id,
                    photo=obj,
                ) for obj in images_list
            ]
            print("Image form is valid and saving done....",
                request.FILES.get('img-photo'),
                [obj for obj in img_form.cleaned_data ] 
            )
        
        # print("Image-FIELDS", )
        #* important note here we are in the (not match_name) case 
        #* toast message will appear after all forms validity checks
        data['pro_id'] = save_form.id 
        data['error'] = 'Product "%s" saved successfully ...' % save_form.name
        data['type'] = 'success'
        return JsonResponse(data)

    else:
        form = ProductForm(prefix="pro")
        cat_form = ProductCategoryForm(prefix="cat")
        price_form = ProductPriceForm(prefix="price")
        extension_form = ProductExtensionForm(prefix="extension")
        uom_form = UOMForm(prefix="uom")
        img_form = ProductImageForm(prefix="img")
        # inv_form = InventoryForm(prefix='inv')

    context = {
        "form": form,
        "cat_form": cat_form,
        "uom_form": uom_form,
        "price_form": price_form,
        "img_form": img_form,
        "extension_form": extension_form,

        'products': products,

        "unit_names": unit_names,
        'title': 'Create Product',
    }
    return render(request, "products/add_product.html", context)

add_product.html

{% extends 'base.html' %}

{% load static %}
{% load i18n %}
{% load widget_tweaks %}

{% block content %}

{% url 'products:add_product' as add_product_url %}

<form method="post" enctype="multipart/form-data" class="product-form" id="product-form"> <!--novalidate-->
    {% csrf_token %}
    {% include 'products/includes/buttons/div_buttons.html' %}

    <section class="content">
        <div class="container-fluid">
            <div class="row">

                <!-- Starting our template tab scenario -->
                <div class="col-md-12">
                    <div class="card">
                        <!-- Buttons -->
                        
                        {% include 'products/includes/buttons/tabs_buttons.html' %}
                        
                        <div class="card-body">
                            <div class="tab-content">
                                
                                <!-- Product Tab -->
                                <div class="active tab-pane fade show clearfix" id="product-tab" role="tabpanel" aria-labelledby="product-tab">
                                    <!-- <input type="hidden" name="product" value="product"> -->
                                    {% include 'products/includes/product/add_product.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Category Tab -->
                                <div class="tab-pane fade show clearfix" id="category-tab" v-if="hideCategory" role="tabpanel" aria-labelledby="category-tab">
                                {% include 'products/includes/category/add_category.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Unit TAb -->
                                <div class="tab-pane fade show clearfix" id="unit-tab" v-if="hideUnit" role="tabpanel" aria-labelledby="unit-tab">
                                    {% include 'products/includes/units/add_uom.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Image Tab -->
                                <div class="tab-pane fade show clearfix" id="image-tab" v-if="hideImage" role="tabpanel" aria-labelledby="image-tab">
                                    {% include 'products/includes/images/add_images.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Settings Tab -->
                                <div class="tab-pane fade show clearfix" id="settings-tab" v-if="hideSettings" role="tabpanel" aria-labelledby="settings-tab">
                                    {% include 'products/includes/settings/add_settings.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Price Tab -->
                                <div class="tab-pane fade show clearfix" id="price-tab" v-if="hidePrice" role="tabpanel" aria-labelledby="price-tab">
                                    {% include 'products/includes/price/add_price.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Vendors Tab -->
                                <div class="tab-pane fade show clearfix" id="vendors-tab" v-if="hideVendors" role="tabpanel" aria-labelledby="vendors-tab">
                                    {% include 'products/includes/vendors/add_vendors.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Vendors Tab -->
                                <div class="tab-pane fade show clearfix" id="manufacture-tab" v-if="hideManufacture" role="tabpanel" aria-labelledby="manufacture-tab">
                                    {% include 'products/includes/manufacture/add_manufacture.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Vendors Tab -->
                                <div class="tab-pane fade show clearfix" id="substitution-tab" v-if="hideSubstitution" role="tabpanel" aria-labelledby="substitution-tab">
                                    {% include 'products/includes/substitution/add_substitution.html' %}
                                </div>
                                <!-- /.tab-pane -->

                                <!-- Adding Tab -->
                                <div class="tab-pane fade show clearfix" id="adding-tab" v-if="hideProduct = true" role="tabpanel" aria-labelledby="adding-tab">
                                    {% include 'products/includes/product/add_product.html' %}
                                </div>
                                <!-- /.tab-pane -->

                            </div>
                            <!-- /.tab-content -->
                        </div>
                        <!-- /.card-body -->

                    </div>
                    <!-- /.card -->

                </div>
                <!-- /.col -->          

            </div>
        </div>
    </section>
</form>
<!-- /.form -->

{% endblock content %}
    

{% block javascripts %}


{% include 'products/includes/product/js.html' %}

{% include 'products/includes/images/js.html' %}


{% include 'products/includes/vueJs.html' %}
{% include 'products/includes/js.html' %}

{% endblock javascripts %}

add_images.html

{% load thumbnail %}

{% load widget_tweaks %}
{% load i18n %}

<!-- Post -->
<div class="post" v-if="hideImage">
    <div class="row">

        <div class="col-md-4">
            <h4 class="">Add Images </h4>
        </div>

    </div>
    {% if add_product_url %}
        <div class="row img-row">
            <div class="col-lg-8">
                <div class="form-group">
                    <div class="input-group input-group-sm">
                        <div class="input-group-prepend">
                            <span class="input-group-text">
                                <i class="fas fa-image"></i>
                            </span>
                        </div>
                        {% render_field img_form.photo class="form-control form-control-sm image-value" %}  
                    </div> 
                </div>
            </div>
            
            <div class="col-lg-1">
                <div class="control ">
                    <button 
                        type="button"
                        id="img_minus"
                        class="btn btn-sm btn-block btn-outline-danger img-minus"
                        style="margin-bottom: 20px;"
                    >
                        <span class="fas fa-trash"></span>
                    </button>
                </div>
            </div>
            <div class="col-lg-1">
                <div class="control ">
                    <button 
                        type="button"
                        id="img_broom"
                        class="btn btn-sm btn-block btn-outline-secondary img-broom"
                        style="margin-bottom: 20px;"
                    >
                        <span class="fas fa-broom"></span>
                    </button>
                </div>
            </div>
            
        </div>
    {% else %}
        {% for obj in img_form %}
        <div class="row img-row">
            <div class="col-lg-8">
                <div class="form-group">
                    <div class="input-group input-group-sm">
                        <div class="input-group-prepend">
                            <span class="input-group-text">
                                <i class="fas fa-image"></i>
                            </span>
                        </div>
                        <img id="blah" src="{{obj.photo.url}}" alt="your image" />
                        {% render_field obj.photo class="form-control form-control-sm image-value" %}
                    </div> 
                </div>
            </div>
            <!-- onchange="document.getElementById(`blah`).src = window.URL.createObjectURL(this.files[0].name)" -->
            <div class="col-lg-1">
                <div class="control ">
                    <button 
                        type="button"
                        id="img_minus"
                        class="btn btn-block btn-outline-danger img-minus"
                        style="margin-bottom: 20px;"
                    >
                        <span class="fas fa-trash"></span>
                    </button>
                </div>
            </div>
            <div class="col-lg-1">
                <div class="control ">
                    <button 
                        type="button"
                        id="img_broom"
                        class="btn btn-block btn-outline-secondary img-broom"
                        style="margin-bottom: 20px;"
                    >
                        <span class="fas fa-broom"></span>
                    </button>
                </div>
            </div>
            
        </div>
        {% endfor %}
    {% endif %}

    <button 
        type="button"
        id="clone_img_button"
        class="btn btn-outline-info img-plus"
        style="margin-bottom: 20px;"
    >
        <span class="fa fa-caret-down"></span>
    </button>
    <!-- END OF UNIT -->

</div>
<!-- /.post -->

images/js.html


<!-- Page specific script -->
<script>
        var addImage = $('.img-row').last().clone();
        var countImage = 0;

        $(document).on('click', '.img-plus', function() {
            let cloneImage = addImage.clone();//.prop('id', 'product_' + count);
         
            if (countImage >= 2) {
                alert('You only have 3 images to add.')
            } else {
                $(this).prevAll('.img-row').first().after(cloneImage.hide());
                cloneImage.slideDown('fast');
                countImage++;
                
            }
                    
            console.log('COUNT-IMAGE-FOR: ', countImage);// $(this).parent().slideUp('fast');

        });

        $(document).on('click', '.img-minus', function() {
            if (countImage == 0) {
                // Do nothing.
                alert('You can not delete this row' );
            } else {
                $(this).closest('.img-row').remove();
                countImage--;
                let myValue = $(this).val();
                console.log('COUNT2-IMAGE: ', countImage,);

            }
        });

        $(document).on('click', '.img-broom', function() {
            $(this).closest('.img-row').find('input').val('');
            // console.log('val: ', $(this).closest('.image-row').find('input').val(0));
            // $(this).closest('.sub-row').find('#sub-name')[0].selectedIndex=0;
        });
        //
   
</script>

product/includes/js.html


<!-- Page specific script  for form submission -->
<script>
    $(document).ready(function () {
        $.ajaxSetup({
            headers: {
                "X-CSRFToken": '{{ csrf_token }}'
            }
        });

        $(document).on('submit', ".product-form", function (e) {
            e.preventDefault();
            // console.log();
       

            let imageValues = $('.image-value').map(function() {
                return $(this).val();
            }).get();

            console.log(
                'submit button clicked successfully',
                'PRO-NAME :', name,
                'OPTIONS:', optionValues,
                'UNIT-VALUEs:', unitValues,
                'UNIT-LABEL:', unitLabelValues,
                'UNIT-PRICE:', unitPriceValues,
                'VALUES :', values,
                'imageValues::', imageValues,
                'img-photo::',  $('#id_img-photo').val(),
            );

            $.ajax({
                type: 'POST',
                url: '{% url "products:add_product" %}', 
                contentType: 'application/x-www-form-urlencoded;charset=utf-8',
                
                data: {
                    // csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
                    'pro-branch': $('[name=pro-branch] option:selected').val(),
                    'pos_station': $('[name=pro-pos_station] option:selected').val(),
                    'pro-pos_station': '', //$('[name=pro-pos_station] option:selected').val(),
                    'pro-store': $('[name=pro-store] option:selected').val(),
                    'pro-name': name,
                    'pro-name_ar': nameAr,
                    'pro-barcode': $('#id_pro-barcode').val(),
                    'pro-reference_code': $('#id_pro-reference_code').val(),
                    'pro-is_deleted': $('[name=pro-is_deleted]').is(':checked'),
                    // 'pro-active': $('[name=pro-inactive]').is(':checked'),
                    'pro-inactive': $('[name=pro-inactive]').is(':checked'),
                    'pro-consumable': $('[name=pro-consumable]').is(':checked'),
                    'pro-on_pos': $('[name=pro-on_pos]').is(':checked'),
                    'pro-purchased': $('#id_pro-purchased').is(':checked'), 
                    'pro-sold': $('#id_pro-sold').is(':checked'), 
                    'pro-favorite': $('#id_pro-favorite').is(':checked'), 
                    'pro-is_inventory': $('#id_pro-is_inventory').is(':checked'), 
                    'pro-sale': $('#id_pro-sale').is(':checked'), 
                    'pro-manufactured': $('#id_pro-manufactured').is(':checked'), 
                    
                    'pro-expiry': $('#id_pro-expiry').is(':checked'), 
                    'pro-has_limit_plus': $('#id_pro-has_limit_plus').is(':checked'), 
                    'pro-has_limit_minus': $('#id_pro-has_limit_minus').is(':checked'), 
                    'pro-expire_period': $('#id_pro-expire_period').val(),
                    // 'pro-expire_ref': '', //$('#id_pro-expire_ref').val(),
                    'pro-expire_ref': $('#id_pro-expire_ref option:selected').val(),
                    'pro-expire_period_hint': $('#id_pro-expire_period_hint').val(),
                    // 'pro-hint_ref': '', // $('#id_pro-hint_ref').val(),
                    'pro-hint_ref': $('#id_pro-hint_ref option:selected').val(),
                    
                    'pro-order_limit_plus': $('#id_pro-limit_plus').val(),
                    'pro-order_unit_plus': $('#id_pro-order_unit_plus').val(),
                    'pro-order_limit_minus': $('#id_pro-limit_minus').val(),
                    'pro-order_unit_minus': $('#id_pro-order_unit_minus').val(),
                    
                    // CATEGORY FORM
                    'cat-main': $('#id_cat-main :selected').val(),
                    'cat-parent': $('#id_cat-parent :selected').val(),
                    'cat-child': $('#id_cat-child :selected').val(),
                    'cat-child_1': $('#id_cat-child_1 :selected').val(),
                    'cat-child_2': $('#id_cat-child_2 :selected').val(),
                    'cat-child_3': $('#id_cat-child_3 :selected').val(),
                    'cat-child_4': $('#id_cat-child_4 :selected').val(),
                    'cat-child_5': $('#id_cat-child_5 :selected').val(),
                    
                    // for price form
                    'price-switch_price': $('#id_price-switch_price').is(':checked'), 
                    'price-offer': $('#id_price-offer').is(':checked'), 
                    'price-tax': $('#id_price-tax').is(':checked'), 
                    'price-dealer': $('#id_price-dealer').is(':checked'), 
                    'price-pricing_policy': $('#id_price-pricing_policy').is('checked'),
                    'price-essential_unit': $('#id_price-essential_unit').val(), 
                    'price-purchasing_price': $('#id_price-purchasing_price').val(), 
                    'price-origin_price': $('#id_price-origin_price').val(), 
                    'price-price': $('#id_price-price').val(), 
                    'price-value': $('#id_price-value').val(), 
                    'price-percentage': $('#id_price-percentage').val(), 
                    'price-dealer_price': $('#id_price-dealer_price').val(),
                    'price-dealer_value': $('#id_price-dealer_value').val(), 
                    'price-dealer_percentage': $('#id_price-dealer_percentage').val(), 
                    'price-offer_price': $('#id_price-offer_price').val(), 
                    'price-offer_percentage': $('#id_price-offer_percentage').val(), 
                    'price-tax_percentage': $('#id_price-tax_percentage').val(),
                    
                    // for uom form
                    'uom-uom_options': $('#id_uom-uom_options :selected').val(),
                    'uom-unit': $('#id_uom-unit :selected').val(), 
                    'uom-value': $('#id_uom-value').val(),
                    'uom-uom_unit': $('#id_uom-uom_unit :selected').val(), 
                    "uom-main_uom": $('#id_uom-main_uom').is(':checked'),
                    "uom-uom_value": $('#id_uom-uom_value').val(),
                    'uom-unit_price': $('#id_uom-unit_price').val(), 

                    'option-list': optionValues, 
                    'unit-list': unitValues, 
                    'value-list': values,
                    'uom-value-list': uomValues,
                    'unit-label-list': unitLabelValues,
                    'unit-price-list': unitPriceValues,
                    
                    // for image form
                    'img-photo': $('#id_img-photo').val(),
                    'images-list': imageValues,
                },
                success: function (data) { 
                    console.log(
                        'WHAT IS GOING ON HERE FROM SUCCESS: ',
                        'DATA ERROR MSG --> ', data['error'],   
                        'AFTER-SUBMITTING:: ', optionValues, 
                        'AFTER-SUBMITTING:: ', unitValues, 
                        'AFTER-SUBMITTING:: ', values,
                        'IMAGE-PHOTO:::: ', $('#id_img-photo').val(), 
                    );
                    
                    $(function() {
                        var Toast = Swal.mixin({
                            toast: true,
                            position: 'top-end',
                            showConfirmButton: false,
                            timer: 9000
                        });
                        var proId = data['pro_id']; 

                        if (data['type'] == 'error'){
                            console.log(data['type'])
                            toastr.error(data['error']);
                        } else if (data['type'] == 'success') {
                            toastr.success(data['error']);
                            console.log('PRO-ID: ', data['pro_id']);
                            
                        } else if (data['type'] == 'info') {
                            toastr.info(data['error']);
                        }
                    });
                },
                error: function (){
                    console.log('ERROR with ajax request');
                },
            });
            e.preventDefault();
        });
            
    });


</script>

This is all my code

I will investigate the problem by creating another simple template and saving the image and I will see what will happen …

After investigating the insertion of image of the (ProductImage model). It is working good (without using Ajax)
the images created and the function(photo_path) works good, It gives me the URL in the database as (images/60/462d/60.jpeg) and send it to (media_root folder).

But when using Ajax (request.FILES[‘photo’]) doesn’t work and gives me “None” and the following url saved in the database (“C:\fakepath\pepsi.jpeg”) … I’m trying to use [
if request.accepts("*/*") ] instead of [ if request.accepts("text/html")] but it didn’t work
I don’t know how to fix it till now , But I’m still searching to find a good solution to image issue

Note that in the docs at File Uploads | Django documentation | Django

Note that request.FILES will only contain data if the request method was POST , at least one file field was actually posted, and the <form> that posted the request has the attribute enctype="multipart/form-data" . Otherwise, request.FILES will be empty.

You have:

which isn’t going to work to supply data to request.FILES.
(There may be other things wrong as well, but this is the first item that I noticed.)

Thanks for your help, I appreciate it so much .
I’ve tested using Ajax with simple function (it has only one image field), It’s doing the same behavior with (“contentType: false”) and it’s not working and no image created in media_root folder.
Without Ajax code the normal behavior occurs and the uploading process creates image via Django normally in the media_root folder

def add_test_image(request, product_id):
    data = {}
    data['error'] = 'Error !!!'
    data['type'] = 'error'
    if request.method == 'POST': #request.accepts('text/html') and 
        img_files = request.FILES.get('photo')
        img_post = request.POST.get('photo')
        print(
            'MY-IMAGE-PHOTO-FILES: ', img_files,
            'MY-IMAGE-PHOTO-POST: ', img_post
        )
        img_form = ProductImageForm(
            request.POST or None,
            request.FILES or None
        )
        if img_form.is_valid():
            img_save_form = img_form.save(commit=False)
            img_save_form.product_id = product_id
            # img_save_form.photo = request.FILES['photo']
            img_save_form.save()
            print('IMAGE FORM IS VALID AND IMAGE SAVED DONE ...', 
                request.FILES['photo'])
            data['error'] = 'IMAGE FORM IS VALID AND IMAGE SAVED DONE ...'
            data['type'] = 'success'
            return JsonResponse(data)
            # return redirect(reverse(
            #    'test_image_details', args=(product_id,)
            #)) 
        else:
            print('IMAGE Form Is Invalid !!!')
    else:
        img_form = ProductImageForm()
            
    context = {
        'img_form': img_form,
        'product_id': product_id
    }
    return render(request, 'home/add_test_image.html', context)

html file


{% block content %}

<form method="post" enctype="multipart/form-data" class="image-form">
    {% csrf_token %}
    <!-- Post -->
    <div class="post">
        <div class="row">
            <div class="col-md-10">
                <h4 class="astrik-input">Add One Image To Product: </h4>
            </div>
        </div>
    
        <hr class="my-4">
        <div class="row image-row">

            <div class="col-lg-10">
                <div class="input-group">
                    <div class="input-group-prepend">
                        <span class="input-group-text">
                            <i class="fas fa-image"></i>
                        </span>
                    </div>
                    <!-- <div class="custom-file">
                        <input type="file" class="custom-file-input" id="InputFile">
                        <label class="custom-file-label" for="InputFile">{% trans 'Choose image' %}</label>
                    </div> -->
                    {% render_field img_form.photo class="form-control form-control-sm image-value" %}
                </div> <br>
            </div>

            
        </div>
        
    </div>
    <!-- /.post -->
    <hr class="my-4">

    <div class="col-lg-4">
        <div class="control ">
            <button type="submit"
                    class="btn btn-warning"
                    style="margin-bottom: 20px;"
            >
                Save Image <!-- <span class="fa fa-plus"></span> -->
            </button>
        </div>
    </div>


</form>

{% endblock content %}


{% block javascripts %}

{% include 'home/test_image_js.html' %}

{% endblock javascripts %}

Js file

$(document).on('submit', ".image-form", function (e) {
        e.preventDefault();
        let productID = '{{product_id}}'; 
        let imageValues = $('.image-value').map(function() {
            return $(this).val();
        }).get();
        
        console.log(
            'imageValues::', imageValues,
            'img-photo::',  $('#id_photo').val(),
        );

        $.ajax({
            type: 'POST',
            url: '{% url "add_test_image" product_id=0 %}'.replace('0', productID), 
            cache: false,
            contentType: false,
            processData: false,
            data: {
                csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
                // for image form
                'photo': $('#id_photo').val(),
                'images-list': imageValues,
            },
            success: function (data) { 
                console.log(
                    'WHAT IS GOING ON HERE FROM SUCCESS: ',
                    'IMAGE-PHOTO:::: ', $('#id_photo').val(), 
                );
                
                $(function() {
                    var Toast = Swal.mixin({
                        toast: true,
                        position: 'top-end',
                        showConfirmButton: false,
                        timer: 9000
                    });
                    if (data['type'] == 'error'){
                        console.log(data['type'])
                        toastr.error(data['error']);
                    } else if (data['type'] == 'success') {
                        toastr.success(data['error']);
                    } else if (data['type'] == 'info') {
                        toastr.info(data['error']);
                    }
                });
            },
            error: function (){
                console.log('ERROR with ajax request');
            },
        });
        e.preventDefault();
    });

What attribute should I use in Ajax request to treat normally with image field and return correct data not “None” as
request.FILES['photo'] and as request.FILES.get('photo')

So what is the content-type header / enctype form attribute supposed to be for file submissions?

The enctype is >> enctype="multipart/form-data" class="image-form"
when I searched to find a solution I found that in stack over flow thread

* Stackoverflow-thread
Also on github

* github-thread

I found this but with using request.is_ajax() not with request.accepts()

cache: false,
contentType: false,
processData: false,

But it didn’t fix my issue…
Now I’m using request.accepts('*/*') but it didn’t fix the issue …
I will try to use the FormData() object as mentioned in the threads , and see if it is useful or not.

But you’re not submitting the form.

You’re creating post data and building your own submission for an AJAX call. What you specify in the form tag doesn’t apply.

That’s why I suggest you look at what you’re submitting by examining the network tab in your browser’s developer tools.

(And whatever you do, never blindly trust SO. Always seek independent verification on a more reliable site.)

1 Like

Finally I fixed the issue,

I will try to use the FormData() object as mentioned in the threads , and see if it is useful or not.

FormData() object fixed it and another missing thing (To get the value of an file field input you must use $('#image').get(0).files[0] NOT $('#image').val() It’s very very important)
Also FormData() enable me to insert multiple rows of a form in the same time,
This is my code if anyone experience this issue with ajax

$(document).on('submit', ".product-form", function (e) {
        e.preventDefault();
let formData = new FormData();
formData.append('pro-branch', $('[name=pro-branch] option:selected').val());
formData.append('pos_station', $('[name=pro-pos_station] option:selected').val());
// IMG-FORM
let imageValues = $('.image-value').map(function() {
     return $(this).get(0).files[0];  // instead of using $(this).val()
}).get();

// because I have many rows of img_form
if(imageValues.length){
    for(let image of imageValues){
        formData.append('img-photo', image);
     }
}
     let token = '{{ csrf_token }}';

     $.ajax({
            type: 'POST',
            url: '{% url "products:add_product" %}', 
            headers: {'X-CSRFToken': token},
            cache: false,
            contentType: false,
            processData: false,
            data: formData,
            success: function (data) { 
                console.log(
                    'SUCCESS: ');
            },
            error: function (){
                console.log('ERROR with ajax request');
            },
        });
        e.preventDefault();

});

Sorry I can’t absorb what do you mean ?, But really thank you for your time and efforts

Thanks KenWhitesell