2 مهر 1402
تهران، خیابان آزادی، تقاطع قریب
برنامه نویسی وب

مدیریت فایل‌های مدیا و استاتیک جانگو در سرویس ابری هروکو

bucketeer

این مقاله نحوه‌ نگهداری صحیح فایل‌های مدیا و استاتیک را برای یک اپلیکیشن جانگو (Django) که بر روی هروکو (Heroku) میزبانی شده‌ است را توضیح می‌دهد. علاوه بر این، این مطلب به شما توضیح خواهد داد که چگونه می‌توانید محدودیت اضافی تعیین فایل‌های رسانه خصوصی (private) در برابر رسانه عمومی (public) را بر اساس تعاریف مدل اقناع کنید.

بنابراین، بدون هیچ مقدمه‌ای، اجازه دهید ابتدا به بررسی این موضوع بپردازیم که فایل‌های مدیا و استاتیک چه هستند و Dynos Heroku چگونه سیستم فایل خود را مدیریت می‌کند؟

فایل‌های مدیا و استاتیک جانگو (Media & Static Files) چه هستند؟

اگر با یک پروژه جانگو کار می‌کنید، به ناچار همه کدهای برنامه پایتون خود را در اطراف مجموعه‌ای از فایل‌های .py نوشته‌اید. این‌‌ها مسیرهای کد برنامه شما هستند و کاربر نهایی (امیدوارم) هرگز این فایل‌ها یا محتوای آن‌ها را نمی‌بیند.

خارج از این فایل‌های با منطق تجاری (business logic)، سرویس دهی مستقیم از سیستم فایل سرورتان امری معمول است. برای این فایل‌های استاتیک، جانگو نیاز به اجرای هیچ کدی بر روی آن‌ها ندارد؛ این فریم‌ورک فایل را جستجو می‌کند و محتویان را برای مشاهده کاربر درخواست‌کننده بازمی‌گرداند.

چند نمونه از فایل‌های استاتیک عبارت‌اند از:

  • HTMLهای تمپلیت نشده
  • فایل‌های CSS و JavaScript برای زیباجلوه دادن صفحه شما
  • عکس پروفایل کاربر
  • خروجی فایل‌های PDF

فایل‌های مدیا در جانگو نوع خاصی از فایل‌های استاتیک هستند. برخلاف‌ فایل‌های استاتیک، فایل‌های مدیا از سیستم فایل سرور نیز خوانده می‌شوند. با این حال، آن‌ها معمولاً فایل‌هایی هستند که توسط کاربران آپلود شده یا توسط اپلیکیشن شما تولید می‌شوند و با FileField و ImageField مدل مرتبط هستند. در مثال‌های بالا، تصاویر پروفایل کاربر و خروجی‌های PDf نمونه‌های رایجی از فایل مدیا هستند.

جانگو (Django) با فایل‌های مدیا و استاتیک

هنگامی که یک فایل مدیا‌ی جدید در یک برنامه وب جانگو آپلود می‌شود، فریم‌ورک پیکربندی تنظیمات DEFAULT_FILE_STORAGE را بررسی می‌کند تا نحوه ذخیره آن فایل را تعیین کند. در این حالت، به طور پیش‌فرض از کلاس django.core.files.storage.FileSystemStorage استفاده می‌شود؛ و این همان کاری است بیشتر پروژه‌ها همزمان با پیکربندی شروع می‌کنند. این پیاده‌سازی به پیکربندی MEDIA_ROOT که در فایل settings.py تعریف شده است نگاه می‌کند و محتویات فایل آپلود شده را در مسیر فایلی که به طور قطعی ایجاد شده است، در MEDIA_ROOT داده‌شده کپی می‌کند.

به‌عنوان مثال، اگر MEDIA_ROOT به عنوان /var/www/media/ تنظیم شود، تمام فایل‌های آپلودشده کپی می‌شوند و در مکانی تحت عنوان /var/www/media/ نوشته می‌شوند.

هروکو (Heroku) با فایل‌های مدیا و استتیک

تا زمانی که با یک پلتفرم کانتینر مانند Heroku شروع به کار نکنید، ذخیره این فایل‌های استاتیک بر روی سیستم فایل دیسک سرور شما مشکلی ندارد. برای توضیح این‌که چرا این مورد دارای اهمیت است، یک گام به عقب برمی‌داریم.

