Overwrite Django ImageField to accept absolute URIs as well as files

What ImageField does under the hood , is that is stores the image path as string in the db. I would like to overwrite the field in such a way, that it can accept either a binary image file or absoulte URI path and return the path as string and store it as char in the db.

Which method would have to be overwritten to achieve this operation ?


To achieve this operation, you would likely need to override the save() method of the ImageField in order to handle both binary image files and absolute URI paths.

Here is an example of how you could do this:

class MyImageField(models.ImageField):
    def save(self, name, content, save=True):
        if isinstance(content, str):
            if content.startswith('http'):
                # it is an URI, let's download the file
                response = requests.get(content)
                content = ContentFile(response.content)
                name = os.path.join(settings.MEDIA_ROOT, name)
                # it is a binary image file
                content = ContentFile(content)
        super().save(name, content, save)

This custom field will check if the passed content is a string, if it is, it will check if it starts with "http" (indicating that it is a URI) or not. If it is a URI, it will download the file using the requests library and create a ContentFile object that Django's ImageField expects, with the downloaded image content. If it's not a URI, it will create the ContentFile object with the passed binary image.

You should use this custom field in your model instead of the original ImageField.

class MyModel(models.Model):
    my_image = MyImageField(upload_to='my_images')

You might need to do some additional modification depending on your use case.

Don't forget to mark it as a solution if that helped you ^_^ .

Without overriding ImageField() you can do those things using one extra URLField() like this...


class Product(models.Model):
    name = models.CharField(max_length=200, null=True)
    image = models.ImageField(upload_to ='Products')
    img_abs_url = models.URLField(blank=True,null=True)

    def __str__(self):
        return self.name


class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = "__all__" 
        exclude = ['img_abs_url']


def HomeView(request):
  form = ProductForm()
  products = Product.objects.all()
  if request.method == 'POST':
    form = ProductForm(request.POST,request.FILES)
    if form.is_valid():
      product_name = form.cleaned_data['name']
      image = form.cleaned_data['image']
      create_product = Product.objects.create(name=product_name,image=image)
      create_product.img_abs_url = request.build_absolute_uri(create_product.image.url)
  context = {'form': form, 'products': products}
  return render(request, 'index.html', context)

Output (admin panel)

enter image description here

Back to Top