3

画像が管理者に保存されたら、画像のサムネイルを作成する必要がある 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 で画像のサムネイルを使用するより効果的な方法があることは知っていますが、この方法でサムネイルを使用すると、このアクセス許可エラーが発生し続ける理由を知りたいと思います。

すべてのヘルプは大歓迎です。ありがとう。

4

2 に答える 2

6

これはWindowsでの動作にかかっていると思いNamedTemporaryFileます。ドキュメントから:

この関数は、ファイルがファイルシステムで表示される名前を持つことが保証されていることを除いて、TemporaryFile()とまったく同じように動作します(Unixでは、ディレクトリエントリはリンク解除されません)。その名前は、ファイルオブジェクトの名前メンバーから取得できます。名前付き一時ファイルがまだ開いているときに、その名前を使用してファイルを2回開くことができるかどうかは、プラットフォームによって異なります(Unixでは使用できますが、Windows NT以降では使用できません)。

(強調鉱山)

行で:

im.save(tf2.name, "JPEG")

saveおそらく、ファイルに書き込めるようにファイルを開こうとします。

PILドキュメントから、saveファイル名の代わりにファイルオブジェクトを渡すことができるため、上記を次のように置き換えます

im.save(tf2, "JPEG")

役立つかもしれません。

于 2010-11-08T16:49:05.503 に答える
3

残念ですが、PILは両方の構文例をサポートしているため、mikejの答えはまったく解決策ではありません。おそらく、同じソフトウェアをどこかからコピーしたもので、Linux マシンでは完全に動作しますが、Windows 7 では動作しません。その理由は、イメージの保存コマンドではなく、次のコマンドにあります。コマンド ...

self.thumbnail.save(thumb_fn, File(open(tf.name)), save=False)

...ファイルがまだ開いていて、少なくともWindowsで2回開くことができないため、許可拒否エラーが発生します。同じエラーをシミュレートできます

copyfile(tf2.name,"some-new-filepath")

適切な回避策は

  1. 閉じても削除されない一時ファイルを作成する
  2. サムネイルを保存して閉じる
  3. 一時ファイルを手動で削除する

これは、サムネイルをどのように保存しても機能します。

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)
于 2012-10-26T05:42:54.977 に答える