هنگام دانلود فابل‌ها در رایانه شخصی خود، هیچ اشکالی ندارد که این فایل‌ها در سیستم فایل (معمولاً در زیرشاخه ~/Downloads یا جایی مشابه)  نوشته شوند. این دانلود به این دلیل است که انتظار دارید عملکرد سیستم فایل کامپیوتر شما در حین ری‌استارت و شات‌داون ادامه پیدا کند. اگر فایلی را دانلود کرده و کامپیوتر خود را ری‌استارت کنید، پس از اتمام ری‌استارت لپ‌تاپ، آن فایل دانلود شده همچنان  سر جای خود است.

هروکو از کانتینرسازی برای اجرای بارهای کاری مشتری استفاده می‌کند. یکی از واقعیت‌های این محیط این است که فایل‌ سیستم‌های مرتبط در طول ری‌استارت و زمان‌بندی مجدد، در جای خود باقی نمی‌مانند. داینوهای هروکو عمر کمی دارند و می‌توانند نابود، ری‌استارت و بدون هیچ اخطاری جابجا شوند که در این حالت با سیستم فایل مرتبط جایگزین می‌شوند. این وضعیت به این معنی است که هر فایل آپلود شده که توسط FileField’s و ImageField’s به آن‌ها ارجاع داده شده است، در هربار ری‌استارت شدن ، جابجا شدن یا اسکیل (Scale) شدنِ داینو، بدون هیچ اثری حذف می‌شود.

نمونه‌ کامل کدهای جدید (Codebase)

من مراحل پیکربندی برنامه جانگو  را برای ذخیره‌ سازی سازگار با Heroku و S3 انجام خواهم داد، اما برای مرور کد کامل به لینک زیر مراجعه کنید.

https://github.com/dstarner/django-heroku-static-file-example

بوت‌استرپینگِ جانگو در هروکو (Bootstrapping Django on Heroku)

این آموزش می‌خواهد به شما در راستای ذخیره‌سازی یک پروژه جانگو، سازگار با S3 کمک کند، اما من مراحلی که برای راه‌اندازی نمونه برنامه جانگو استفاده کردم را، به سرعت توضیح می‌دهم. این توضیحات می‌تواند به کسانی که به تازگی وارد جانگو و هروکو شده‌اند یا کسانی که در ادامه مراحل راه‌اندازی دچار مشکل هستند، کمک کند.

می‌توانید پروژه تگ شده را قبل از تغییر فضای ذخیره سازی در کمیت 299bbe2 مشاهده کنید.

  • یک پروژه جانگوی بوت‌استرپ شده (example)
  • برای مدیریت وابستگی از poetry استفاده کنید.
  • تمامی کد جانگو در زیر پکیج example قرار دارد، و فایل py در روت است. من همیشه این ساختار را از برنامه‌های جانگو که در روت پروژه تعریف شده‌اند، تمیزتر می‌دانم.
  • پیکربندی پروژه برای هروکو
  • پکیج django-heroku گزینه‌هایی مانند ALLOWED_HOSTS، DATABASE_URL و غیره را به صورت خودکار پیکربندی می‌کند. این کار دردسر استقرار جانگو در هروکو را به میزان قابل توجهی کاهش می‌دهد.
  • Procfileی که یک فرآیند gunicorn را برای مدیریت برنامه WSGI اجرا می‌کند نیز لازم است.
  • یک json با برخی از مقادیر پیکربندی اساسی و منابع تعریف شده برای پروژه، کار می‌کند.
  • یک تعریف از فرآیند release در Procfile و یک اسکریپت مربوط به scripts/release.sh، مجموعه فایل‌های استاتیک و انتقال پایگاه داده را اجرا می‌کند.

معرفی افزونه Heroku’s Bucketeer

قبل از این‌که بتوانیم مدیریت فایل‌های استاتیک و مدیا را شروع کنیم، برنامه جانگو به مکانی دائمی برای ذخیره فایل‌ها احتیاج دارد. برای بار چندم، می‌توانیم به فهرست گسترده‌ی افزونه‌های هروکو برای ذخیره‌سازی سازگار با S3 نگاه کنیم. انتخاب ما، افزونه‌ی Bucketeer خواهد بود.

