5

I am currently using Cloudinary with Django to store user profile pictures and would like to pass parameters to it store it in a folder and and overwrite the existing image instead of creating a new one.

In my user model:

picture = CloudinaryField('image')

This works as expected with Django Admin and forms. I would just like the ability to store it in the folder users/USERNAME/profile and when someone updates their picture to delete the old one.

Alex Atwater
  • 151
  • 1
  • 15
  • 1
    See the explanation on [Django's upload documentation page](http://cloudinary.com/documentation/django_image_upload#django_forms_and_models), specifically he use of `CloudinaryFileField()` which accepts upload-option hash, incuding the `public_id` & `folder` parameters. – Nadav Ofir May 01 '16 at 11:30
  • @NadavOfir [Overriding](http://stackoverflow.com/a/39906960/2996101) the ```upload_options``` method assures that the image will be transformed even if the model form is not rendered. For example, when a script tries to save the image. – raratiru Oct 06 '16 at 23:14

3 Answers3

7

update

The solution that worked in 2016 is no longer viable. According to the docs, the following will work:

image = CloudinaryField(
    "Image",
    overwrite=True,
    resource_type="image",
    transformation={"quality": "auto:eco"},
    format="jpg",
)

The allowed params are listed here and here in the code for version 1.17.0 or here in the docs.

For example, I was confused with the keyword quality. I was using it directly when using the API but in CloudinaryField is not allowed.

The proper way to define the quality of the uploaded photo is by setting:

transformation={"quality": 80}.

This is clarified in the docs where it is explained that:

Note that when using the SDK for a dynamically typed language, the transformation parameters can be specified directly without using this transformation parameter.


This worked perfectly:

from cloudinary.models import CloudinaryField as BaseCloudinaryField
from django.db import models


class CloudinaryField(BaseCloudinaryField):
    def upload_options(self, model_instance):
        return {
            'public_id': model_instance.name,
            'unique_filename': False,
            'overwrite': True,
            'resource_type': 'image',
            'tags': ['map', 'market-map'],
            'invalidate': True,
            'quality': 'auto:eco',
        }

class MarketMap(models.Model):
    name = models.CharField(max_length=17)
    image = CloudinaryField()
Taufiq Rahman
  • 5,600
  • 2
  • 36
  • 44
raratiru
  • 8,748
  • 4
  • 73
  • 113
1

You can also add these kind of options to the form field like so:

image = CloudinaryFileField(
    label='My image',
    options={
        'tags': "module, home",
        'format': 'jpg',
        'crop': 'limit',
        'width': 640
    },
    required=False)
Christoffer
  • 7,436
  • 4
  • 40
  • 42
1

It took me a while to realize -- and based on the questions I see in StackOverflow its not clear for others as well -- CloudinaryField and CloudinaryFileField appear similar but are different classes. CloudinaryField is a Model class, whereas CloudinaryFileField is a Form class. The options to specify a file path or tags are done at the FORM level with CloudinaryFileField (See Image Upload API documentation)

from cloudinary.forms import CloudinaryFileField
# Note - cloudinary folders are specified at the FORM level and not in the MODEL
class EditPhotoForm(ModelForm):
class Meta:
    model = Photo
    fields = ('name', 'description', 'image', 'slug')
    image = CloudinaryFileField(options={'folder' : 'media/photos/', 'tags': 'landscapes'})
Philip
  • 71
  • 5