Django - placing and accessing a js file in root directory - django

I am trying to implement Firebase cloud messaging push notifications in my Django project.
Firebase would look for a js file named firebase-messaging-sw.js in a project' root directory (no matter, what sort of project it is).
So, the problem is that I can't figure out what is my project's root directory (sorry, for being stupid), and how to make Firebase see this file. Just as an experiment, I copy-pasted the js file to each and every folder of my project, and still no success (Firebase service can't see the file).
Here's my settings.py file (with relevant content):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ROOT_URLCONF = 'android_blend.urls'
WSGI_APPLICATION = 'android_blend.wsgi.application'
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
STATIC_URL = '/static/'
if DEBUG:
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR),"static","static-only")
#STATIC_ROOT = [os.path.join(BASE_DIR,"static-only")]
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR),"static","media")
#MEDIA_ROOT = [os.path.join(BASE_DIR,"media")]
STATICFILES_DIRS = (
#os.path.join(os.path.dirname(BASE_DIR),"static","static"),
os.path.join(BASE_DIR,"static"),
)
My Django project layout is like this:
android_blend
android_blend
settings.py
url.py
wsgi.py
app1
app2
...
appN
manage.py
So the question is, what should I do in order for an outside service app (Google Firebase) be able to see the javascript file ?
In my browser, I get the following error:
A bad HTTP response code (404) was received when fetching the script.

I was also facing the same problem.
I tried it in the following way:
Add the following line in urls.py
url(r'^firebase-messaging-sw.js', views.firebase_messaging_sw_js),
Now add the function in view.py file
#csrf_exempt
def firebase_messaging_sw_js(request):
filename = '/static/firebase-messaging-sw.js'
jsfile = open(absAppPath + filename, 'rb')
response = HttpResponse(content=jsfile)
response['Content-Type'] = 'text/javascript'
response['Content-Disposition'] = 'attachment; filename="%s"' % (absAppPath + filename)
return response
So localhost:8000/firebase-messaging-sw.js will work properly...
Hope this will help you...

Related

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.

FileNotFoundError for the media folder after deploying Django app on Apache

