1

I have the following situation. Project files was stored in ~/django-apps/app-old/app. For some reasons I move files to ~/django-apps/app . Application have some images, stored with use of ImageField. In database images have paths like so:

~/django-apps/app-old/app/media/images/blabla.jpeg

So, I need to fix this paths in database to look like this:

~django-apps/app/media/images/blabla.jpeg

I try to write management command for to do this:

from django.core.management.base import BaseCommand, CommandError
from books.models import Book
import string

class Command(BaseCommand):
    help = ''

    def handle(self, *args, **options):
        books = Book.objects.all()
        total = len(books)
        curr = 1

        for book in books:
            print "%d/%d" % (curr, total)
            if book.cover_url != "":
                book.cover_url.path = string.replace(book.cover_url.path, "app-old/", "")
                book.save()
            curr+=1

By using this command I get following error:

Traceback (most recent call last):
  File "manage.py", line 11, in <module>
    execute_manager(settings)
  File "/usr/local/lib/python2.6/dist-packages/django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "/usr/local/lib/python2.6/dist-packages/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.6/dist-packages/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.6/dist-packages/django/core/management/base.py", line 220, in execute
    output = self.handle(*args, **options)
  File "/var/www/dizpers/data/django-apps/app/books/management/commands/fix-covers-path.py", line 23, in handle
    book.cover_url.path = string.replace(book.cover_url.path, "bparser-old/", "")
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/files.py", line 65, in _get_path
    return self.storage.path(self.name)
  File "/usr/local/lib/python2.6/dist-packages/django/core/files/storage.py", line 234, in path
    raise SuspiciousOperation("Attempted access to '%s' denied." % name)
django.core.exceptions.SuspiciousOperation: Attempted access to '/var/www/dizpers/data/django-apps/app-old/app/media/covers/a3d9545d3a17bb68a91749019c95357d.jpeg' denied.

Why I get this error message? How I can fix image's path?

UPD1

My model contain ImageField like this:

cover_url = models.ImageField(upload_to=os.path.join(MEDIA_ROOT, "covers"), null=True, default=None)

UPD2

Path property is readonly

Dmitry Belaventsev
  • 6,347
  • 12
  • 52
  • 75

2 Answers2

3

This should work

for book in books:
        print "%d/%d" % (curr, total)
        if book.cover_url != "":
            new_path = string.replace(book.cover_url.path, "app-old/", "")
            book.cover_url = new_path
            book.save()
        curr+=1
Rakesh
  • 81,458
  • 17
  • 76
  • 113
  • The error like the one in my question. `SuspiciousOperation: Attempted access to '/var/www/dizpers/data/django-apps/app-old/app/media/covers/a3d9545d3a17bb68a91749019c95357d.jpeg' denied.` – Dmitry Belaventsev Aug 27 '12 at 17:43
1

You get this message because the default file system storage prevents usage of absolute path for security reasons.

If you really want to use an absolute path

django-documents forces absolute paths for security reasons, this is how:

from django.core.files.storage import FileSystemStorage


fs = FileSystemStorage(location=UPLOAD_TO)


class Document(models.Model):
    file = models.FileField(storage=fs, upload_to=UPLOAD_TO)

Where UPLOAD_TO can be an absolute path.

-- UPDATE IN REPLY TO QUESTION UPDATE --

If you don't need such security

Then you should read the documentation on FileField:

FileField.upload_to A local filesystem path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute.

In your case, upload_to='covers' is sufficient.

Note that relative paths should be stored in the database.

jpic
  • 32,891
  • 5
  • 112
  • 113
  • I added to the question update - description of my ImageField. I use there absolute path? I shouldn't do it? – Dmitry Belaventsev Aug 27 '12 at 15:00
  • It doesn't matter if it is an ImageField, because ImageField inherits from FileField :) Try it and you'll see ;) – jpic Aug 27 '12 at 15:35
  • so, I need to modify my model? and yes, you are right that ImageField inerits from FileField. I speak about absolute path in this field instead of relative - maybe I should use relative path in my ImageField and maybe it will solve the problem? – Dmitry Belaventsev Aug 27 '12 at 15:44
  • I have one question about your updated answer. What kind of security problems I can face, when simply modify model to use relative path (the second way "If you don't need such security")? – Dmitry Belaventsev Aug 27 '12 at 16:45
  • 1
    If MEDIA_ROOT is public, then files uploaded to MEDIA_ROOT are public. This is good for example for avatars and such, but not for confidential documents. – jpic Aug 27 '12 at 17:54