Django + Heroku: Images Work Until Next Push [duplicate] - python

This question already has an answer here:
Deploying on Heroku - Images disappears after upload
(1 answer)
Closed 6 years ago.
I have a basic learning blog app that I am running into an issue with: a "blog post" with an image uploaded via the app's admin form works fine, until I push another version via heroku. Then where the image was displays the broken img icon, and the app cannot find the image even though the picture target when I look at the picture address is the same.
I feel like I'm missing something fundamentally important about something - hence why I can't seem to fix this by google. Does anyone know why I'm tripping up here, and am I even approaching this right?
I'm using Django + Gunicorn + dj-static to serve the static files.
Here is the model:
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
picture = models.ImageField(upload_to='blog/static/blog/images')
section = models.ForeignKey('Section')
posted = models.DateTimeField(auto_now_add=True)
posted_by = models.TextField()
tags = models.ManyToManyField('Tag')
def __str__(self):
return self.title
the view:
def detail(request, post_id):
post = Post.objects.get(id=post_id)
picture = post.picture
context = {'post': post, 'picture': picture}
return render(request, 'blog/detail.html', context)
snip containing the image html:
<hr>
<img src="{{ picture.url }}">
<hr>
settings.py dealing with static files:
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'
BOOTSTRAP3 = {'include_jquery': True}
LOGIN_URL = '/users/login'
MEDIA_ROOT = 'media'
MEDIA_URL = '/media/'
#Herokusettings
if os.getcwd() == '/app':
import dj_database_url
DATABASES = {
'default' : dj_database_url.config(default='postgres://localhost')
}
DEBUG = False
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
ALLOWED_HOSTS = ['*']
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
# Static files (CSS, JavaScript, Images)
# https://docs.djangoprojectcom/en/1.9/howto/static-files/
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media')
MEDIA_URL = '/media/'
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(PROJECT_ROOT, 'static'),
)
and wsgi.py:
import os
from django.core.wsgi import get_wsgi_application
from dj_static import Cling, MediaCling
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bss.settings")
application = Cling(get_wsgi_application())
application = Cling(MediaCling(get_wsgi_application()))
#application = get_wsgi_application()
Thank you for giving this a look, I feel like I'm missing something fundamental about how all this works.

The default upload location on Heroku is into temporary storage. This is because you will get a different web worker each time you deploy.
You need to use S3 or another location to store your files. Luckily this is well documented for Paperclip on Heroku.

Related

Django storages backend url pattern error when using dropbox

I am trying to use dropbox as a backend storage solution for django using django-storages, i followed the documentation but i am getting this error:
'C:/media/post_pics/profile_pic.jpeg' did not match pattern '(/(.|[\r\n])*|id:.*)|(rev:[0-9a-f]{9,})|(ns:[0-9]+(/.*)?)'
This is my models.py:
class Post(models.Model):
title = models.CharField(max_length=64)
date = models.DateField(timezone.now())
picture = models.ImageField(upload_to='post_pics')
...and my settings.py:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Dropbox media file storage
DEFAULT_FILE_STORAGE = 'storages.backends.dropbox.DropBoxStorage'
DROPBOX_OAUTH2_TOKEN = 'myToken'
DROPBOX_ROOT_PATH = '/media/'
It turns out it was just a problem with how windows path works, using a linux system solved it

Cannot upload image to MEDIA_ROOT using Mongoengine ImageField

