To retrieve image URL, exactly the same way as with ImageField:
`my_object.photo.url`
To retrieve thumbnails URL's just add the size to it:
`my_object.photo.url_125x125`
`my_object.photo.url_300x200`
To convert to greyscale set the third attribute of size to True

# -*- encoding: utf-8 -*-"""django-thumbs by Antonio Meléhttp://django.es"""fromdjango.db.modelsimportImageFieldfromdjango.db.models.fields.filesimportImageFieldFilefromPILimportImagefromdjango.core.files.baseimportContentFileimportcStringIOdefgenerate_thumb(img,thumb_size,format,bw=False):""" Generates a thumbnail image and returns a ContentFile object with the thumbnail Parameters: =========== img File object thumb_size desired thumbnail size, ie: (200,120) format format of the original image ('jpeg','gif','png',...) (this format will be used for the generated thumbnail, too) bw convert to grayscale? True or False """img.seek(0)# see http://code.djangoproject.com/ticket/8222 for detailsimage=Image.open(img)# Convert to RGB if necessaryifimage.modenotin('L','RGB'):image=image.convert('RGB')ifbw:image=image.convert('L')# get sizethumb_w,thumb_h=thumb_size# If you want to generate a square thumbnailifthumb_w==thumb_h:# quadxsize,ysize=image.size# get minimum sizeminsize=min(xsize,ysize)# largest square possible in the imagexnewsize=(xsize-minsize)/2ynewsize=(ysize-minsize)/2# crop itimage2=image.crop((xnewsize,ynewsize,xsize-xnewsize,ysize-ynewsize))# load is necessary after crop image2.load()# thumbnail of the cropped image (with ANTIALIAS to make it look better)image2.thumbnail(thumb_size,Image.ANTIALIAS)else:# not quadx1=y1=0x2,y2=image.sizewRatio=1.0*x2/thumb_size[0]hRatio=1.0*y2/thumb_size[1]ifhRatio>wRatio:y1=int(y2/2-thumb_size[1]*wRatio/2)y2=int(y2/2+thumb_size[1]*wRatio/2)else:x1=int(x2/2-thumb_size[0]*hRatio/2)x2=int(x2/2+thumb_size[0]*hRatio/2)image2=imageimage2=image2.crop((x1,y1,x2,y2))printimage2.sizeimage2.thumbnail(thumb_size,Image.ANTIALIAS)io=cStringIO.StringIO()# PNG and GIF are the same, JPG is JPEGifformat.upper()=='JPG':format='JPEG'image2.save(io,format,quality=100)returnContentFile(io.getvalue())defgenerate_bw(img):""" Generates a thumbnail image and returns a ContentFile object with the thumbnail Parameters: =========== img File object thumb_size desired thumbnail size, ie: (200,120) format format of the original image ('jpeg','gif','png',...) (this format will be used for the generated thumbnail, too) bw convert to grayscale? True or False """img.seek(0)# see http://code.djangoproject.com/ticket/8222 for detailsimage=Image.open(img)image=image.convert('L')io=cStringIO.StringIO()# PNG and GIF are the same, JPG is JPEGifformat.upper()=='JPG':format='JPEG'image2.save(io,format,quality=100)returnContentFile(io.getvalue())classImageWithThumbsFieldFile(ImageFieldFile):""" See ImageWithThumbsField for usage example """def__init__(self,*args,**kwargs):super(ImageWithThumbsFieldFile,self).__init__(*args,**kwargs)self.sizes=self.field.sizesself.bw=self.field.bwifself.field.bw:defget_bw(self):ifnotself:return''else:split=self.url.rsplit('.',1)thumb_url='%s.bw.%s'%(split[0],split[1])returnthumb_urlsetattr(self,'url_bw',get_bw(self))ifself.sizes:defget_size(self,size):ifnotself:return''else:split=self.url.rsplit('.',1)thumb_url='%s.%sx%s.%s'%(split[0],w,h,split[1])returnthumb_urlforsizeinself.sizes:iflen(size)>2:(w,h,bw,)=sizeelse:(w,h,)=sizesetattr(self,'url_%sx%s'%(w,h),get_size(self,size))defsave(self,name,content,save=True):super(ImageWithThumbsFieldFile,self).save(name,content,save)ifself.bw:split=self.name.rsplit('.',1)thumb_name='%s.bw.%s'%(split[0],split[1])thumb_content=generate_bw(content)thumb_name_=self.storage.save(thumb_name,thumb_content)ifnotthumb_name==thumb_name_:raiseValueError('There is already a file named %s'%thumb_name)ifself.sizes:forsizeinself.sizes:bw=Falseiflen(size)>2:(w,h,bw,)=sizeelse:(w,h,)=sizesplit=self.name.rsplit('.',1)thumb_name='%s.%sx%s.%s'%(split[0],w,h,split[1])# you can use another thumbnailing function if you likethumb_content=generate_thumb(content,size[:2],split[1],bw)thumb_name_=self.storage.save(thumb_name,thumb_content)ifnotthumb_name==thumb_name_:raiseValueError('There is already a file named %s'%thumb_name)defdelete(self,save=True):name=self.namesuper(ImageWithThumbsFieldFile,self).delete(save)ifself.sizes:forsizeinself.sizes:iflen(size)>2:(w,h,bw,)=sizeelse:(w,h,)=sizesplit=name.rsplit('.',1)thumb_name='%s.%sx%s.%s'%(split[0],w,h,split[1])try:self.storage.delete(thumb_name)except:passclassImageWithThumbsField(ImageField):attr_class=ImageWithThumbsFieldFile""" Usage example: ============== photo = ImageWithThumbsField(upload_to='images', sizes=((125,125,True),(300,200),) To retrieve image URL, exactly the same way as with ImageField: my_object.photo.url To retrieve thumbnails URL's just add the size to it: my_object.photo.url_125x125 my_object.photo.url_300x200 To convert to greyscale set the third attribute of size to True Note: The 'sizes' attribute is not required. If you don't provide it, ImageWithThumbsField will act as a normal ImageField How it works: ============= For each size in the 'sizes' atribute of the field it generates a thumbnail with that size and stores it following this format: available_filename.[width]x[height].extension Where 'available_filename' is the available filename returned by the storage backend for saving the original file. Following the usage example above: For storing a file called "photo.jpg" it saves: photo.jpg (original file) photo.125x125.jpg (first thumbnail) photo.300x200.jpg (second thumbnail) With the default storage backend if photo.jpg already exists it will use these filenames: photo_.jpg photo_.125x125.jpg photo_.300x200.jpg Note: django-thumbs assumes that if filename "any_filename.jpg" is available filenames with this format "any_filename.[widht]x[height].jpg" will be available, too. To do: ====== Add method to regenerate thubmnails """def__init__(self,verbose_name=None,name=None,bw=False,width_field=None,height_field=None,sizes=None,**kwargs):self.verbose_name=verbose_nameself.name=nameself.width_field=width_fieldself.height_field=height_fieldself.sizes=sizesself.bw=bwsuper(ImageField,self).__init__(**kwargs)try:fromsouth.modelsinspectorimportadd_introspection_rulesadd_introspection_rules([],["^thumbs\.ImageWithThumbsField"])exceptImportError:pass