اذهب إلى المحتوى

السؤال

نشر

السلام عليكم،

عندما أقوم بعمل POST الى API مطور ياستخدام Django وأضف ملف صورة في الطلب أحصل على رمز الحالة 415 Unsupported Media Type وأحصل على هذه في الاستجابة :

detail: 'Unsupported media type "application/json" in request.'

مع أن الطلب ينجح ان لم أقم باضافة صورة، أيضاً عند وجود صورة أقوم بإرسال الطلب كFormData بدون إضافة { 'Content-Type': 'application/json'} .

هل يوجد طريقة محددة لارسال ملف صورة الى API مطور باستخدام Django Rest Framework ؟

Recommended Posts

  • 0
نشر

وعليكم السلام ورحمة الله وبركاته.

لاحظ الخطأ يخبرك أنه لا يمكن قبول الصور من خلال الطلب من نوع application/json كما تفعل .

فهذه المشكلة شائعة عند رفع ملفات كالصور باستخدام Django REST Framework. والسبب أنك عندما ترسل الطلب مع صورة يجب أن ترسل البيانات باستخدام multipart/form-data وليس application/json أو أى نوع أخر.

ولا يجب أن تقوم بتعيين Content-Type يدويا إلى application/json حيث بما أنك تستخدم FormData فإنه يتم إضافة Content-Type المناسب (multipart/form-data).

فمثلا لو قمت بإرسال طلب ال API من خلال java script فيجب أن يكون كالتالي: 

const formData = new FormData();
formData.append('name', 'example');
formData.append('image', fileInput.files[0]);

fetch('/api/upload/', {
  method: 'POST',
  body: formData
});

ولو كنت ترسل الطلب من خلال postman فيجب إختيار form-data من ال body وإرسال الصور منها :

image.png.42cd5a12fde16a345658a242921580d5.png

  • 0
نشر
بتاريخ 8 دقائق مضت قال محمد_عاطف:

وعليكم السلام ورحمة الله وبركاته.

لاحظ الخطأ يخبرك أنه لا يمكن قبول الصور من خلال الطلب من نوع application/json كما تفعل .

فهذه المشكلة شائعة عند رفع ملفات كالصور باستخدام Django REST Framework. والسبب أنك عندما ترسل الطلب مع صورة يجب أن ترسل البيانات باستخدام multipart/form-data وليس application/json أو أى نوع أخر.

ولا يجب أن تقوم بتعيين Content-Type يدويا إلى application/json حيث بما أنك تستخدم FormData فإنه يتم إضافة Content-Type المناسب (multipart/form-data).

فمثلا لو قمت بإرسال طلب ال API من خلال java script فيجب أن يكون كالتالي: 

const formData = new FormData();
formData.append('name', 'example');
formData.append('image', fileInput.files[0]);

fetch('/api/upload/', {
  method: 'POST',
  body: formData
});

ولو كنت ترسل الطلب من خلال postman فيجب إختيار form-data من ال body وإرسال الصور منها :

image.png.42cd5a12fde16a345658a242921580d5.png

 

بتاريخ 9 دقائق مضت قال محمد_عاطف:

وعليكم السلام ورحمة الله وبركاته.

لاحظ الخطأ يخبرك أنه لا يمكن قبول الصور من خلال الطلب من نوع application/json كما تفعل .

فهذه المشكلة شائعة عند رفع ملفات كالصور باستخدام Django REST Framework. والسبب أنك عندما ترسل الطلب مع صورة يجب أن ترسل البيانات باستخدام multipart/form-data وليس application/json أو أى نوع أخر.

ولا يجب أن تقوم بتعيين Content-Type يدويا إلى application/json حيث بما أنك تستخدم FormData فإنه يتم إضافة Content-Type المناسب (multipart/form-data).

فمثلا لو قمت بإرسال طلب ال API من خلال java script فيجب أن يكون كالتالي: 

const formData = new FormData();
formData.append('name', 'example');
formData.append('image', fileInput.files[0]);

fetch('/api/upload/', {
  method: 'POST',
  body: formData
});

ولو كنت ترسل الطلب من خلال postman فيجب إختيار form-data من ال body وإرسال الصور منها :

image.png.42cd5a12fde16a345658a242921580d5.png

شكراً لك، ولاكني بالفعل لا أضيف application/json الى الكود عندما ارفع صورة ويظهر نفس الخطأ

const apiRequest = async (endpoint, options = {}) => {
  const url = `${API_BASE_URL}${endpoint}`;
  // If the body is of type FormData, do not add the content type.
  const isFormData = options.body instanceof FormData;
  const headers = isFormData
    ? { ...options.headers }
    : { 'Content-Type': 'application/json', ...options.headers };

  const response = await fetch(url, {
    ...options,
    headers,
  });

  if (!response.ok) {
    const errorData = await response.json().catch(() => ({}));
    throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
  }

  if (response.status === 204) {
    return { success: true };
  }

  return response.json();
};

