Django的可疑行动

时间:2009-12-23 00:32:32

标签: python django

我在尝试删除上传的图片时遇到了问题。

错误如下:

SuspiciousOperation: Attempted access to '/media/artists/12-stones/154339.jpg' denied.

在阅读之后看起来错误是由于它正在寻找错误位置的图像(注意第一个斜杠,/ media /在文件系统上不存在)

我的MEDIA_ROOT和MEDIA_URL是:

MEDIA_ROOT = '/home/tsoporan/site/media/'
MEDIA_URL = "/media/

我的模型upload_to参数传递了这个函数:

def get_artist_path(instance, filename):
  return os.path.join('artists', slugify(instance.name), filename)

我的问题是:

1)如何解决此问题以备将来上传?

2)是否可以在不重新上载的情况下修复当前图像的路径?

此致 泰特斯

11 个答案:

答案 0 :(得分:58)

当我在upload_to定义中添加一个前导斜杠时出现此错误。

BAD

pic = models.ImageField(upload_to="/uploads/product_images/")

GOOD

pic = models.ImageField(upload_to="uploads/product_images/")

答案 1 :(得分:30)

嗯,代码中的一点点问题表明,可能会有更深层次的错误信息在整个过程中被同质化。

在django / core / files / storage.py第210行(这是1.1.1)中我们有:

def path(self, name):
    try:
        path = safe_join(self.location, name)
    except ValueError:
        raise SuspiciousOperation("Attempted access to '%s' denied." % name)
    return smart_str(os.path.normpath(path))

所以错误必须来自safe_join()。

在django / utils / _os.py中,我们有以下内容。请注意它在第三行到最后一行引发的ValueError:

===========================

def safe_join(base, *paths):
    """
    Joins one or more path components to the base path component intelligently.
    Returns a normalized, absolute version of the final path.

    The final path must be located inside of the base path component (otherwise
    a ValueError is raised).
    """
    # We need to use normcase to ensure we don't false-negative on case
    # insensitive operating systems (like Windows).
    base = force_unicode(base)
    paths = [force_unicode(p) for p in paths]
    final_path = normcase(abspathu(join(base, *paths)))
    base_path = normcase(abspathu(base))
    base_path_len = len(base_path)
    # Ensure final_path starts with base_path and that the next character after
    # the final path is os.sep (or nothing, in which case final_path must be
    # equal to base_path).
    if not final_path.startswith(base_path) \
       or final_path[base_path_len:base_path_len+1] not in ('', sep):
        raise ValueError('the joined path is located outside of the base path'
                         ' component')
    return final_path

==================

嗯,“连接路径位于基本路径组件之外”。现在有一些对abspathu()的调用(在此例程之上定义,对于NT而言与其他操作系统不同)。 abspathu()通过修改当前工作目录os.cwdu()将所有非绝对路径转换为绝对路径。

问题:您的媒体目录中是否有符号链接(符号链接)?换句话说,它不是项目目录的直接子项?我不知道这是否是一个有效的问题,它只是突然出现了。

问题:哪些 传递给safe_join()的self.locationname的值?

Wild-ass-guess:self.location是空的吗?

另一个疯狂猜测:MEDIA_ROOT是否以某种方式变为/media/

如果您安装了自己的Django副本(这并不难),尝试在这些例程中添加一些print语句,然后将其作为开发服务器运行。打印输出将转到控制台。

更新:嗯。你说“2)self.location和name的值是:/ home / tsoporan / site / media和/media/albums/anthem-for-the-underdog/30103635.jpg”

以下路径是否有意义?

"/home/tsoporan/site/media/media/albums/anthem-for-the-underdog"

请注意... / media / media / ...在那里。

另外,这是什么操作系统? Django rev?

答案 2 :(得分:12)

作为对其他人的说明,如果您要查找的静态文件资源中有一个双“//”,则可能会导致此问题。