افزونه‌ی Heroku’s Bucketeer یک سطل ذخیره‌سازی AWS S3 برای آپلود و دانلود فایل‌ها برای اپلیکیشن ما فراهم می‌کند. اپلیکیشن جانگو از این سطل پیکربندی شده برای ذخیره فایل‌های آپلود شده توسط سرور و دانلود آن‌ها از S3 در زمان درخواست فایل توسط کاربر، استفاده می‌کند.

اگر می‌خواهید درباره AWS S3، راه حل بسیار محبوب ذخیره‌سازی داده که Bucketeer بر اساس آن ساخته شده است، اطلاعات بیشتری کسب کنید، می‌توانید اسناد کاربری S3 را مطالعه نمائید.

شایان ذکر است که پلانِ پایه‌ی Bucketeer (Hobbyist)  5 دلار در ماه است. اگر قصد دارید نمونه تک‌کلیکه پست شده در بالا را بچرخانید، در صورتی که پس از اتمام استفاده از برنامه، به طور فعال آن را نابود کنید، تنها چند سنت هزینه‌بردار خواهد بود.

گنجاندن افزونه‌ی‌ Bucketeer

برای گنجاندن افزونه‌ Bucketeer در اپلیکیشنمان، می‌توانیم آن را از طریق هروکو CLI، داشبورد وب یا با پروژه‌ی فایل app.json پیکربندی کنیم. ما از روش سوم گنجاندن افزونه در یک فایل app.json استفاده خواهیم کرد.

اگر پروژه قبلا یکی نداشته باشد، می‌توانیم ساختار اصلی فهرست‌شده در زیر را ایجاد کنیم، که بخش مهم آن اضافه کردن پیکربندی «افزونه‌ها» است. این صف منبع “bucketeer:hobbyist” را تعریف می‌کند که برنامه ما از آن استفاده خواهد کرد، و اگر افزونه از قبل وجود نداشته باشد، هروکو آن را در برنامه ما نصب می‌کند. ما همچنین کلمه کلیدی ”as” را درج می‌کنیم که با عبارت BUCKETEER، مقدمه‌ای بر متغیرهای پیکربندی مرتبط است. این پیش‌گفتار برای قطعی نگه‌داشتن نام مقادیر پیکربندی تولید شده مفید است؛ زیرا به طور پیش‌فرض، هروکو پیشوند را به‌عنوان یک رنگ تصادفی تولید می‌کند.

				
					{
    // ... rest above
    "addons": [
        // ...other addons...
        {
            "plan": "bucketeer:hobbyist",
            "as": "BUCKETEER"
        }
    ]
}

				
			

با تعریف منابع مورد نیاز، می‌توانیم یکپارچه‌سازی با افزونه ذخیره‌سازی خود را آغاز کنیم.

پیاده‌سازی راه حل ذخیره‌سازی ما

پکیج django-storages مجموعه‌ای از پشتیبان‌های ذخیره‌سازی سفارشی و قابل استفاده مجدد برای جانگو است. این پکیج کمک زیادی به ذخیره فایل‌های استاتیک و مدیا در گزینه‌های مختلف ارائه دهنده فضای ذخیره‌سازی و کلود می‌کند. یکی از از ارائه‌دهندگان ذخیره‌سازی پشتیبانی شده، S3 است که افزونه Bucketeer ما بر روی آن ساخته شده است. ما از بک‌اند S3 django-storages برای مدیریت انواع فایل‌های مختلف استفاده خواهیم کرد.

نصب django-storages

با نصب بسته django-storages و بسته boto3 مربوطه که به‌عنوان رابط با AWS’s S3 استفاده می‌شود، شروع کنید. ما همچنین وابستگی‌های خود را قفل خواهیم کرد تا اطمینان حاصل شود که poetry و استقرار هروکو، همانطور که انتظار می‌رود، به کار خود ادامه دهند.

				
					poetry add django-storages boto3 && poetry lock
				
			

سپس، درست مانند بسیاری از بسته‌های مرتبط با جانگو، ذخیره‌سازی‌های جانگو باید به INSTALLED_APPS پروژه در فایل settings.py اضافه شوند. این به جانگو اجازه می‌دهد تا با راه‌اندازی برنامه، جریان‌های کد مناسب را بارگیری کند.

				
					# example/config/settings.py
