OSError at /blog/create [Errno 13] Permission denied: '/static' during image upload in Django

OSError at /blog/create [Errno 13] Permission denied: '/static' during image upload in Django

所以我正在通过构建自己的博客应用程序来练习 Django,但我无法弄清楚为什么在尝试使用 ImageField 上传 header 图像时会出现此错误。我将 wsgi 配置为使用正确的用户,如下所示。并且我确保用户在静态目录中具有完全权限。关于这个问题,我在这里看到了一些类似的帖子,但 none 已经为我修复了它。

这是回溯:

Environment:


Request Method: POST
Request URL: http://example.com/blog/create

Django Version: 1.8.4
Python Version: 2.7.6
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'app',
 'grappelli',
 'filebrowser',
 'tinymce',
 'django.contrib.admin')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')


Traceback:
File "/var/www/example.com/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/www/example.com/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  22.                 return view_func(request, *args, **kwargs)
File "/var/www/example.com/mysite/app/views.py" in create_post
  93.           post.save()
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/base.py" in save
  734.                        force_update=force_update, update_fields=update_fields)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/base.py" in save_base
  762.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/base.py" in _save_table
  846.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/base.py" in _do_insert
  885.                                using=using, raw=raw)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/manager.py" in manager_method
  127.                 return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/query.py" in _insert
  920.         return query.get_compiler(using=using).execute_sql(return_id)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
  973.             for sql, params in self.as_sql():
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in as_sql
  931.                 for obj in self.query.objs
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/fields/files.py" in pre_save
  315.             file.save(file.name, file, save=False)
File "/var/www/example.com/lib/python2.7/site-packages/django/db/models/fields/files.py" in save
  94.             self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "/var/www/example.com/lib/python2.7/site-packages/django/core/files/storage.py" in save
  64.         name = self._save(name, content)
File "/var/www/example.com/lib/python2.7/site-packages/django/core/files/storage.py" in _save
  223.                     os.makedirs(directory)
File "/usr/lib/python2.7/os.py" in makedirs
  150.             makedirs(head, mode)
File "/usr/lib/python2.7/os.py" in makedirs
  157.     mkdir(name, mode)

Exception Type: OSError at /blog/create

这里是 settings.py:

"""
Django settings for example project.
"""

from os import path
PROJECT_ROOT = path.dirname(path.abspath(path.dirname(__file__)))

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ALLOWED_HOSTS = (
    '.example.com',
    '.example.com.',
)

ADMINS = (
    # ('Your Name', 'your_email@example.com'),
    ('My Name', 'myemail@gmail.com'),
)

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '...',
        'USER': '...',
        'PASSWORD': '...',
        'HOST': '...',
        'PORT': '3306',
        'CONN_MAX_AGE': None
    }
}

LOGIN_URL = '/login'

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# On Unix systems, a value of None will cause Django to use the same
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'America/Chicago'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = '/static/media/'



# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'

# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = '/var/www/example.com/mysite/static/'

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

# Additional locations of static files
STATICFILES_DIRS = (
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

# List of finder classes that know how to find static files in 
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

# Make this unique, and don't share it with anybody.
SECRET_KEY = '...'

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.request',
)

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
#     'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

#SESSION_COOKIE_SECURE = True
#CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
X_FRAME_OPTIONS = 'DENY'

ROOT_URLCONF = 'mysite.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'example.wsgi.application'

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or
    # "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)


INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',
    #'disqus',
    'grappelli',
    'filebrowser',
    'tinymce',
    # Uncomment the next line to enable the admin:
    'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)



# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}

# Specify the default test runner.
TEST_RUNNER = 'django.test.runner.DiscoverRunner'

TINYMCE_JS_ROOT = '/var/www/example/mysite/static/tiny_mce'
TINYMCE_JS_URL = 'http://54.152.243.113/static/tiny_mce/tiny_mce_src.js'
TINYMCE_COMPRESSOR = True

FILEBROWSER_MEDIA_ROOT = MEDIA_ROOT
FILEBROWSER_MEDIA_URL = MEDIA_URL
FILEBROWSER_DIRECTORY = ''

阿帕奇 mysite.conf:

ServerSignature off
Group varwwwusers 

<VirtualHost *:80> 
     ServerAdmin webmaster@example.com
     ServerName example.com
     ServerAlias www.example.com
     DocumentRoot /var/www/example.com/mysite/
     ErrorLog /var/www/example.com/logs/error.log 
     CustomLog /var/www/example.com/logs/access.log combined

     Alias /robots.txt /var/www/example.com/mysite/app/static/robots.txt
     Alias /favicon.ico /var/www/example.com/mysite/app/static/favicon.ico

     Alias /media/ /var/www/example.com/mysite/static/media/
     Alias /static/ /var/www/example.com/mysite/static/

     <Directory /var/www/example.com/mysite/static>
        Require all granted
    </Directory>

     <Directory /var/www/example.com/mysite/static/media>
        Require all granted 
    </Directory>

     <Directory /var/www/example.com/mysite>
        <Files wsgi.py>
          Require all granted 
    </Files>
    </Directory>

    WSGIDaemonProcess example.com  user=www-data group=varwwwusers python-path=/var/www/example.com/mysite:/var/www/example.com/lib/python2.7/site-packages
    WSGIProcessGroup example.com   
    WSGIScriptAlias / /var/www/example.com/mysite/example/wsgi.py
</VirtualHost>

最后是 views.py 中似乎发生错误的部分(根据跟踪的 post.save() 调用):

@login_required
def create_post(request):
    if request.method == "POST":
        form = BlogForm(request.POST,request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.publish_date = datetime.now()
            post.save()
            return HttpResponseRedirect('/blog/page/1')
    else:
        form = BlogForm()
    return render(request, 'app/createblogpost.html', { 'title': 'Blog Poster', 'form': form, })

如果有任何不同,我将在 AWS EC2 免费套餐上托管示例站点并且数据库是 AWS RDS。任何解决这个问题的帮助将不胜感激!如果需要任何进一步的信息,请告诉我。

问题在这里:

MEDIA_ROOT = '/static/media/'

MEDIA_ROOT 应该是绝对路径(的确如此,但它没有指向正确的目录)。它应该是这样的:

MEDIA_ROOT = '/var/www/example.com/mysite/static/media'