{{ STATIC_URL }}/style.css # Causes the issue it should be
{{ STATIC_URL }}style.css

答案 3 :(得分:2)

啊,想出来,有点尴尬,但事实证明错误更高了。我通过脚本插入这些图像,然后重新认识到我的路径以/ media /开始。

现在我有大约4000张错误路径的图片...有没有办法以某种方式修改所有这些图像的路径?还是需要重新加载?

谢谢大家,为我的错误道歉。

答案 4 :(得分:2)

你真的应该问一个新问题。请尝试以下方法:

编写一个独立的django脚本,如下所示:

from django.core.management import setup_environ
from mysite import settings
setup_environ(settings)
from django.db import transaction

from app.models import Album # or whatever your model name is

for a in Album.objects.all():
    # Do something to cleanup the filename.
    # NOTE! This will not move the files, just change the value in the field.
    a.filename = re.sub(r'^/media', '', a.filename)
    a.save()

transaction.commit_unless_managed() # flush all changes

答案 5 :(得分:1)

如果你想使用其他位置,例如/ data / images / myfile /,你应该在django settings.py文件中将MEDIA_ROOT设置为/ data / images。

答案 6 :(得分:0)

我发现,通过使用愚蠢的print语句,某些媒体文件在其网址路径中以/media为前缀。虽然默认存储选项会处理此问题,但如果您使用S3BotoStorage中的django-storages,则会出现问题。

所以我通过覆盖_normalize_name来修复它(由@ peter-rowell的回答引导):

class MediaStorage(FixedUrlBotoStorage):
    location = settings.MEDIAFILES_LOCATION

    # Overriding function because some media files are stored with '/media' prefixed (which causes problems)
    def _normalize_name(self, name):
        if name.startswith('/media'):
            name = name.lstrip('/media')
        return super(MediaStorage, self)._normalize_name(name)

答案 7 :(得分:0)

如果您的临时文件不属于MEDIA_ROOT文件夹,请使用Inputs display none <div class="container"> <div class="row"> <div class="line"></div> <div class="square"></div> <div class="line"></div> </div> <div class="row inputs none"> <input/> <input/> <input/> <input/> </div> </div> Inputs visible <div class="container"> <div class="row"> <div class="line"></div> <div class="square"></div> <div class="line"></div> </div> <div class="row inputs"> <input/> <input/> <input/> <input/> </div> </div> Inputs reduced font-size <div class="container"> <div class="row"> <div class="line"></div> <div class="square"></div> <div class="line"></div> </div> <div class="row inputs reduce-font-size"> <input/> <input/> <input/> <input/> </div> </div>。这不会引发SimpleUploadedFile错误:

SuspiciousOperation

如果您的临时文件已经是MEDIA_ROOT的一部分,请使用upload_file = SimpleUploadedFile(name=basename(out_file), content=open(out_file, 'rb').read()) object = YourModel.objects.create(file=upload_file) 。如果要将现有的Django文件链接到对象,这很有用。

File

答案 8 :(得分:0)

我以一种非常简单的方式解决了这个问题,转到此文件夹中的 utils.py

djk\lib\site-packages\django\core\files\utils.py         

(djk 是 virtualenv 的名字)

在文件中添加 line 7line 8 python 注释,就是这样,工作完成了。

答案 9 :(得分:-1)

答案 10 :(得分:-1)

我也遇到了这个错误。通过调试我发现引发了以下异常。

SuspiciousOperation(u"Attempted access to '2015-03-19-08:29:51-2-f8945842891244629dfd0c0af4c72a9c.pdf' denied.",)

BTW,我使用django-storages(v1.1.8)将我的媒体文件存储到S3上(使用S3boto后端)。我正在使用django 1.7.6。

但是,如果我切换到存储文件名与冒号(:)它似乎工作。我还没弄明白,根本原因是什么。只是发布这个以防这对其他人有帮助。显然,django或django-storages不喜欢带冒号的文件名。