使用 Pyramid 和 SQLAlchemy 上传图片

Image uploads with Pyramid and SQLAlchemy

用Pyramid、SQLAlchemy和deform应该如何上传图片文件?最好这样人们可以轻松地在模板中获取图像缩略图标签。需要什么配置(存储图片在文件系统后端等)。

这个问题绝不是专门问一件事。然而,这里是一个视图,它定义了一个带有变形的表单上传,测试有效图像文件的输入,将记录保存到数据库,然后甚至将其上传到亚马逊 S3。这个例子显示在我所引用的各种文档的链接下。 使用变形上传文件 see the documentation.

如果您想了解如何将图像文件保存到磁盘,请参阅这篇文章see the official documentation

那么如果你想学习如何使用 SQLAlchemy 保存新项目 see the SQLAlchemy tutorial.

如果你想问一个更好的问题,每个部分都可以给出更精确的详细答案,那么请这样做。

@view_config(route_name='add_portfolio_item', 
renderer='templates/user_settings/deform.jinja2',
permission='view')
def add_portfolio_item(request):

    user = request.user
    # define store for uploaded files
    class Store(dict):
        def preview_url(self, name):
            return ""

    store = Store()
    # create a form schema
    class PortfolioSchema(colander.MappingSchema):
        description = colander.SchemaNode(colander.String(),
            validator = Length(max=300),
            widget = text_area,
            title = "Description, tell us a few short words desribing your picture")
        upload = colander.SchemaNode(
                deform.FileData(),
                widget=widget.FileUploadWidget(store))

    schema = PortfolioSchema()
    myform = Form(schema, buttons=('submit',), action=request.url)

    # if form has been submitted
    if 'submit' in request.POST:

        controls = request.POST.items()
        try:
            appstruct = myform.validate(controls)
        except ValidationFailure, e:
            return {'form':e.render(), 'values': False}
        # Data is valid as far as colander goes

        f = appstruct['upload']
        upload_filename = f['filename']
        extension = os.path.splitext(upload_filename)[1]
        image_file = f['fp']

        # Now we test for a valid image upload
        image_test = imghdr.what(image_file)
        if image_test == None:
            error_message = "I'm sorry, the image file seems to be invalid is invalid"
            return {'form':myform.render(), 'values': False, 'error_message':error_message,
            'user':user}


        # generate date and random timestamp
        pub_date = datetime.datetime.now()
        random_n = str(time.time())

        filename = random_n + '-' + user.user_name + extension
        upload_dir = tmp_dir
        output_file = open(os.path.join(upload_dir, filename), 'wb')

        image_file.seek(0)
        while 1:
            data = image_file.read(2<<16)
            if not data:
                break
            output_file.write(data)
        output_file.close()

        # we need to create a thumbnail for the users profile pic
        basewidth = 530
        max_height = 200
        # open the image we just saved
        root_location = open(os.path.join(upload_dir, filename), 'r')
        image = pilImage.open(root_location)
        if image.size[0] > basewidth:
            # if image width greater than 670px
            # we need to recduce its size
            wpercent = (basewidth/float(image.size[0]))
            hsize = int((float(image.size[1])*float(wpercent)))
            portfolio_pic = image.resize((basewidth,hsize), pilImage.ANTIALIAS)
        else:
            # else the image can stay the same size as it is
            # assign portfolio_pic var to the image
            portfolio_pic = image

        portfolio_pics_dir = os.path.join(upload_dir, 'work')

        quality_val = 90
        output_file = open(os.path.join(portfolio_pics_dir, filename), 'wb')
        portfolio_pic.save(output_file, quality=quality_val)

        profile_full_loc = portfolio_pics_dir + '/' + filename

        # S3 stuff
        new_key = user.user_name + '/portfolio_pics/' + filename
        key = bucket.new_key(new_key)
        key.set_contents_from_filename(profile_full_loc)
        key.set_acl('public-read')

        public_url = key.generate_url(0, query_auth=False, force_http=True)

        output_dir = os.path.join(upload_dir)
        output_file = output_dir + '/' + filename
        os.remove(output_file)
        os.remove(profile_full_loc)

        new_image = Image(s3_key=new_key, public_url=public_url,
         pub_date=pub_date, bucket=bucket_name, uid=user.id,
         description=appstruct['description'])
        DBSession.add(new_image)
        # add the new entry to the association table.
        user.portfolio.append(new_image)

        return HTTPFound(location = route_url('list_portfolio', request))

    return dict(user=user, form=myform.render())