Add S3 Storage...
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
SECRET_KEY=django-insecure-change-me
|
||||
DEBUG=True
|
||||
ALLOWED_HOSTS=localhost,127.0.0.1
|
||||
S3_ENABLE=False
|
||||
|
||||
# PostgreSQL (por defecto habilitado; si POSTGRES_ENABLED=False se usa SQLite)
|
||||
POSTGRES_ENABLED=True
|
||||
@@ -14,6 +15,17 @@ POSTGRES_PORT=5432
|
||||
# Redis
|
||||
REDIS_URL=redis://127.0.0.1:6379/1
|
||||
|
||||
# S3 (activar con S3_ENABLE=True)
|
||||
AWS_STORAGE_BUCKET_NAME=
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_S3_REGION_NAME=
|
||||
AWS_S3_ENDPOINT_URL=
|
||||
AWS_S3_CUSTOM_DOMAIN=
|
||||
AWS_S3_USE_SSL=True
|
||||
AWS_QUERYSTRING_AUTH=False
|
||||
AWS_DEFAULT_ACL=public-read
|
||||
|
||||
# Stripe
|
||||
STRIPE_PUBLISHABLE_KEY=
|
||||
STRIPE_SECRET_KEY=
|
||||
|
||||
@@ -35,6 +35,7 @@ Templates use Django's inheritance pattern:
|
||||
- **Image uploads**: Organized in `tienda/static/media/images/` via `upload_to='images/'` in ImageField
|
||||
- **Access**: Media files served automatically in development via Django's static file handler
|
||||
- **Image model**: Located in [tienda/models.py](tienda/models.py) with `ImageField(upload_to='images/')`
|
||||
- **S3 mode**: if `S3_ENABLE=True` (case-insensitive), static and media switch to S3 storages instead of the local filesystem; Nginx should proxy the app only and the browser should load asset URLs from the bucket or CDN
|
||||
|
||||
## Shipping Restrictions
|
||||
- **Zona de envío**: Solo se vende/envía dentro de la provincia de Almería
|
||||
|
||||
+4
-2
@@ -34,7 +34,9 @@ http {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# Archivos estáticos generados por collectstatic.
|
||||
# Modo local: sirve static/media desde volúmenes montados.
|
||||
# Si S3_ENABLE=True, estos bloques no se usan y el navegador debe
|
||||
# cargar los assets directamente desde el bucket o CDN.
|
||||
location /static/ {
|
||||
alias /static/;
|
||||
expires 30d;
|
||||
@@ -42,7 +44,7 @@ http {
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Archivos subidos por usuarios.
|
||||
# Archivos subidos por usuarios en modo local.
|
||||
location /media/ {
|
||||
alias /media/;
|
||||
expires 7d;
|
||||
|
||||
+43
-1
@@ -53,6 +53,21 @@ def env_int(name: str, default: int) -> int:
|
||||
return default
|
||||
return int(value)
|
||||
|
||||
|
||||
def env_str(name: str, default: str = '') -> str:
|
||||
value = os.getenv(name)
|
||||
if value is None:
|
||||
return default
|
||||
return value.strip()
|
||||
|
||||
|
||||
def env_optional_str(name: str) -> str | None:
|
||||
value = os.getenv(name)
|
||||
if value is None:
|
||||
return None
|
||||
value = value.strip()
|
||||
return value or None
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
load_dotenv(BASE_DIR / '.env')
|
||||
@@ -66,6 +81,7 @@ SECRET_KEY = os.getenv('SECRET_KEY', 'django-insecure-#g((q@lvnkt(j6)2(gvtn0px)r
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = env_bool('DEBUG', True)
|
||||
S3_ENABLE = env_bool('S3_ENABLE', False)
|
||||
|
||||
ALLOWED_HOSTS = env_list('ALLOWED_HOSTS', [
|
||||
'192.168.1.142',
|
||||
@@ -87,9 +103,11 @@ INSTALLED_APPS = [
|
||||
'compressor',
|
||||
]
|
||||
|
||||
if S3_ENABLE:
|
||||
INSTALLED_APPS.append('storages')
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
@@ -98,6 +116,9 @@ MIDDLEWARE = [
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
if not S3_ENABLE:
|
||||
MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware')
|
||||
|
||||
ROOT_URLCONF = 'proyecto.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
@@ -211,6 +232,27 @@ STORAGES = {
|
||||
},
|
||||
}
|
||||
|
||||
if S3_ENABLE:
|
||||
AWS_STORAGE_BUCKET_NAME = env_str('AWS_STORAGE_BUCKET_NAME') or None
|
||||
AWS_ACCESS_KEY_ID = env_optional_str('AWS_ACCESS_KEY_ID')
|
||||
AWS_SECRET_ACCESS_KEY = env_optional_str('AWS_SECRET_ACCESS_KEY')
|
||||
AWS_S3_REGION_NAME = env_optional_str('AWS_S3_REGION_NAME')
|
||||
AWS_S3_ENDPOINT_URL = env_optional_str('AWS_S3_ENDPOINT_URL')
|
||||
AWS_S3_CUSTOM_DOMAIN = env_optional_str('AWS_S3_CUSTOM_DOMAIN')
|
||||
AWS_S3_USE_SSL = env_bool('AWS_S3_USE_SSL', True)
|
||||
AWS_QUERYSTRING_AUTH = env_bool('AWS_QUERYSTRING_AUTH', False)
|
||||
AWS_DEFAULT_ACL = env_str('AWS_DEFAULT_ACL', 'public-read') or None
|
||||
AWS_S3_OBJECT_PARAMETERS = {}
|
||||
|
||||
STORAGES = {
|
||||
'default': {
|
||||
'BACKEND': 'tienda.storage_backends.MediaStorage',
|
||||
},
|
||||
'staticfiles': {
|
||||
'BACKEND': 'tienda.storage_backends.StaticStorage',
|
||||
},
|
||||
}
|
||||
|
||||
STATICFILES_FINDERS = [
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
|
||||
+1
-1
@@ -28,5 +28,5 @@ urlpatterns = [
|
||||
path('api/', api.urls)
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
if settings.DEBUG and not settings.S3_ENABLE:
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
@@ -14,6 +14,7 @@ Django==6.0.4
|
||||
django-appconf==1.2.0
|
||||
django-redis==5.4.0
|
||||
django_compressor==4.6.0
|
||||
django-storages[boto3]==1.14.6
|
||||
gunicorn==25.1.0
|
||||
idna==3.11
|
||||
Jinja2==3.1.6
|
||||
@@ -22,6 +23,7 @@ MarkupSafe==3.0.3
|
||||
packaging==26.0
|
||||
paypalrestsdk==1.13.3
|
||||
pillow==12.2.0
|
||||
boto3==1.42.97
|
||||
prompt_toolkit==3.0.52
|
||||
pycparser==3.0
|
||||
pyOpenSSL==26.0.0
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from storages.backends.s3 import S3ManifestStaticStorage, S3Storage
|
||||
|
||||
|
||||
class StaticStorage(S3ManifestStaticStorage):
|
||||
location = 'static'
|
||||
default_acl = 'public-read'
|
||||
querystring_auth = False
|
||||
file_overwrite = True
|
||||
object_parameters = {
|
||||
'CacheControl': 'public, max-age=31536000, immutable',
|
||||
}
|
||||
|
||||
|
||||
class MediaStorage(S3Storage):
|
||||
location = 'media'
|
||||
default_acl = 'public-read'
|
||||
querystring_auth = False
|
||||
file_overwrite = False
|
||||
object_parameters = {
|
||||
'CacheControl': 'public, max-age=604800',
|
||||
}
|
||||
Reference in New Issue
Block a user