I'm trying to upload images using Mongoengine ImageField.
But after uploading a test image,I got page not found by visiting http://127.x.x.x:xxxx/media/testimage.png.
Raised by: django.views.static.serve
"/Users/xxx/Documents/basedir/media/testimage.png" does not exist
myproject/settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
myproject/myapp/models.py
from mongoengine import Document, ImageField
class Image(Document):
image = ImageField(upload_to="")
filename = fields.StringField()
myproject/urls.py
from django.conf import settings
urlpatterns = [
#bla
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
What did I do wrong?
You may want to have a look at this. It is fairly thorough and provides every step needed to configure static files. 404 Error for django serving static files. How to setup django to serve static files?. It appears you are definitely missing STATICFILES_DIRS and also have you ran python manage.py collectstatic command?
It would also be good to confirm you upload_to of the ImageField is also correct. You can verify this in the shell. python manage.py shell

Django-Filebrowser and uploading images

I have Django Grappelli == 2.6.5 with Filebrowser and Tinymce. I use Django ==1.7.5.
I have problem with uploading images. Image uploads in the browser, appears in the folder \media\uploads but Filebrowser doesn't see it and throws an error: 'media\uploads\img.jpg' could not be found
Here is my settings:
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(PROJECT_ROOT, STATIC_URL.strip("/"))
MEDIA_URL = STATIC_URL + "media/"
MEDIA_ROOT = os.path.join(PROJECT_ROOT, *MEDIA_URL.strip("/").split("/"))
DIRECTORY = getattr(settings, "FILEBROWSER_DIRECTORY", 'uploads/')
In the pyhon shell I did following:
from django.conf import settings
import filebrowser.settings
filebrowser.settings.MEDIA_ROOT
C:\\mysite\\static\\media
filebrowser.settings.DIRECTORY
uploads/
Why is this happened? How can I set the right upload directory to Django-Filebrowser? I've read documentation and searched for answears in google. But I don't understand how fix it and I'm confused. Can you help me please.
in your projects urls.py:
from django import views
....
urlpatterns = [
...
url(r'^media/(?P<path>.*)$', views.static.serve, {
'document_root': settings.MEDIA_ROOT})
...
]

broken image on my django production site. Why is it?

I just product my site using Heroku and I got a odd problem with my media images broken.
Here is my site structure on Heroku.
-- app
-- manage.py
-- mysite
-- settings
-- __init__.py
-- base.py
-- production.py
-- static
-- media
-- product
-- images
--
-- static_dirs
-- static_root
In my app/mysite/settings/ init.py
from .base import *
try:
from .local import *
live = False
except:
live = True
if live:
from .production import *
and in my base.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'static', 'media')
STATIC_ROOT = os.path.join(BASE_DIR, 'static', 'static_root')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static', 'static_dirs'),
)
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
)
and in my production.py, I annotated as below.
# Static asset configuration
# import os
# BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# STATIC_ROOT = 'staticfiles'
# STATIC_URL = '/static/'
# STATICFILES_DIRS = (
# os.path.join(BASE_DIR, 'static'),
# )
Finally, I ran server and I got still broken image shown on my page.
When I look the image carefully through "google inspect element",I can still see the probably right path as below.
<img class="img-responsive" src="/media/products/images/aws.png">
But when I see my /static/media/products/images/ folder, there were images created on development statge only, not the images I just created on production site. (aws.png)
As still beginner for django development, It is a tough to find answer even after few hour's googling.
Please let me sleep & thanks always.
Django is serving static files in debug mode only. The situation and the solutions are explained in the docs: https://docs.djangoproject.com/en/1.4/howto/static-files/
You need to run collectstatic on your production box.

Upload Media from Heroku to Amazon S3