I have a Django app that I just added to the already deployed Django web on Apache.
Because it is ran by Apache, path of the media folder seems to be different.
My app lets the user upload an excel file which then changes numbers and save as csv file.
(only showed relevant folders/code snippets)
Current directory
converts\
_init_.py
apps.py
forms.py
models.py
converter.py
urls.py
views.py
main\
settings.py
urls.py
wsgi.py
meida\
excels\
example.xlsx
csvs\
example.csv
static\
manage.py
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
main\urls.py
urlpatterns = [
path('', RedirectView.as_view(url='/converts/')),
path('converts/', include('converts.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The part that causes the problem is the following in converts/converter.py:
def convertExcel(name):
path = 'media/excels/'
key = path + name
wb = load_workbook(key)
Originally in development, a function in view calls convertExcel(example.xlsx) and the workbook, via media/excels/example.xlsx, finds the correct file to work with the loaded workbook. But in production server, it gives
FileNotFoundError: [Errno 2] No such file or directory: 'media/excels/example.xlsx'
My Question is:
Do I have to back track from where apache2.conf is to find the path? Or is there a way to set path to my django project so i can just set path in my convertExcel() as 'media/excels'? Or is there any other way I can call the uploaded workbook?
Any kind of help/comment would be appreciated.
Please comment if additional information is needed.
My guess is that you should use MEDIA_ROOT variable because it points to the uploaded files. So you would have
def convertExcel(name):
from django.conf import settings
path = os.path.join(settings.MEDIA_ROOT, 'excels')
key = os.path.join(path, name)
wb = load_workbook(key)

Prod server serving files only when debug turned on- Django

I am trying to serve dynamically created files on my Django server.
The code works fine and serves the image file from media folder on my local server.
It also works and serves the image file in Production server but only when I set debug to True in Prod server.
But when I set debug to False in Prod Server, I get a file not found error (in console):
GET http://thesitename/media/imgs/img.png 404 (Not Found)
The server serves the files from the /static folder, but does not serve the files from /media folder.
my settings.py looks like this:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "frontend/media/")
urls.py looks like this:
app_name = 'frontend'
urlpatterns = [ ###urls###
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Views.py looks like this:
def template_page(request, loation, par, date):
### generating image using pil here ###
pil_image.save("frontend/media/imgs/img.png”)
path_to_image_passing_to_template = “/media/imgs/img.png”
params = {
'path_to_image_passing_to_template' : path_to_image_passing_to_template
}
return render(request, 'frontend/template_page.html', params)
html looks like this:
<img src="{{path_to_image_passing_to_template}}" />
and file structure is like this:
/backend
urls.py
views.py
/frontend
/static
/media
/imgs
/templates
/frontend
urls.py
views.py
/thesite
settings.py
urls.py
wsgi.py
/static
I don't understand why it should work with debugging turned on in prod server and not otherwise!!!
I have looked at several questions but did not find any query close to this kind of issue. I took some help while writing working out the dynamic media files code from this answer earlier but am stuck right now.
Confirm that you have 'os.environ' module loaded...try executing the
code below on the production server.
import os
print(os.environ.get('MEDIA_ROOT'))
Make sure it shows the expected path.
then ensure that your 'urls.py' and 'Views.py' have 'import os' line appearing at the top of the file. Good Luck!

Reading a static file

I have a Django project called myproject, which has an app called myapp. I want to read a text file and load its contents into a list. I'm a little confused about static files and relative directories in Django, and my initial attempt is not working. So far, I have the following code...
In /myproject/settings.py:
STATIC_URL = '/static/'
In /myapp/static/myapp, there is a file called myfile.txt.
In /myapp/views.py:
with open('myapp/myfile.txt') as f:
lines = f.readlines()
When running the server, I get the error: No such file or directory: 'myapp/myfile.txt'
What am I doing wrong?
in your settings:
import os
gettext = lambda s: s
PROJECT_PATH = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
MEDIA_ROOT = os.path.join(PROJECT_PATH, "media")
MEDIA_URL = "/media/"
create a folder media under your app folder.
then put the file you want to read in that folder.
and try this in your views.py:
from django.conf import settings
with open(settings.MEDIA_ROOT + '\\yourfile.text', 'rb') as f:
lines = f.readlines()

Adding expire header for Django static files on Heroku

I'm trying to optimize my webpage and am having trouble setting expiration date headers on my static files.
I am running django-1.5, python-2.7.3.
Here's my cache settings in settings.pyso far:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(PROJECT_ROOT, 'cache/'),
}
}
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 5 * 60
CACHE_MIDDLEWARE_KEY_PREFIX = ''
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
...
'django.middleware.cache.FetchFromCacheMiddleware',
)
And my static file settings in settings.py:
import os.path
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.abspath(os.path.join(PROJECT_DIR, '..'))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles/')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(PROJECT_DIR, 'static'),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
The closest advice I've found was here, but I'm unable to modify the .htaccess files on Heroku.
Any help is greatly appreciated. Thanks!
The django staticfiles app does not provide out of the box support for custom headers. You'll have to hack together your own view to serve up the files and add custom headers to the HttpResponse.
But You should not be serving your static files using Django. This is a terrible idea.
Django is single-threaded, and blocking. So every time you're serving a user a static file, you're literally serving nothing else (including your application code, which is what Django is there for).
Django's staticviews file is insecure, and unstable. The documentation specifically says not to use it in production. So do not use it in production. Ever.
In production you shouldn't serve static files with Django. See the warning boxes on this page: https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#static-file-development-view
In development, Django's contrib.staticfiles app automatically serves staticfiles for you by overwriting the runserver command. This way you can't control the way it serves the static files.
You can prevent the staticfiles app from serving the static files by adding the --nostatic option to the runserver command:
./manage.py runserver --nostatic
Then you can write an url config to manually serve the static files with headers you want:
from functools import wraps
from django.conf import settings
from django.contrib.staticfiles.views import serve as serve_static
from django.conf.urls import patterns, url
urlpatterns = patterns('', )
if settings.DEBUG:
def custom_headers(view_func):
#wraps(view_func)
def wrapper(request, *args, **kwargs):
response = view_func(request, *args, **kwargs)
response['Custom-header'] = 'Awesome'
response['Another-header'] = 'Bad ass'
return response
return wrapper
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', custom_headers(serve_static)),
)
If you want your manage.py to have the --nostatic option on by default, you can put this in your manage.py:
if '--nostatic' not in sys.argv:
sys.argv.append('--nostatic')
I think since you are hosting your project on heroku , the generally accepted practice seems to be using S3 for serving static files.
Have a look at this question :
Proper way to handle static files and templates for Django on Heroku
I am not too sure about this but I am sure you should be able to change headers while serving files from S3 atleast this SO question seems to suggest that way
Is it possible to change headers on an S3 object without downloading the entire object?
Hope this helps