INSTALLED_APPS = [
    # ... django.X.Y apps above
    'storages',
    # ... custom project apps below
]

				
			

پیاده سازی پشتیبان‌های ذخیره سازی استاتیک، عمومی و خصوصی در جانگو

ما بعدتر برای پیکربندی استفاده از django-storages، به فایل settings.py بازخواهیم گشت، اما قبل از انجام آن، ما سه بک‌اند ذخیره‌سازی سفارشی را پیاده خواهیم کرد:

  • 1- بک‌اند ذخیره‌سازی برای فایل‌های استاتیک، CSS، جاوااسکریپت، و imageهای در دسترس عموم که در کنترل نسخه با نام git ذخیره شده و همراه با برنامه ارسال می‌شود.
  • 2- بک‌اند ذخیره‌سازی عمومی برای فایل‌های مدیای پویا که در کنترل نسخه ذخیره نمی‌شوند، مانند فایل‌های آپلود شده و پیوست‌ها.
  • 3- بک‌اند ذخیره‌سازی خصوصی برای فایل‌های مدیای پویا که در کنترل نسخه ذخیره نمی‌شوند و برای مشاهده نیاز به دسترسی اضافی دارند، مانند گزارش‌های هر کاربر و عکس‌های پروفایل احتمالی. فایل‌هایی که توسط این بک‌اند مدیریت می‌شوند، به یک کلید دسترسی نیاز دارند و دسترسی به آن‌هایی را که کلید معتبر ندارند، مسدود می‌کنند.

ما می‌توانیم از بک‌اند ذخیره‌سازی django-storages ‘s S3Boto3Storage برای ایجاد این موارد استفاده کنیم. کد زیر می‌تواند مستقیماً در پروژه شما «کپی و جای‌گذاری» شود. ویژگی‌های settings مختلف خوانده‌شده در ماژول به زودی نوشته خواهد شد، بنابراین اگر همین الان این کد را وارد کنید، نباید توقع داشته باشید که کار کند.

				
					# FILE: example/utils/storage_backends.py

from django.conf import settings
from storages.backends.s3boto3 import S3Boto3Storage


class StaticStorage(S3Boto3Storage):
    """Used to manage static files for the web server"""
    location = settings.STATIC_LOCATION
    default_acl = settings.STATIC_DEFAULT_ACL


class PublicMediaStorage(S3Boto3Storage):
    """Used to store & serve dynamic media files with no access expiration"""
    location = settings.PUBLIC_MEDIA_LOCATION
    default_acl = settings.PUBLIC_MEDIA_DEFAULT_ACL
    file_overwrite = False


class PrivateMediaStorage(S3Boto3Storage):
    """
    Used to store & serve dynamic media files using access keys
	and short-lived expirations to ensure more privacy control
    """
    location = settings.PRIVATE_MEDIA_LOCATION
    default_acl = settings.PRIVATE_MEDIA_DEFAULT_ACL
    file_overwrite = False
    custom_domain = False

				
			

ویژگی‌های فهرست‌شده در هر کلاس ذخیره‌سازی بک‌اند، موارد زیر را انجام می‌دهند:

  • Location: دایرکتوری والد مورد استفاده در سطل S3 برای فایل‌های مرتبط را دیکته می‌کند. این ویژگی با مسیر ایجاد شده توسط یک FileField یا ImageField در متد upload_to مرتبط است.
  • default_acl: خط مشی دسترسی مورد نیاز برای خواندن فایل‌ها را دیکته می‌کند. این امر کنترل دسترسی بک‌اند ذخیره‌سازی را از طریق مقادیر None، Pucblic-read و Private دیکته می‌کند. django-storages وکلاس والد S3Boto3Storage، این‌ها را به سیاست‌های شیء ترجمه می‌کنند.
  • file_overwrite: در بیشتر موارد، اگر مسیر خاصی را به‌روز می‌کنیم، بهتر است فایل‌های موجود را بازنویسی نکنیم. با تنظیم این ویژگی بر روی False، یک پسوند منحصر به فرد به مسیر اضافه می‌شود تا از از تصادف‌های نامگذاری جلوگیری شود.
  • custom_domain: در اینجا غیرفعال است، اما اگر می‌خواهید از AWS’s CloudFront و django-storage برای سرویس‌دهی از آن استفاده کنید، می‌توانید فعالش کنید.