// Product Mutations
export const useCreateProduct = () => {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (productData) => {
      if (productData.image && productData.image instanceof File) {
        const formData = new FormData();
        Object.keys(productData).forEach(key => {
          if (productData[key] !== null && productData[key] !== undefined) {
            formData.append(key, productData[key]);
          }
        });
        
        return fetch(`${API_BASE_URL}/api/products/`, {
          method: 'POST',
          body: formData,
        }).then(response => {
          if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
          return response.json();
        });
      } else {
        return apiRequest('/api/products/', {
          method: 'POST',
          body: JSON.stringify(productData),
        });
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: productKeys.lists() });
      queryClient.invalidateQueries({ queryKey: categoryKeys.lists() });
      queryClient.invalidateQueries({ queryKey: productKeys.lowStock });
      queryClient.invalidateQueries({ queryKey: productKeys.outOfStock });
    },
  });
};

 

  • 0
نشر
بتاريخ 11 دقائق مضت قال ديب الحجار:

 

شكراً لك، ولاكني بالفعل لا أضيف application/json الى الكود عندما ارفع صورة ويظهر نفس الخطأ

const apiRequest = async (endpoint, options = {}) => {
  const url = `${API_BASE_URL}${endpoint}`;
  // If the body is of type FormData, do not add the content type.
  const isFormData = options.body instanceof FormData;
  const headers = isFormData
    ? { ...options.headers }
    : { 'Content-Type': 'application/json', ...options.headers };

  const response = await fetch(url, {
    ...options,
    headers,
  });

  if (!response.ok) {
    const errorData = await response.json().catch(() => ({}));
    throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
  }

  if (response.status === 204) {
    return { success: true };
  }

  return response.json();
};

// Product Mutations
export const useCreateProduct = () => {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (productData) => {
      if (productData.image && productData.image instanceof File) {
        const formData = new FormData();
        Object.keys(productData).forEach(key => {
          if (productData[key] !== null && productData[key] !== undefined) {
            formData.append(key, productData[key]);
          }
        });
        
        return fetch(`${API_BASE_URL}/api/products/`, {
          method: 'POST',
          body: formData,
        }).then(response => {
          if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
          return response.json();
        });
      } else {
        return apiRequest('/api/products/', {
          method: 'POST',
          body: JSON.stringify(productData),
        });
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: productKeys.lists() });
      queryClient.invalidateQueries({ queryKey: categoryKeys.lists() });
      queryClient.invalidateQueries({ queryKey: productKeys.lowStock });
      queryClient.invalidateQueries({ queryKey: productKeys.outOfStock });
    },
  });
};
 

 

لاداعي للشكر .

نعم من المفترض أن الكود صحيح ويجب أن يتم إرسال الطلب بشكل صحيح . هل يمكنك إرسال صورة للطلب من خلال نافذة network في أدوات المطور مع بيانات الطلب . وأيضا يرجى إرسال كود Django view فمن الممكن أن المشكلة فيه  

  • 0
نشر
بتاريخ 5 دقائق مضت قال محمد_عاطف:

لاداعي للشكر .

نعم من المفترض أن الكود صحيح ويجب أن يتم إرسال الطلب بشكل صحيح . هل يمكنك إرسال صورة للطلب من خلال نافذة network في أدوات المطور مع بيانات الطلب . وأيضا يرجى إرسال كود Django view فمن الممكن أن المشكلة فيه  

اimage.png.5d076de798ecf699b35d05f9609a274d.png

الطلب فارغ كما ترى وهذا يحدث فقط عند إضافة صورة. أرفقت لك أيضاً ملجد المشروع مع ملف views.py

inventory-ms.zip views.py

  • 0
نشر
بتاريخ 58 دقائق مضت قال ديب الحجار:

الطلب فارغ كما ترى وهذا يحدث فقط عند إضافة صورة. أرفقت لك أيضاً ملجد المشروع مع ملف views.py

inventory-ms.zip 56.38 kB · 1 تنزيل views.py 6.96 kB · 1 تنزيل

كنت أقصد بيانات الطلب headers . ولكن لا مشكلة من المفترض أن ملف views لديك صحيح لا توجد به مشكلة حيث الكود سليم من ناحية parser_classes في ال ProductViewSet.

وغالبا السبب في إعدادات REST_FRAMEWORK في settings.py. لذلك يرجى التحقق إذا كان لديك في settings.py هذا الجزء:

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
    ],
}

فإذا كان موجود فهذا يلغي إعداد parser_classes الموجود في الـ ViewSet ويجعل DRF يتوقع دائما JSON.

لذلك الحل إما حذف هذا الإعداد أو تعديله وإضافة التالي به :

'DEFAULT_PARSER_CLASSES': [
    'rest_framework.parsers.JSONParser',
    'rest_framework.parsers.MultiPartParser',
    'rest_framework.parsers.FormParser',
]

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...