如何在Django模板中显示使用AppEngine的Image API裁剪的图像?

时间:2013-06-01 19:59:45

标签: google-app-engine django-nonrel djangoappengine

我正在使用django non-rel作为appengine(djangoappengine)并且有一个用户选择图像的应用程序,我必须从所选图像返回裁剪。

我的应用中的图片会在django-filetransfers instructions之后上传到Blobstore。我设法上传(甚至下载)文件就好了。

我遇到的问题是,我不知道如何在裁剪后在模板中显示图像。

我的观点的(简化)代码如下:

def canvas_size(request):
if request.method == 'POST':
    #some code here
else:
    #At this point the user has selected an image, and I store its pk in session
    img_file = ImageModel.objects.get(pk=request.session[SESSION_KEY]['image_pk'])
    img = images.Image(blob_key=str(img_file.file.file.blobstore_info.key())) 
    img.resize(height=300)
    img.crop(left_x=0.0, top_y=0.0, right_x=0.5, bottom_y=1.0)
    crop_img = img.execute_transforms(output_encoding=images.JPEG)
    #I know that the image is being cropped because if I do
    #print crop_img
    #I get to see the image in browser
    response_dict = {
        'crop_img' : crop_img,
    }

    template_name = 'canvas/step7.html'
    response = render_to_response(template_name, response_dict, context_instance=RequestContext(request))
    return response

在canvas / step7.html中,我尝试了以下内容:

<img src="{{ crop_img.url }}" />
<img src="{{ crop_img.file.url }}" />

但当然这不起作用。

基于Google AppEngine Image documentation,我知道execute_transforms()函数将图像的编码表示作为字符串返回。所以我想我错过了将字符串转换为文件的步骤......也许?

有人能指出我正确的方向,以便使用django在模板中显示裁剪吗?

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

我终于设法解决了我的问题。我遵循了voscausa的建议,但我发布了一个适合Django的解决方案。

<强>背景 我无法使用get_serving_url,因为我需要裁剪特定的坐标。 方法 execute_transforms 返回一个字符串。 从blobstore

可以更好地提供作物

<强>解决方案

models.py

from djangotoolbox.fields import BlobField
class ImageModel(models.Model):
    file = models.FileField(upload_to="images")

class MiniCanvas(models.Model):
    crop = BlobField()

views.py

from my_app.models import ImageModel, MiniCanvas
from google.appengine.api import images

def view_that_crops(request):
 if request.method == 'POST':
        #Do stuff here
    else:
        #The pk of the selected image is stored in session
        img_file = ImageModel.objects.get(pk=request.session[SESSION_KEY]['image_pk'])
        img = images.Image(blob_key=str(img_file.file.file.blobstore_info.key())) 
        img.resize(height=300)
        img.crop(left_x=0.0, top_y=0.0, right_x=0.5, bottom_y=1.0)

        #This method returns the image's encoded representation as a string
        crop_img = img.execute_transforms(output_encoding=images.JPEG)
        #I can save the string as a BlobField in my model
        mini_canvas = MiniCanvas.objects.create(crop=crop_img)
        response_dict = {
            'mini_canvas_pk' : mini_canvas.pk,
        }

        template_name = 'canvas/step7.html'
        response = render_to_response(template_name, response_dict, context_instance=RequestContext(request))
        return response

#This function will be called in template
def show_crop(request, crop_pk):
    try:
        crop = MiniCanvas.objects.get(pk=crop_pk)
    except MiniCanvas.DoesNotExist:
        crop = None
    if not crop:
        #TODO: return a default image maybe?
        return HttpResponse()
    #Don't forget content_type
    return HttpResponse(crop.crop, content_type="image/jpeg")

urls.py

from my_app.views import show_crop, view_that_crops
urlpatterns = patterns('',
    url(r'^cropper/(?P<crop_pk>\d+)/$', show_crop, name='show_crop'),
)

模板'canvas / step7.html'

<img src="{% url show_crop mini_canvas_pk %}" alt="The crop you were looking for" />

就是这样。我不明白的是如何在模板中调用voscausa建议的处理程序。 (我是新来的:()

这是关于如何裁剪图像并在模板中显示图像的完整示例。但是,我相信可以(而且应该)做出一些改进。如:裁剪作为后台任务,以避免性能问题;或使用memecache ......

我希望这有助于其他人!

编辑我应该补充一点,models.py中的BlobField最初并不明显。由于discussion in this google group,我找到了它。

答案 1 :(得分:0)

您必须将裁剪后的图像保存在上述代码的数据存储区或blobstore中,然后才能使用缓存(memcache)。

现在你可以写一个处理程序来提供图片网址。

Blobstore Handler示例:

class ImgServe(blobstore_handlers.BlobstoreDownloadHandler):

    def get(self, resource):    # resource contains the blob_key + image type (like .jpeg)                                   

        (key, _, _) = resource.rpartition('.')
        blob_info = blobstore.BlobInfo.get(key)
        self.response.headers[str('Content-Type')] = str(blob_info.content_type)     
        self.send_blob(blob_info, save_as=True)

作为替代方案,您还可以使用get_serving_url进行动态裁剪。在这种情况下,您不必自己裁剪图像,但使用Google高性能图像服务和get_serving_url来获取图像。在这种情况下,您不必编写处理程序。

另见答案:Python Google App Engine Image object