تنظیمات را برای استفاده از بک‌اندهای حافظه پیکربندی کنید

با تعریف پشتیبان‌های ذخیره‌سازی، می‌توانیم آن‌ها را برای استفاده در موقعیت‌های مختلف از طریق فایل setting.py پیکربندی کنیم. با این حال، استفاده از S3 و این پشتیبان‌های ذخیره‌سازی ابری مختلف در حین توسعه، چالش‌برانگیز است، و من همیشه طرفدار نگه‌داشتن همه منابع و فایل‌ها به صورت «local» در ماشین توسعه بوده‌ام؛ بنابراین یک مسیر منطقی ایجاد خواهیم کرد که:

  • از سیستم فایل local برای ذخیره فایل‌های استاتیک و مدیا برای راحتی استفاده کنید. سرور جانگو مسئولیت سرویس‌دهی مستقیم این فایل‌ها را بر عهده خواهد داشت.
  • هنگامی که یک متغیر محیطی فعال است، از بک‌اندهای ذخیره‌سازی سفارشی S3 استفاده کنید. ما از متغیر S3_ENABLED برای کنترل آن استفاده می‌کنیم و آن را در متغیرهای پیکربندی Heroko فعال می‌کنیم.

در ابتدا، فرض می‌کنیم که شما یک فایل settings.py، منتسب به Vanilla در مورد متغیرهای استاتیک و مرتبط با مدیا دارید. برای رفرنس، یک پروژه جدید باید صاحب بلوکی شبیه به ردیف‌های زیر باشد:

				
					# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/

STATIC_URL = 'static/'

STATIC_ROOT = BASE_DIR / 'collected-static'

				
			

ما یک جریان کنترل کمی پیشرفته طراحی خواهیم کرد که به طور یکپارچه دو مورد تعریف شده در بالا را کنترل می‌کند. علاوه بر این، کنترل کافی برای نادیده‌ گرفتن هر قسمت از پیکربندی را در صورت نیاز فراهم می‌کند.

از آنجایی که مقادیر پیش‌فرض برای استفاده از فایل استاتیک از قبل وجود دارند، می‌توانیم مقادیر پیش‌فرض را برای استفاده از فایل مدیا استفاده کنیم. این‌ها هنگام ارائه فایل‌ها به صورت local ، از سرور در حال توسعه استفاده می‌شوند.

				
					STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'collected-static'

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'collected-media'

				
			

ایجاد متغیرهای سه گانه

برای شروع فرآیند گنجاندن S3، اجازه دهید کنترل‌هایی را برای مدیریت، در صورتی که بخواهیم فایل‌های استاتیک و مدیا را از سرور local یا از طریق بک‌اند ذخیره‌سازی S3 ارائه کنیم،  ایجاد نمائیم. ما سه متغیر ایجاد خواهیم کرد:

S3_ENABLED: کنترل می‌کند که آیا فایل‌های مدیا و استاتیک باید به‌طور پیش‌فرض از فضای ذخیره‌سازی S3 استفاده کنند یا خیر.

LOCAL_SERVE_MEDIA_FILES: کنترل می‌کند که آیا فایل‌های مدیا باید از حافظه S3 استفاده کنند یا خیر.  مقدار S3_ENABLED به‌طور پیش‌فرض منفی فرض شده است.

LOCAL_SERVE_STATIC_FILES: کنترل می‌کند که آیا فایل‌های استاتیک باید از حافظه S3 استفاده کنند یا خیر. مقدار S3_ENABLED به‌طور پیش‌فرض منفی فرض شده است.

				
					from decouple import config  # import explained below

# ...STATIC and MEDIA settings here...

# The following configs determine if files get served from the server or an S3 storage
S3_ENABLED = config('S3_ENABLED', cast=bool, default=False)
LOCAL_SERVE_MEDIA_FILES = config('LOCAL_SERVE_MEDIA_FILES', cast=bool, default=not S3_ENABLED)
LOCAL_SERVE_STATIC_FILES = config('LOCAL_SERVE_STATIC_FILES', cast=bool, default=not S3_ENABLED)

