Подозрительная операция Джанго - PullRequest
27 голосов
/ 23 декабря 2009

У меня возникла проблема при попытке удалить загруженные изображения.

Ошибка заключается в следующем:

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) Можно ли исправить пути к моим текущим изображениям без повторной загрузки?

С уважением, Titus

Ответы [ 9 ]

58 голосов
/ 01 июня 2011

Я получил эту ошибку, когда поставил начальную косую черту в определении upload_to.

BAD

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

GOOD

pic = models.ImageField(upload_to="uploads/product_images/")
30 голосов
/ 23 декабря 2009

Что ж, небольшой перебор в коде показывает, что может быть более глубокое сообщение об ошибке, которое было гомогенизировано на этом пути.

в 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 (), текущий рабочий каталог.

Вопрос: У вас случайно есть символическая ссылка (символическая ссылка) на ваш медиа-каталог? Другими словами, это не прямой потомок каталога проекта? Я не знаю, если это правильный вопрос, он просто выпал из моей головы.

Вопрос: Какие являются значениями self.location и name, которые передаются в safe_join ()?

Wild-ass-догадка: self.location пусто?

Еще одно безумное предположение: MEDIA_ROOT как-то изменилось на /media/?

Если у вас установлена ​​собственная копия Django (это не сложно сделать), попробуйте добавить в эти подпрограммы некоторые операторы печати, а затем запустите ее в качестве сервера разработки. Вывод на печать поступит на консоль.

Обновление: Хммм. Вы сказали: «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 / ... там.

Кроме того, что это за ОС? Джанго, рев?

12 голосов
/ 05 июля 2012

Как примечание для других, эта проблема может быть вызвана тем, что у вас есть двойной символ «//» в статическом файловом ресурсе, который вы ищете.

{{ STATIC_URL }}/style.css # Causes the issue it should be
{{ STATIC_URL }}style.css
2 голосов
/ 23 декабря 2009

Вы действительно должны просто задать новый вопрос по этому вопросу. Попробуйте следующее:

Напишите автономный скрипт 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
2 голосов
/ 23 декабря 2009

А, разобрался, немного неловко, но оказывается, ошибка была выше. Я подключал эти изображения с помощью скрипта и, перебирая его, снова понял, что мои пути начинаются с /media/.

Теперь у меня есть около 4000 изображений с неправильными путями ... есть ли способ как-то изменить пути для всех этих изображений? Или нужно будет перезагружать?

Спасибо всем, извиняюсь за мою ошибку.

1 голос
/ 23 апреля 2012

, если вы хотите использовать другое местоположение ,, такое как / data / images / myfile /, вы должны установить для MEDIA_ROOT значение / data / images в файле django settings.py.

0 голосов
/ 25 января 2016

Я обнаружил, используя тупые операторы print, что некоторые медиа-файлы имеют префикс /media в своих URL-путях. Хотя опция хранения по умолчанию справляется с этим, возникает проблема, если вы используете 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)
0 голосов
/ 19 марта 2015

Я тоже получил эту ошибку. При отладке я обнаружил, что возникает следующее исключение.

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

Кстати, я использую django-хранилища (v1.1.8) для хранения своих медиафайлов на S3 (используя бэкэнд S3boto). Я использую Django 1.7.6.

Но если я переключусь на сохранение с именем файла без двоеточий (:), похоже, это сработает. Я еще не выяснил, в чем причина. Просто отправьте это на тот случай, если это поможет кому-то еще. По-видимому, django или django-хранилища не любят имена файлов с двоеточиями.

0 голосов
/ 12 февраля 2011

Эта ошибка исправлена ​​в django 1.2.5. Смотри http://docs.djangoproject.com/en/dev/releases/1.2.5/#filefield-no-longer-deletes-files

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...