Django Displaying images uploaded by ImageField properly - django

I'm building my own porfolio using Django, and I just had a question regarding uploading images using the ImageField.
I uploaded an image through the admin page using ImageField, and after a long search session, finally got my page to display the image successfully.
urls.py
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('',include('pages.urls')), # main landing page
path('admin/', admin.site.urls),
path('project/',include("projects.urls"))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
projects.html
<img src="{{project.image.url}}">
However, the official django docs say that this is not a good way to deploy a django site. Why is that, and what is the best/proper way to display images?

The reason is also given in documentation:
This method is grossly inefficient and probably insecure, so it is unsuitable for production.
Proper way of deploying media files in production is to use a reverse proxy server like NGINX or Apache, or you can use a S3 compatible storage(like Amazon S3) to serve those media files as well. I can give you an example configuration in NGINX for serving media files:
location /media {
alias /path/to/media/direcoty; # Change to your own media directory here.
access_log off;
}

Related

Django/Wagtail Media Files not showing up in the admin portal on a fresh install

I am working on a site in dev that contains a media folder. When I do a fresh setup of the site (empty db) and do all the migrations and steps to get the site up and running I noticed in the admin portal none of the images and assets in the media folder dont show up even though they exist. I have to re-import an image and then it shows up in the admin portal as expected. I have looked all over and cannot find an answer. To put it simply why isnt the admin portal importing existing files in the media folder on a fresh setup?
django==3.2
wagtail==3.0
base.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = 'media/'
urls.py
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls
from wagtail.contrib.sitemaps.views import sitemap
from search import views as search_views
urlpatterns = [
...
]
if settings.DEBUG:
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# Serve static and media files from development server
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
If anyone has any idea?
That is totally normal. Just as you need to import your page data into the database, you also need to import the information about your documents into the database (in addition to having the files). You can write a script to help with these imports. I don't have one for images but here is one I wrote for importing documents from a nested directory in the file system into a nested set of collections: https://gist.github.com/cnk/54031ca6775fa0d29997449a1e2010ec

How can I host a Django web app on Cpanel out the public_html folder?

I am trying to host a Django web application on Cpanel.
However, my hosting service is having a main folder which is called public_html. In this folder, there is the index page. My project folder named myapp is out of the public_html folder. Whenever I run the application, it is showing the content of the index.html which is in the public_html folder instead of running the home page of my application that should be executed from this main urls.py file.
Bellow is the main urls.py content.
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
from django.conf.urls import url
from django.views.generic.base import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path('depenses/', include('depenses.urls', namespace='depenses')),
path('cart/', include('cart.urls', namespace='cart')),
path('orders/', include('orders.urls', namespace='orders')),
path('coupons/', include('coupons.urls', namespace='coupons')),
path('', include('shop.urls', namespace='shop')),
# path('', TemplateView.as_view(template_name='templates/index.html'), name='home'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Again my project is out of the public_html folder.
Please assist me to host my application.
This is normal behavior considering the fact that the web service will attempt to serve HTML/PHP files only.
You will need to deploy your Django app through a python interpreter like Apache Passenger or something similar that would handle and serve it.
This can be easily achieved without many configurations and hassles with the Python App feature of CloudLinux.
Therefore, I would suggest you simply find a hosting provider that provides CloudLinux's Python App feature. The deployment process via that feature is with just a few simple clicks.

How to serve another static root in Django for html pages?

The typical configuration serves two static roots:
http://www.example.org/static/
http://www.example.org/media/
This is STATIC_URL and MEDIA_URL.
I would like to add a third one to host static files build with Sphinx:
http://www.example.org/docs/
I know I could configure this on the level of the web server. Is it also possible to configure this on the level of Django?
Here is my python package, that implements Sphinx with Django templates and renders it to static pages. A kind lightweight read-the-docs. Still in an early state, yet working.
https://github.com/elmar-hinz/Django.SphinxCMS
How about building a url just like you do for the static files? The DOCS_ROOT setting should be a string in your settings.
from django.urls import re_path
from django.views.static import serve
from django.conf import settings
urlpatterns += [
re_path(r'^docs/(?P<path>.*)', serve, {'document_root': settings.DOCS_ROOT})
]

How does Django serve media files?