if (not LOCAL_SERVE_MEDIA_FILES or not LOCAL_SERVE_STATIC_FILES) and not S3_ENABLED:
    raise ValueError('S3_ENABLED must be true if either media or static files are not served locally')

				
			

در مثال بالا، ما از پکیج python-decouple استفاده می‌کنیم تا خواندن و قالب‌بندی‌کردن متغیرهای محیطی به متغیر‌های Python را آسان‌تر کنیم. هنگام کار با تنظیمات settings.py، این پکیج را به شدت توصیه می‌کنم. ما همچنین یک مرحله بررسی ارزش را برای اطمینان از سازگاری بین این سه متغیر در نظر می‌گیریم. اگر هر سه متغیر در محیط تعریف شده باشند اما با یکدیگر در تضاد باشند، برنامه ارور می دهد.

اکنون می‌توانیم پیکربندی متغیرهای پیکربندی مختلف مورد نیاز بک‌اندهای ذخیره‌سازی فایل را بر اساس مقدار (مقادیر) آن متغیرهای کنترلی آغاز کنیم. ما با گنجاندن برخی از پیکربندی‌های S3 مورد نیاز، چه در حین ارائه فایل‌های استاتیک، چه مدیا و چه هر دو نوع فایل، کارمان را شروع می‌کنیم.

				
					if S3_ENABLED:
    AWS_ACCESS_KEY_ID = config('BUCKETEER_AWS_ACCESS_KEY_ID')
    AWS_SECRET_ACCESS_KEY = config('BUCKETEER_AWS_SECRET_ACCESS_KEY')
    AWS_STORAGE_BUCKET_NAME = config('BUCKETEER_BUCKET_NAME')
    AWS_S3_REGION_NAME = config('BUCKETEER_AWS_REGION')
    AWS_DEFAULT_ACL = None
    AWS_S3_SIGNATURE_VERSION = config('S3_SIGNATURE_VERSION', default='s3v4')
    AWS_S3_ENDPOINT_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
    AWS_S3_OBJECT_PARAMETERS = {'CacheControl': 'max-age=86400'}

				
			

پیشوندگذاری متغیرهای محیطی

موارد بالا برخی از متغیرهای مورد نیاز بک‌اند ‌‌S3 مربوط‌ به django-storages را تعریف و مقادیر را با پیکربندی‌های محیطی که توسط افزونه Bucketeer ارائه می‌شوند، تنظیم می‌کند.  همانطور که قبلاً ذکر شد، همه افزونه‌های متغیرهای محیطی با BUCKETEER_ پیشوندگذاری شده‌اند.

متغیر محیطی S3_SIGNATURE_VERSION مورد نیاز نیست و به احتمال زیاد نیازی هم به گنجاندن آن نیست.

با پیکربندی S3، می‌توانیم به متغیرهای کنترل LOCAL_SERVE_MEDIA_FILES و LOCAL_SERVE_STATIC_FILES رجوع کنیم تا تنظیمات پیش‌فرض فایل مدیا و استاتیک را در صورتی که بخواهیم از طریق S3 ارائه شوند، لغو کنیم.

				
					if not LOCAL_SERVE_STATIC_FILES:
    STATIC_DEFAULT_ACL = 'public-read'
    STATIC_LOCATION = 'static'
    STATIC_URL = f'{AWS_S3_ENDPOINT_URL}/{STATIC_LOCATION}/'
    STATICFILES_STORAGE = 'example.utils.storage_backends.StaticStorage'

				
			

به آخرین خطی که STATICFILES_STORAGE  در آن بر روی بک‌اند سفارشی که ایجاد کرده‌ایم، تنظیم شده است توجه کنید. این تضمین می‌کند که از سیاست‌های مکان و ACL (فهرست کنترل دسترسی) پیروی شود. با این پیکربندی، همه فایل‌های استاتیک در زیر /static/ و در سطل قرار می‌گیرند، اما در صورت تمایل می‌توانید STATIC_LOCATION را به‌روزرسانی کنید.

