How to display image file from sftp remote server in django template? - python

We have 2 servers. One of them is for media files and the other one is for django project server(ngnx+gunicorne).
Our media server is local(internal). We want to access to media server from inside the project with sftp storage package which includes paramiko. we don't want to access media server via URL (http,https).
HttpResponse(file, content_type=type) can display the image file as a big picture but we want to pass the image file to django template for display in html file like <img src="{{images}}" alt="">
We know HttpResponse is not a good solution but we use it below code for explained our problem.
# view
def coursesPageView(request):
courses = Course.objects.filter(is_published=True)
image_data =[imageRespone(data) for data in courses]
data = {
'published_courses_list':courses,
'images' : image_data
}
return render(request, 'pages/course2.html', data)
def imageRespone(valid_image):
if sfs.exists(valid_image.image.name):
file = sfs._read(valid_image.image.name)
type, encoding = mimetypes.guess_type(valid_image.image.name)
response = HttpResponse(file, content_type=type)
return response
else:
return HttpResponse('404 Not Found')
#course2.html
<img src="{{images}}" alt="">

What you can do is mounting a shared drive into your webserver pointing to your media server (Samba for linux). Then with Django you can specify the localisation of your statics file.
For example :
import os
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.abspath(os.path.join(os.sep, 'srv', 'media'))
STATIC_URL = '/app/static/'
STATIC_ROOT = os.path.abspath(os.path.join(os.sep, 'srv', 'static'))
Pay attention to the permissions between the web server and the mounted folder.

Related

Django - Can't read media files

