如何修复以下Django错误:“类型:IOError”“值:[Errno 13] 权限被拒绝”
我正在跟着一个Django的教程,里面要求在管理员界面保存图片后,生成一些图片缩略图。我还使用了Python的tempfile模块来保存一个临时文件名。
不过,我一直遇到以下错误:
"Type: IOError" "Value: [Errno 13] Permission denied: 'c:\\docume~1\\myname\\locals~1\\temp\\somefilename'"
这是我正在使用的代码
设置
MEDIA_ROOT = '/home/myname/projectname/media/'
MEDIA_URL = 'http://127.0.0.1:8000/media/'enter code here
models.py
from string import join
import os
from PIL import Image as PImage
from settings import MEDIA_ROOT
from os.path import join as pjoin
from tempfile import *
from string import join
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
from django.core.files import File
class Image(models.Model):
title = models.CharField(max_length=60, blank=True, null=True)
image = models.FileField(upload_to="images/")
thumbnail = models.ImageField(upload_to="images/", blank=True, null=True)
tags = models.ManyToManyField(Tag, blank=True)
albums = models.ManyToManyField(Album, blank=True)
created = models.DateTimeField(auto_now_add=True)
rating = models.IntegerField(default=50)
width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
user = models.ForeignKey(User, null=True, blank=True)
thumbnail2 = models.ImageField(upload_to="images/", blank=True, null=True)
def save(self, *args, **kwargs):
#Save image dimensions
super(Image, self).save(*args, **kwargs)
im = PImage.open(pjoin(MEDIA_ROOT, self.image.name))
self.width, self.height = im.size
# large thumbnail
fn, ext = os.path.splitext(self.image.name)
im.thumbnail((128,128), PImage.ANTIALIAS)
thumb_fn = fn + "-thumb2" + ext
tf2 = NamedTemporaryFile()
im.save(tf2.name, "JPEG")
self.thumbnail2.save(thumb_fn, File(open(tf2.name)), save=False)
tf2.close()
# small thumbnail
im.thumbnail((40,40), PImage.ANTIALIAS)
thumb_fn = fn + "-thumb" + ext
tf = NamedTemporaryFile()
im.save(tf.name, "JPEG")
self.thumbnail.save(thumb_fn, File(open(tf.name)), save=False)
tf.close()
super(Image, self).save(*args, **kwargs)
def size(self):
"""Image size."""
return "%s x %s" % (self.width, self.height)
def __unicode__(self):
return self.image.name
def tags_(self):
lst = [x[1] for x in self.tags.values_list()]
return str(join(lst, ', '))
def albums_(self):
lst = [x[1] for x in self.albums.values_list()]
return str(join(lst, ', '))
def thumbnail_(self):
return """<a href="/media/%s"><img border="0" alt="" src="/media/%s" /></a>""" % (
(self.image.name, self.thumbnail.name))
thumbnail.allow_tags = Trueenter code here
管理员界面
class ImageAdmin(admin.ModelAdmin):
# search_fields = ["title"]
list_display = ["__unicode__", "title", "user", "rating", "size", "tags_","albums_",
"thumbnail", "created"]
list_filter = ["tags", "albums", "user"]
def save_model(self, request, obj, form, change):
obj.user = request.user
obj.save()
我知道在Django中使用图片缩略图有很多更有效的方法,但我想知道为什么在这种方式下使用缩略图时,我总是会遇到这个权限错误。
非常感谢大家的帮助。谢谢。
2 个回答
我很遗憾,但mikej的回答根本不是解决办法,因为PIL支持这两种语法示例。可能是我从某个地方复制了同样的软件,它在我的Linux机器上运行得很好,但在Windows 7上却不行。问题不在于图像保存的命令,而是在于下面这个命令。
self.thumbnail.save(thumb_fn, File(open(tf.name)), save=False)
... 这个命令导致了权限被拒绝的错误,因为文件仍然是打开状态,Windows上不能重复打开同一个文件。你可以通过以下方式模拟同样的错误:
copyfile(tf2.name,"some-new-filepath")
一个合适的解决方法是:
- 创建一个临时文件,关闭时不会被删除
- 保存并关闭缩略图
- 手动删除临时文件
无论你怎么保存缩略图,这个方法都能奏效。
tf = NamedTemporaryFile(delete=False)
im.save(tf.name, "PNG")
#im.save(tf, "PNG")
tf.close()
copyfile(tf.name,"some-new-filepath")
os.remove(tf.name)
我觉得这个问题跟Windows上NamedTemporaryFile
的表现有关。根据文档的说明:
这个函数的工作方式和
TemporaryFile()
完全一样,不同的是这个文件在文件系统中有一个可见的名字(在Unix系统中,目录项不会被删除)。你可以通过文件对象的名字属性来获取这个名字。不过,是否可以在命名的临时文件仍然打开的情况下,第二次用这个名字打开文件,因平台而异(在Unix上可以;在Windows NT或更高版本上则不可以)。
(强调是我加的)
在这一行:
im.save(tf2.name, "JPEG")
save
大概是试图打开这个文件,以便可以写入内容。
根据PIL文档,你可以给save
传递一个文件对象,而不是文件名,所以把上面的内容替换为
im.save(tf2, "JPEG")
可能会有所帮助。