简体   繁体   English

图像从部署到 heroku 的 django web 应用程序消失

[英]Images disappears from django web app deployed to heroku

I am working on a django project, writing rest APIs with django rest framework to use them in android application, my main idea is develop back end in django and front end in android, project is deployed on heroku. I am working on a django project, writing rest APIs with django rest framework to use them in android application, my main idea is develop back end in django and front end in android, project is deployed on heroku. My application contains some inventory with the item pictures, issue is while i am uploading the image it successfully upload the image but after some time or more specifically after some hours the image disappears by it self.我的应用程序包含一些带有物品图片的库存,问题是当我上传图像时它成功上传了图像,但经过一段时间或更具体地说是几个小时后图像自行消失。

Here is my setting.py file这是我的 setting.py 文件

"""
Django settings for forBirds project.

Generated by 'django-admin startproject' using Django 3.0.6.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os
import dj_database_url

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ''

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'account',
    'rest_framework',
    'rest_framework.authtoken',
    'Birds',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

ROOT_URLCONF = 'forBirds.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'forBirds.wsgi.application'

# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': '',
        "USER": "",
        "PASSWORD": "",
        "HOST": "",
        "PORT": "",
    }
}

# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators


REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework.authentication.BasicAuthentication",
        "rest_framework.authentication.SessionAuthentication",
        "rest_framework.authentication.TokenAuthentication"
    ),
    "DEFAULT_PERMISSIONS_CLASSES": (
        "rest_framework.permissions.IsAuthenticated"
    ),
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 1,
}
AUTH_USER_MODEL = 'account.Account'

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
PROJECT_ROOT = os.path.join(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# Extra lookup directories for collectstatic to find static files
STATICFILES_DIRS = (
    os.path.join(PROJECT_ROOT, 'static'),
)

#  Add configuration for static files storage using whitenoise
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

prod_db = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(prod_db)


The Heroku filesystem is ephemeral - that means that any changes to the filesystem whilst the dyno is running only last until that dyno is shut down or restarted. Heroku 文件系统是短暂的 - 这意味着在测功机运行时对文件系统的任何更改只会持续到该测功机关闭或重新启动。 Each dyno boots with a clean copy of the filesystem from the most recent deploy.每个测功机都使用最新部署的文件系统的干净副本启动。

Instead of storing uploaded files to disk, the best practice is to leverage a cloud file storage service such as Amazon's S3.最好的做法是利用云文件存储服务,例如亚马逊的 S3,而不是将上传的文件存储到磁盘。

When you upload a file to the Django admin, it looks at the DEFAULT_FILE_STORAGE settings configuration to determine how to store that file.当您将文件上传到 Django 管理员时,它会查看DEFAULT_FILE_STORAGE设置配置以确定如何存储该文件。 By default , it uses django.core.files.storage.FileSystemStorage , which means that it is writing those uploaded files to the dyno's filesystem at the location defined by MEDIA_ROOT . 默认情况下,它使用django.core.files.storage.FileSystemStorage ,这意味着它将那些上传的文件写入到由MEDIA_ROOT定义的位置的测功机文件系统中。

The issue is, dynos are ephemeral, and they can be destroyed, restarted, and moved without any warning, which replaces your filesystem .问题是,测功机是短暂的,它们可以在没有任何警告的情况下被销毁、重新启动和移动, 从而替换您的文件系统 This means that those uploaded files are just deleted without a trace, but the ImageField reference still thinks they are there.这意味着那些上传的文件只是被删除而没有任何痕迹,但ImageField引用仍然认为它们在那里。

The solution to this issue is to update the project's DEFAULT_FILE_STORAGE to use something permanent, such as an s3-compatible object store .此问题的解决方案是更新项目的DEFAULT_FILE_STORAGE以使用永久的东西,例如与s3 兼容的 object 存储 In Heroku & Django land, a common solution is to use django-storages alongside Heroku's Bucketeer add-on .在 Heroku 和 Django 领域,一个常见的解决方案是使用django-storages storages 和Heroku 的 Bucketeer 插件 This solution uploads your files to a persistent data store that survives dyno restarts, instead of writing to the dyno file system which gets deleted frequently.此解决方案将您的文件上传到在 dyno 重新启动后仍然存在的持久数据存储,而不是写入经常被删除的 dyno 文件系统。

I know that this can be daunting, so I wrote up this article with a pretty good write-up of the Heroku + Bucketeer process.我知道这可能会让人望而生畏,所以我写了这篇文章,对 Heroku + Bucketeer 过程进行了很好的描述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM