Проблемы при попытке сохранить изображение из react-native в модель django
Я пишу свое первое react-native приложение с бэкендом django. чтобы мое приложение работало правильно, мне нужно отправить изображение из библиотеки изображений устройства на сервер django и затем сохранить его в модели. вот мой код -
react-native-
const sendI = async (image) => {
const formData = new FormData()
let image_data = {
uri : image.uri,
name : image.fileName,
type : image.type,
}
if (image != null){
await formData.append( 'image', image_data)
await formData.append('name', usern)
//await formData.append('name', 'a' )
console.log(formData)
setSentI(formData)
console.log('recieved')
}
console.log(image)
}
const showImagePicker = async () => {
// Ask the user for the permission to access the media library
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
alert("You've refused to allow this appp to access your photos!");
return;
}
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
// Explore the result
console.log(result);
if (!result.cancelled) {
await setProfileImage(result);
console.log(result.uri);
sendI(result);
}
}
const openCamera = async () => {
// Ask the user for the permission to access the camera
const permissionResult = await ImagePicker.requestCameraPermissionsAsync();
if (permissionResult.granted === false) {
alert("You've refused to allow this appp to access your camera!");
return;
}
const result = await ImagePicker.launchCameraAsync();
// Explore the result
console.log(result);
if (!result.cancelled) {
setProfileImage(result);
console.log(result);
}
}
const image = () => {
console.log(sentI)
fetch(server + `home/imagetest/`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: sentI,
})
.then( res => res.json())
.then( res => {
console.log(res)
})
.catch( error => console.log(error))
}
django-
models.py
class Profile(models.Model):
image = models.ImageField(upload_to="images/", blank=True)
views.py
@csrf_exempt
def imagetest(request):
if request.method == "POST":
print(request.FILES)
image = request.FILES.get('image', False)
user = request.POST.get('name', False)
print(image)
print(user)
userid = User.objects.get(username=user).id
profile = Profile.objects.get(id=userid)
profile.image = image
print(profile)
print(profile.image)
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', include('home.urls')),
path('auth/', obtain_auth_token),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
STATIC_URL = '/static/'
Когда я пробую это и пытаюсь распечатать profile.image, я получаю имя файла без "image/" перед ним. Когда я проверил интерфейс администратора, поле изображения пустое. Я работал над этим вопросом несколько недель и до сих пор не могу понять, как сохранить изображение в модели django?
проблема в том, что Django rest framework требует изображения в формате base64
поэтому вы можете установить drf_extra_fields
from drf_extra_fields.fields import Base64ImageField
и использовать его внутри класса сериализатора следующим образом:
profile_image = Base64ImageField(use_url=True, required=False)
из react native вы должны преобразовать изображение в base64 . в react вы можете использовать этот код, но я не знаю, работает ли он с react native
const convertBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file)
fileReader.onload = () => {
resolve(fileReader.result);
}
fileReader.onerror = (error) => {
reject(error);
}
})
}
этот код также содержит дополнительную либу для сжатия изображения под названием 'compressorjs'
const handleFileRead = async (event) => {
const file = event.target.files[0]
let compressedFile = null;
const compressed = new Compressor(file, {
quality: 0.6,
});
const base64 = await convertBase64(compressed.file)
setValue('profile_image', base64)
setFile(compressedFile)
}