New to Heroku & Amazon S3, so bear with me. Uploaded my Django app onto Heroku, and having a problem with user media uploads. The model is below:
#models.py
class Movie(models.Model):
title = models.CharField(max_length = 500)
poster = models.ImageField(upload_to = 'storages.backends.s3boto')
pub_date = models.DateTimeField(auto_now_add = True)
author = models.ForeignKey(User)
The poster attribute is the one where the image is uploaded. I had it running fine locally, and now on Heroku there is an error. So I added 'storages.backends.s3boto', as numerous other posts have told me to. (not sure if right).
My Settings.py file looks like this right now, kind of a mess:
#settings.py
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
PROJECT_DIR = os.path.join(PROJECT_ROOT, '../qanda')
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = '****************'
AWS_SECRET_ACCESS_KEY = '************'
AWS_STORAGE_BUCKET_NAME = 'mrt-assets'
AWS_PRELOAD_METADATA = True
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'qanda/media/movie_posters/)
MEDIA_URL = '/media'
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = 'https://mrt-assets.s3.amazonaws.com/static/'
STATICFILES_DIRS = (os.path.join(PROJECT_DIR, 'static'),)
My bucket is called mrt-assets, and there are 2 folders in there static (css, js, images and media. I'm not too worried about the static files for now, as I've hardcoded the CSS/JS files into my HTML files*, but how do I get my user uploaded media (images of any kind) into mrt-assets/media?
*although if someone wanted to help with STATIC files too that would be great. But user uploaded media more urgent.
EDIT (per Yuji's comment):
Have tried a number of options, and none of them working. I've gone back and deleted a lot of changes, and this is now my Settings
#settings.py
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
MEDIA_ROOT = 'http://s3.amazonaws.com/mrt-assets/media/'
MEDIA_URL = '/media/'
STATIC_ROOT = 'http://s3.amazonaws.com/mrt-assets/static/'
STATIC_URL = '/static/'
ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
TEMPLATE_DIRS = (os.path.join(PROJECT_ROOT, "templates"),)
#models.py
#same as before, but now have changed the poster directory
poster = models.ImageField().
Not really sure what to do, need to connect my Heroku app to S3 so user media uploads are saved there.
Have now changed my S3 Bucket to this
mrt-assets
static
css
js
images
media
(empty)
The trick of getting your media to upload into <bucket>/media and your static assets into <bucket>/static is to create two different default storage backends for the two asset types or to explicitly instantiate your model fields with a storage object taking a location parameter.
Instantiating model field with custom storage
from storages.backends.s3boto import S3BotoStorage
class Movie(models.Model):
title = models.CharField(max_length=500)
poster = models.ImageField(storage=S3BotoStorage(location='media'))
pub_date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User)
Giving S3BotoStorage a location will prefix all uploads with its path.
Creating custom storage backends for media and static assets
This is almost the same as explicitly defining a storage backend with
location, but instead we'll be using settings.MEDIA_ROOT and
settings.STATIC_ROOT to apply a path prefix globally.
# settings.py
STATIC_ROOT = '/static/'
MEDIA_ROOT = '/media/'
DEFAULT_FILE_STORAGE = 'app.storage.S3MediaStorage'
STATICFILES_STORAGE = 'app.storage.S3StaticStorage'
# app/storage.py
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
class S3MediaStorage(S3BotoStorage):
def __init__(self, **kwargs):
kwargs['location'] = kwargs.get('location',
settings.MEDIA_ROOT.replace('/', ''))
super(S3MediaStorage, self).__init__(**kwargs)
class S3StaticStorage(S3BotoStorage):
def __init__(self, **kwargs):
kwargs['location'] = kwargs.get('location',
settings.STATIC_ROOT.replace('/', ''))
super(S3StaticStorage, self).__init__(**kwargs)
Refining it
You can refine the above code to take advantage of
Heroku config vars
to make it more portable:
# settings.py
import os
STATIC_ROOT = os.environ.get('STATIC_ROOT',
os.path.join(os.path.dirname(__file__), 'static'))
MEDIA_ROOT = os.environ.get('MEDIA_ROOT',
os.path.join(os.path.dirname(__file__), 'media'))
DEFAULT_FILE_STORAGE = os.environ.get('DEFAULT_FILE_STORAGE',
'django.core.files.storage.FileSystemStorage')
STATICFILES_STORAGE = os.environ.get('STATICFILES_STORAGE',
'django.contrib.staticfiles.storage.StaticFilesStorage')
Couple the above settings with a .env file and you can use the
default storage backends locally for development and testing and when
deploying on Heroku you'll automatically switch to
app.storage.S3MediaStorage and app.storage.S3StaticStorage respectively:
# .env
STATIC_ROOT=static
MEDIA_ROOT=media
DEFAULT_FILE_STORAGE=app.storage.S3MediaStorage
STATICFILES_STORAGE=app.storage.S3StaticStorage

Categories

Resources