简体   繁体   中英

How To Serve media Files In Production

I have a Django project which sends automated e-mails with attached pdfs to users. At the moment I just have a normal /media/ folder with the pdf in it which the code points to. This works in development but throws a server error in production.

My question is how do I server media files in production? I have read a lot about it but can't find exactly what I'm after.

I use collectstatic in my production environment which works for static files, I'd expect something similar for media files.

urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('page.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

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

settings

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')

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

views.py (that sends the file)

file_path = os.path.join(settings.STATIC_ROOT+'\\pdf\\free_pdf.pdf')
...
msg.attach_file(file_path)

passenger.wsgi

import os
import sys

sys.path.append(os.getcwd())
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

import django.core.handlers.wsgi
from django.core.wsgi import get_wsgi_application
from whitenoise import WhiteNoise
SCRIPT_NAME = os.getcwd()
SCRIPT_NAME = '' #solution for damn link problem

class PassengerPathInfoFix(object):
    def __init__(self, app):
        self.app = app
    def __call__(self, environ, start_response):
        from urllib.parse import unquote
        environ['SCRIPT_NAME'] = SCRIPT_NAME
        request_uri = unquote(environ['REQUEST_URI'])
        script_name = unquote(environ.get('SCRIPT_NAME', ''))
        offset = request_uri.startswith(script_name) and len(environ['SCRIPT_NAME']) or 0
        environ['PATH_INFO'] = request_uri[offset:].split('?', 1)[0]
        return self.app(environ, start_response)
application = get_wsgi_application()
application = PassengerPathInfoFix(application)
application = WhiteNoise(application, root='/home/mysite/mysite/static_files')

(this code is from when I abandoned the media folder and was trying to just serve it with my static files)

My proj structure:

|project
|__app
|__static
|  |__app
|    |__style.css
|__media
|  |__app
|     |__pdfToBeSent
|__static_files (generated by collectstatic)
|__media_files (i created this)

collectstatic also doesn't copy my projects media files into media_files , I have been copying them in there myself (unsure about this).

I have also tried moving the media file to every possible location in my project

I am also serving my static files with whitenoise.

Thank you.

Since I was in a similar situation (on the same hosting, A2Hosting), I will try to share my understanding of the problem and the solution I opted for.

Pardon me if I may seem presumptuous in this presentation, I'm simply trying to retrace all the points that represent the flow of thoughts that led me to this solution.

A small premise: if with "media files" you intend multimedial files, such as images and so on, I think you shouldn't use the Django media folder as it's designed to serve files uploaded by the users .
Not knowing if your PDFs are indeed uploaded by some user or not, I'll try to expose my solution anyway.

When in a production environment, Django isn't going to serve static and media files.
For the former I too used WhiteNoise, while for the latter the approach is different (at least on a shared hosting base).

When we set Debug = False in settings.py I suspect that the media folder, created along with the Django project, becomes somewhat unreadable/unaccessible (I cannot tell if by the hand of Django or by the hand of the hosting, or a conjuction of the two).

The official method to handle media files is indeed to rely on an external storage service (like Amazon S3), but this solution isn't suitable for budget limited scenarios.

In my situation, I had the Django app running on a subdomain related to my main domain.
Principal domain: www.mydomain.com
App domain: subdomain.mydomain.com

Leaving the media folder created with the Django project where it was, I created another one in the following unix path:
/home/A2hosting_username/subdomain.mydomain.com/media

Then, in settings.py I changed the MEDIA_ROOT variable from:

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

to:

MEDIA_ROOT = '/home/A2hosting_username/subdomain.mydomain.com/media'

After that, in the model.py class used to define the database and interact with it, I specified the path to the uploaded media (videos, in my case) in this way:

class Video(models.Model):
   name = models.CharField(max_length=50)
   path = models.FileField(upload_to="../media/videos", null=True, verbose_name="")

Since we don't have access to the Apache config file, it may be useful to edit the .htaccess file (relative to subdomain.mydomain.com ) in the following way, to prevent the browser to "time out" when the uploaded file is somewhat heavy:

<ifModule mod_headers.c>
    Header set Connection keep-alive
</ifModule>

I hope this can be of any help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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