I have set up a Django application that uses images. I think I have set up the media settings MEDIA_ROOT and MEDIA_URL correctly. However the images don't show up. Do you know what can be the problem?
Let consider this example:
The image files are under /home/www/media/app/photos and we are trying to request http://example.com/photos/123.jpg
Should I use these settings?
MEDIA\_ROOT = /home/www/media
MEDIA_URL = http://example.com/app
UPDATE: Forgot to mention that I'm using built-in development server.
FOR DEVELOPMENT ONLY
You can setup a static media server for use with their development server by doing this in your urls.py file. I have attached the code showing how I use it (along with the forced DEBUG conditionals.)
from django.conf import settings
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^$', 'views.index'),
# Accounts
(r'^accounts/login/$', 'views.user_login'),
(r'^accounts/logout/$', 'views.user_logout'),
# Contrib Modules
(r'^admin/(.*)', admin.site.root),
)
if settings.DEBUG :
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
)
I place my MEDIA_ROOT in a subdirectory of html/media and link to it as such in settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'html/media/').replace('\\','/')
After development is finished, the project gets deployed to the web server where static media files are then served by Apache using directives.
Serving static content from Django is discouraged from the developer themselves (if I'm not wrong, it only works when in debug mode). You should use a dedicated web server, instead.
If you really need to do that, anyway, read the documentation on how to serve static files.
This is the correct way of showing image files with ImageField. Imagine we have a user profile picture:
models.py:
UserProfile:
profilePic= models.ImageField( upload_to='PATH_TO_UPLOAD', blank=True, null=True)
settings.py:
MEDIA_ROOT = 'FULL_PATH_OF_MEDIA'
MEDIA_URL = 'URL_OF_MEDIA'
urls.py:
urlpatterns = [
.
.
.
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
PATH_TO_UPLOAD is the path which user upload data goes. This is sub-directory of FULL_PATH_OF_MEDIA, which means the uploaded file will have
FULL_PATH_OF_MEDIA/PATH_TO_UPLOAD
full path.Now this content can be accessed at this url:
SITE_NAME/URL_OF_MEDIA/PATH_TO_UPLOAD
I also recommend reading this on static_files vs media_files
doc
You can just add those lines to your urls.py
from django.urls import re_path
from django.views.static import serve
urlpatterns = [
...
re_path(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
]
I suspect you are getting the Django 404 page. Try directly accessing one of your images and see if that's happening.
If so, your need to configure your web server to not send requests within your media hierarchy to Django but to instead serve them directly. Here is a snip from my Apache conf file. The first section tells Apache to send everything to Django. The second section has "SetHandler None" which says "handle stuff under /media in the normal way."
See http://docs.djangoproject.com/en/dev/howto/deployment/modpython/ for all the exciting details.
Partial httpd.conf file for PrinceOfPinot.com (AKA pop):
<Location "/">
SetHandler python-program
PythonAutoReload Off
PythonDebug Off
PythonPath "['/var/www/production/pop', '/usr/local/lib/python2.5/site-packages/django'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE settings
PythonHandler django.core.handlers.modpython
</Location>
<Location "/media">
SetHandler None
AddOutputFilterByType DEFLATE text/html text/css application/x-javascript
</Location>
I'm aware that the original question is with the dev server, but for anyone else who is looking for a production environment answer:
https://docs.djangoproject.com/en/1.8/howto/static-files/deployment/ provides a guide on how to have django serve files in a production environment. From the tone of the guide, it does seem to imply that it is best to have a separate web server to handle the files or use mod_wsgi with Apache

Django - uploaded images can not be retrieved

I am exploring file/images uploads in Django. I have a model with Photo class which has thumb ImageField. I uploaded thumb with admin panel and I made template which just gives <img src='{{photo.thumb.url}}' />. Unfortunately I don't get any images and when I try to get direct link it says "page not found". It seems that django either does not move them to media_url or maybe it has no permission to access it? I wonder what can I do to fix it.
Thanks a lot beforehand.
PS: Running django on dev server with sqlite db.
The development server by default doesn't serve static files (see the documentation). You'll need to add the following code to the bottom of your urls.py to enable static file serving:
from django.conf import settings
if settings.DEBUG:
urlpatterns += patterns('',
(r'%s(?P<path>.*)' % settings.MEDIA_URL[1:], 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
That should sort you out.