0

I am writing my first react-native app with a django backend. for my app to work properly I need to send an image from the device's image library to the django server and then save it in the model. here's my code -

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)

urls.py(home)

router = routers.DefaultRouter()
router.register('users', UserViewSet)
router.register('profiles', ProfileViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('login/', views.login),
    path('signup/', views.signup),
    path('profile/', views.setprofile),
    path('profileimg/', views.setprofileimg),
    path('checkprofile1/', views.checkprofile1),
    path('checkprofile2/', views.checkprofile2),
    path('matchfriends/', views.matchfriends),
    path('getRequesting/', views.getRequesting),
    path('acceptRe/', views.acceptRe),
    path('denyRe/', views.denyRe),
    path('request/', views.request),
    path('unrequest/', views.unrequest),
    path('imagetest/', views.imagetest),
    path('counttest/', views.counttest),

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/'

When I try this and I try to print the profile.image I get the file's name without the "image/" before it. When I checked the admin's interface the image field is blank. I have worked on this issue for weeks and I still can't figure out how to save the image in the django model?

Itay Lador
  • 313
  • 1
  • 10

1 Answers1

1

The problem is Django rest framework need images in base64 format.

so you can install drf_extra_fields.

from drf_extra_fields.fields import Base64ImageField

and use it inside serializer class like this:

profile_image = Base64ImageField(use_url=True, required=False)

From react native you should convert image to base64. In react you can use this code but I don't know if works with 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);
        }
    })
}

This code also contain extra lib to compress image called '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)
}
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
Hashem
  • 595
  • 1
  • 3
  • 8