问题
I'm trying to save an image using the chunks method to handle the case where a user tries to upload a large image:
destination = open(incident.Image.path, 'wb+')
for chunk in request.FILES['image'].chunks():
destination.write(chunk)
destination.close()
My problem is I can't get the filepath without first saving something in the Image field like so:
fileName = str(int(time.time() * 1000))
imageName = fileName + '.jpg'
incident.Image.save(imageName, request.FILES['image'])
My question is how can I get the equivalent of incident.Image.path without first saving the image? I don't want to hardcode the path, and the reason I'm stuck is because I can't get the full filepath without getting the upload_to portion of the ImageField declaration
EDIT:
Ok, I've gotten a little farther but I'm stuck again:
imgBuffer = StringIO.StringIO()
for chunk in request.FILES['image'].chunks():
imgBuffer.write(chunk)
# rotate it
rotate = request.POST['rotation']
im = Image.open(imgBuffer)
im = im.rotate(float(rotate))
incident.Image.save(imageName, ContentFile(imgBuffer))
I'm getting IOError cannot identify image file which is thrown at im = Image.open(imgBuffer), any ideas?
回答1:
Have a look at stringIO also have a look at this site
回答2:
Images (as files) are saved in pre_save method of model fields. Here is a working example (got from my project) of a such custom model field - FixedImageField.
You may see how I retrieve an image path in the function pre_save.
In my case I have a complicated scheme (I have to inherit the image field) but you can simplify it for your case.
You can implement your own _save_fixed_resolution_image(chunks,path) - in my case it transforms an image to an image with maximum 400x400 size:
from PIL import Image
import StringIO
from yourproject.settings import MEDIA_ROOT
import os
from django.db import models
class ChunksImageField( models.ImageField ):
def pre_save( self, model_instance, add ):
file = super( models.FileField, self ).pre_save(model_instance, add)
if file and not file._committed:
if callable( self.upload_to ):
path = self.upload_to( model_instance, "" )
else:
path = self.upload_to
file.name = path
full_path = os.path.join( MEDIA_ROOT, path )
chunks = _get_chunks( file.chunks() )
self._save_image_func( model_instance, chunks, full_path )
return file
class FixedImageField( ChunksImageField ):
def __init__( self, *args, **kwargs ):
super( FixedImageField, self ).__init__( *args, **kwargs )
def _save_image_func( self, model_instance, chunks, path ):
_save_fixed_resolution_image( chunks, path )
def _save_fixed_resolution_image( chunks, out_file_path ):
image = _get_image( chunks )
if image.size[ 0 ] > _image_max_size or image.size[ 1 ] > _image_max_size:
image.thumbnail( ( _image_max_size, _image_max_size, ) )
save_image( image, out_file_path )
def save_image( image, out_file_path ):
image.save( out_file_path, "JPEG", quality = 100 )
def _get_chunks( chunks ):
chunks_ = ""
for chunk in chunks:
chunks_ += chunk
return chunks_
How to use it in your model:
class YourModel( models.Model ):
image = FixedImageField( upload_to = image_path ) # substitute your image path here
回答3:
I solved the primary problem as follows:
myimage = MyImageModel()
upload_to = myimage.myimagefield.field.upload_to
filepath = os.path.join(settings.MEDIA_ROOT, upload_to)
The secondary problem of not uploading twice I did as follows:
filename = os.path.basename(url)
myimage.myimagefield = os.path.join(upload_to, filename)
myimage.save()
来源:https://stackoverflow.com/questions/10949601/django-get-imagefield-path-before-saving-image