ما می‌توانیم یک وضعیت بسیار مشابه را برای فایل‌های مدیا پیکربندی کنیم:

				
					if not LOCAL_SERVE_MEDIA_FILES:
    PUBLIC_MEDIA_DEFAULT_ACL = 'public-read'
    PUBLIC_MEDIA_LOCATION = 'media/public'

    MEDIA_URL = f'{AWS_S3_ENDPOINT_URL}/{PUBLIC_MEDIA_LOCATION}/'
    DEFAULT_FILE_STORAGE = 'rn_api.utils.storage_backends.PublicMediaStorage'

    PRIVATE_MEDIA_DEFAULT_ACL = 'private'
    PRIVATE_MEDIA_LOCATION = 'media/private'
    PRIVATE_FILE_STORAGE = 'rn_api.utils.storage_backends.PrivateMediaStorage'

				
			

تفاوت بزرگ در این‌جا این است که ما دو بک‌اند ذخیره‌سازی مختلف را برای فایل‌های مدیا پیکربندی کرده‌ایم. یکی برای اشیاء در دسترس عموم و یکی برای اشیائی که به توکن دسترسی نیاز دارند. هنگامی که فایل درخواست می‌شود، این توکن به صورت داخلی توسط django-storages تولید می‌شود، بنابراین لازم نیست نگران دسترسی عمومی ناشناس باشید.

خدمات توسعه محلی (Local) در جانگو

از این بابت که ما S3_ENABLED را در محیط توسعه محلی خود، بر روی False تنظیم خواهیم کرد، این ویژگی فایل‌های استاتیک و مدیا را به صورت محلی و به جای سرور S3 از طریق جانگو ارائه می‌دهد. برای مدیریت این سناریو، باید مسیریابی URL را پیکربندی کنیم. ما می‌توانیم فایل urls.py خود را برای ارائه فایل‌های مناسب مانند این پیکربندی کنیم:

				
					from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path


urlpatterns = [
    path('admin/', admin.site.urls),
]

if settings.LOCAL_SERVE_STATIC_FILES:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

if settings.LOCAL_SERVE_MEDIA_FILES:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

				
			

این کار فایل‌های استاتیک یا مدیا را بر اساس مقادیر متغیرهای تنظیمات LOCAL_SERVE_STATIC_FILES و LOCAL_SERVE_MEDIA_FILES ارائه می‌کند.

فعال کردن حافظه S3 در جانگو

ما می‌توانیم این حافظه‌ها و افزونه خودمان را در فایل app.json فعال کنیم تا شروع به استفاده از این پشتیبان‌های ذخیره‌سازی کنند. این کار به‌طور موثر LOCAL_SERVE_STATIC_FILES و LOCAL_SERVE_MEDIA_FILES را غیرفعال می‌کند تا هنگام استقرار در هروکو، هر دو کارشان را از طریق S3 شروع کنند.

				
					{
  // ...rest of configs...
  "env": {
    // ...rest of envs...
    "S3_ENABLED": {
      "description": "Enable to upload & serve static and media files from S3",
      "value": "True"
    },
  }
}

				
			

استفاده از فضای ذخیره سازی خصوصی در جانگو

جانگو به‌طور پیش‌فرض، از کلاس PublicMediaStorage برای آپلود فایل‌های مدیا استفاده می‌کند؛ به این معنی که محتویات برای هرکسی که لینک را در اختیار داشته باشد، قابل دسترسی خواهد بود. با این حال، یک مدل در صورت تمایل می‌تواند از بک‌اند PrivateMediaStorage استفاده کند، که توکن‌های دسترسی کوتاه‌ مدتی ایجاد می‌کند که مانع از مشاهده عمومی شیء مرتبط می‌شود.

نمونه زیر، مثالی از استفاده از فایل‌های رسانه‌ای عمومی و خصوصی در یک مدل است:

				
					from django.db import models

from example.utils.storage_backends import PrivateMediaStorage


class Organization(models.Model):
    """A sample Organization model with public and private file field usage
	"""

    logo = models.ImageField(help_text='A publicly accessible company logo')

    expense_report = models.FileField(
        help_text='The private expense report requires a short-lived access token'
	    storage=PrivateMediaStorage()  # will create private files
	)

				
			

می‌توانید کد برای این مثال کامل را در کمیت 265becc مشاهده کنید. این پیکربندی به پروژه شما اجازه می‌دهد تا با استفاده از جانگو بر روی هروکو و با استفاده از Bucketeer مقیاس کارآمدی داشته باشد.

Leave feedback about this

  • کیفیت
  • قیمت
  • خدمات

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video
X