I'm using Django to create a website where you can upload an image on that website and check if the image contains Moire pattern. Here is the project structure:
In file settings.py, I specified the following directory for media files:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
and in file views.py, I implemented the API that will receive the image and detect moire pattern like this:
from django.core.files.storage import default_storage
def index(request):
if request.method == 'POST':
f = request.FILES['sentFile']
response = {}
fname = 'pic.jpg'
fname2 = default_storage.save(fname, f)
file_url = default_storage.url(fname2)
image = Image.open(file_url)
pred_label = moire_detect(image)
response['label'] = pred_label
return render(request, 'frontpage.html', response)
else:
return render(request, 'frontpage.html')
However, when I try to open the image using Image module of Pillow, I got this error "No such file or directory: '/media/pic_O1TOyCK.jpg'".
I don't really understand what is happening here, because the path is correct. Any help would be really appreciated.
Image.open doesn't work with url but with normal path.
But file_url has /media/pic_O1TOyCK.jpg which is relative url and it can be used on HTML (to get http://localhost/media/pic_O1TOyCK.jpg) but it can't be used as normal path to access directly local file.
You should rather use fname2 with Image.open()

Static images disappeared after using AWS for Heroku site

I made a site for Heroku using Django and I got it to the point where it kept all the static images and files on Heroku just fine but the images the user uploads got deleted on dyno reset; that's why I wanted to use AWS to host the files the user uploads.
This is the code I am using in my settings:
AWS_ACCESS_KEY_ID = os.environ.get('my key')
AWS_SECRET_ACCESS_KEY = os.environ.get('my secret key')
AWS_STORAGE_BUCKET_NAME = 'my bucket name'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
STATIC_URL = 'http://' + AWS_STORAGE_BUCKET_NAME + '.s3.eu-west-1.amazonaws.com/'
ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
AWS_QUERYSTRING_AUTH = False
I added the "eu-west-1" part in the static URL because it was in the bucket's URL but not in my site's src for the image.
The problem is that now most of my JavaScript and CSS have disappeared as have all my static files that were previously just on Heroku and worked fine, furthermore the files that the user uploads also don't show up and the src doesn't containt the "eu-west-1" that I added (and it doesn't work without that part either).
Can somebody help me make it so that my static files are on Heroku as before while user uploaded files are on AWS?

Django: open PDF file object

in my Django app I´m trying to open and show pdf files that wasn't loaded to a model, but can´t find the appropriate way.
I have a group of PDF invoices that I manually copied to media/my_folder (I use Dropbox as media host to be able to do that).
Then I want to show each invoice when requested.
File object option
After investigating several posts, I think the way to do it is creating a file object dynamically.
invoice_path = "my_folder/" + invoice_number + ".pdf"
f = open(invoice_path, 'w')
myfile = File(f)
Then I understand the in the template I could be able to access the file as it was loaded to the model.
<p>Ver factura AFIP</p>7
I get a FileNotFoundError, I guess I´m not setting the path to media files correctly.
Exception Type: FileNotFoundError at /catalog/perfilfactura/FA B
0003-00000220 Exception Value: [Errno 2] No such file or
directory: 'media/Facturas_Electronicas/FA-B-0003-00000220.pdf'
This happens when trying to open the file. The path I set it's supposed to be relative to MEDIA_ROOT, just add the subfolder "my_folder" and then the pdf file name.
Path in template option
I also tried to set the path directly in the template as in:
<p><a href="media/{{ archivo_factura }}.pdf" download>Ver factura AFIP</a></p>
<p><a href="{{ MEDIA_URL }}Facturas_Electronicas/{{ archivo_factura }}.pdf" download>Ver factura AFIP</a></p>
In both cases I get a downloaded ampty PDFs.
My settings:
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
And my Dropbox settings:
DEFAULT_FILE_STORAGE = 'storages.backends.dropbox.DropBoxStorage'
DROPBOX_OAUTH2_TOKEN = 'my_token'
DROPBOX_ROOT_PATH = '/Kinemed APP/'
Thanks!
There doesn't seem to be any reason to either open the file or create a File object. If your file is inside the media directory, all you need to do to create a URL for it is to join the media root:
invoice_path = os.path.join(settings.MEDIA_ROOT, "my_folder/" + invoice_number + ".pdf")
and now pass invoice_path directly to the template and access it there.

Django Storages using s3boto ignoring MEDIA_URL

I am trying to use django-storages with s3boto in my app and trying to serve media and static files from s3.
I have the following settings in my settings file:
AWS_STORAGE_BUCKET_NAME = '<bucket_name>'
AWS_S3_ACCESS_KEY_ID = '<access_key>'
AWS_S3_SECRET_ACCESS_KEY = '<secret>'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
STATICFILES_LOCATION = 'static'
STATICFILES_STORAGE = '<custom_storage_satic>'
MEDIAFILES_LOCATION = 'media'
DEFAULT_FILE_STORAGE = '<custom_storage_media>'
And my custom_storages.py is
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
class StaticStorage(S3BotoStorage):
location = settings.STATICFILES_LOCATION
class MediaStorage(S3BotoStorage):
location = settings.MEDIAFILES_LOCATION
When I create an image in django, instead of getting the relative path to my image starting with
image.url
'/media/image/<rest_of_the_path>.jpg'
I am getting the absolute url, which is something like
image.url
'https://<s3_bucket_name>.s3.amazonaws.com/media/image/original/'
When I use local storage instead of s3boto, it works as expected and gives me the relative path. Am I missing something here?
I struck the same issue when attempting to use the Imgix CDN for my S3 media (I suspect we're both using the same tutorial based on your use of the custom_storages.py override).
Here is an abridged version of the S3BotoStorage class in the django-storages framework. This excerpt highlights the important properties and methods for this issue, namely the custom-domain property.
class S3BotoStorage(Storage):
location = setting('AWS_LOCATION', '')
custom_domain = setting('AWS_S3_CUSTOM_DOMAIN')
def url(self, name, headers=None, response_headers=None, expire=None):
# Preserve the trailing slash after normalizing the path.
name = self._normalize_name(self._clean_name(name))
if self.custom_domain:
return "%s//%s/%s" % (self.url_protocol, self.custom_domain, filepath_to_uri(name))
As you can see in the url method, a URL is generated to override the STATIC_URL and MEDIA_URL Django settings. Currently the domain of the URL is created with the AWS_S3_CUSTOM_DOMAIN setting, which is why you continue to see the static S3 URL for media files.
So first, in your Django settings file, add a setting describing your CDN's domain.
IMGIX_DOMAIN = 'example.imgix.net'
Then, similar to the override of the location property, add an override to the custom_domain property in your MediaStorage class.
class MediaStorage(S3BotoStorage):
location = settings.MEDIAFILES_LOCATION
custom_domain = settings.IMGIX_DOMAIN
Now the final URL to your media files should begin with your CDN's domain, followed by the relative path to your file on the S3 bucket.
If you are serving static media from an S3 bucket, you must use an absolute URL, since the media is being served from a wholly different server.

Django Static URL not rendering images correctly

I'm writing a view that displays a set of images on a page.
This is the model
#models.py
class Movie(models.Model):
title = models.CharField(max_length = 500)
poster = models.ImageField(upload_to = 'qanda/static/movie_posters')
#index.html
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster }}"></a>
When I runserver, the image doesn't appear. The URL the image is trying to load is
http://127.0.0.1:8000/static/movie_posters/qanda/static/movie_posters/image.jpg
When the URL it should be trying to load is
http://127.0.0.1:8000/static/movie_posters/image.jpg
My assumption is that since movie.poster is located at 'qanda/static/movie_posters', when I render it on HTML, it is loading the Static URL (127.0.0:8000/static) and then the location 'qanda/static/movie_posters' at the end. How do I make the image render correctly?
There are two pieces of how image url is calculated.
First in your settings.py you define MEDIA_ROOT. MEDIA_ROOT specifies an absolute folder on your computer where media will be stored. So for example for these settings:
MEDIA_ROOT = '/abs/path/to/media/'
and if you have a field
models.ImageField(upload_to='movie_posters')
then images will be stored at:
/abs/path/to/media/movie_posters/
/abs/path/to/media/movie_posters/poster.jpg <- example
This deals with where media is stored on your hard drive.
Second piece is how to calculate urls for these media files. For that you define MEDIA_URL in your settings.py. That essentially maps a URL to your MEDIA_ROOT location. So then if your MEDIA_URL is:
MEDIA_URL = 'http://localhost/media/'
Then if you want to access an image stored at movie_posters/poster.jpg which has an absolute path of /abs/path/to/media/movie_posters/poster.jpg, its URL should be http://localhost/media/movie_posters/poster.jpg. You can compute the URL by doing:
{{ MEDIA_URL }}{{ movie.poster }}
Please note that I am using MEDIA_URL instead of STATIC_URL. Those are not the same thing. Computing urls like that however is not very neat. Thats why Django's ImageField and FileField have an url attribute:
{{ movie.poster.url }}
Django will then compute the proper url depending on your MEDIA_URL setting.
Note:
For all of this to work, you have to have a separate media server running. Django does not serve any media files. In development it is only capable of serving static file (not same as media files). So in development one nice trick to serve media files is to use Python's simple web server. For that, open a new terminal (on Linux and Mac) or Command Prompt (on Windows) window/tab and navigate to your media folder. Then just execute the following command there:
python -m SimpleHTTPServer 8090
and make sure your setting is:
MEDIA_URL = 'http://localhost:8090/'
and then Python will serve your media files. That works nice for development.
If you want to serve your media just using the development server you can add this for the time being to your urls.py
urlpatterns = patterns( ...all your awesome urls...) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
you can define a custom template tag which returns the basename of the URL like this:
from django import template
import os
register = template.Library()
#register.filter
def getBasename(myURL):
return os.path.basename(myURL)
this should go in your custom template tags (eg. customTemplateTags.py) file within your templatetags directory of your app.
Then you can use the filter in order to get only the image filename, not the entire URL.
{% load customTemplateTags %}
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster.url|getBasename }}"></a>

Categories

Resources