How to Serve Media Files in Django + React - reactjs

I'm confused about serving media files on django and react. Here is my code:
Here is my settings.py :
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'build/static'),
]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api-user/', include('landingpage.urls')),
path('', TemplateView.as_view(template_name='index.html'))
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
Render it on react :
<img
src="/img/logo.jpeg" // is it true?
/>
I put my image on build/img folder. When i open with localhost 3000 it's rendered but when i open with localhost 8000, i get not found error with this image link http://127.0.0.1:8000/img/logo.jpeg
My question is :
Where to put images? Should i create media folder to store all my image or put it on build/image folder? How to specify the src link to image on in react?
Thanks.

In your original config Django looking the files in media dir, not in build/img dir
Change media files settings from
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
To
If you are storing images inside the build/img folder as you
mentioned in the comments then MEDIA_URL & MEDIA_ROOT should be
like
MEDIA_URL = "/img/" #edited
MEDIA_ROOT = os.path.join(BASE_DIR, 'build/img') #if the build dir is in root directory, if not then change it accordingly
Now you can use the access image files in This URL Pattern http://127.0.0.1:8000/img/logo.jpeg

Answering:
Put react images into public/static react project directory, so they will be moved to build/static and later served as other static files
In react there is something called PUBLIC_LINK. I recommend to read this answer
I can propose more general approach for react+django in production:
In settings.py create 3 varibles:
REACT_DIR – for your react project root
REACT_ROOT_URL_FILES – list of filenames to be served via root url (e.g. /favicon.png)
STATICFILES_DIRS – add directory where react created static files bundles
#settings.py
REACT_DIR = os.environ.get('REACT_DIR','/path/to/react/app/')
REACT_ROOT_URL_FILES = os.environ.get("REACT_ROOT_URL_FILES",'favicon.png manifest.json robots.txt').split(" ")
STATIC_URL = f'/{os.environ.get("STATIC_URL","static")}/'
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_DIRS = [
#...
os.path.join(REACT_DIR,'build','static')
]
Then in views.py write view to handle react root dir files (of names from REACT_ROOT_URL_FILES) as also react index.html:
from django.views.generic import View
from django.http import HttpResponse,FileResponse
from django.conf import settings
import os
class ServeReactView(View):
def get(self,request):
try:
url = request.path.strip('/')
if url in settings.REACT_ROOT_URL_FILES:
#return one of the files named from the list
file_name = url
file = open(os.path.join(settings.REACT_DIR,'build',file_name),'rb')
return FileResponse(file)
with open(os.path.join(settings.REACT_DIR,'build','index.html')) as file:
#return react index.html
return HttpResponse(file.read())
except:
return HttpResponse(
"""
{} not found!
""".format(request.path),status=501)
And at the and add this view to urls.py:
#urls.py
urlpatterns = [
#...
re_path(r"^.*",ServeReactView.as_view(),name="serve_web_client_view")
]
P.S
When you're serving more common react files (images etc..) I think it's better to put them into public/static/ react project directory, so they will be moved to build/static and later served as other static files

Related

Obtain absolute path on image ckeditor + django + react

Django
There are 2 question about this topic, but both of them (this is one Absolute paths on images uploaded by django-ckeditor) are not updated. For example, in Django 4.X, url was removed. Despite this, I've tried these solutions, but no one worked for me.
I've also tried to use:
CKEDITOR_MEDIA_PREFIX on my settings.py
But it didn't work either.
This is my settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_URL = '/media/'
CKEDITOR_UPLOAD_PATH = 'uploads/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
This is my urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api/news/', include('news.urls')),
re_path(r'^ckeditor/', include('ckeditor_uploader.urls')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += [
re_path(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT
}),
]
So here is my question, how can I set up my Django-rest-framework app in such way that I get the absolute path when I render the html on my next.js site?
This is what I get right now:
<img alt=\"\" src=\"/media/uploads/2022/01/19/video.svg\"/>
This is what I'd like to get:
<img alt=\"\" src=\"http://website.com/media/uploads/2022/01/19/video.svg\"
React
Is there any way to achieve these from the frontend? For example, updating all img's src
If you need a quick solution (I'm pretty sure this is not the "right" way of doing this), here is my approach:
As I only need to update the img.src in one JavaScript file, I did it using a hook to get all the images, filter only those ones that are stored in the server and update their src.
useEffect(()=>{
//! Don´t forget to update this
const imgDomain = 'https://...';
const imgStore = document.querySelectorAll("img[src]");
Object.keys(imgStore).map((x)=>{
if(imgStore[x].src.includes('uploads')){
const originalURL = imgStore[x].src;
var mediaPos = originalURL.indexOf('/media/');
var URLlength = originalURL.length;
var slicedSRC = originalURL.slice (mediaPos, URLlength);
var newSRC = imgDomain+slicedSRC;
imgStore[x].src = newSRC;
}
})
}, []);

How to play an uploaded video in django rest framework

I have a trouble with using django-rest-framework.
I uploaded some videos.
And I try to play that videos in react.
But I faced 404 error.
I added static and media root in setting.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
This is upload code.
videofile = request.FILES['videoData']
fs = FileSystemStorage()
filename = fs.save(videofile.name, videofile)
user = request.user
File.objects.create(
user = user,
title = request.data['videotitle'],
url = filename,
categorys = request.data['categories'],
preveimage = request.data['vidoePrevimg'],
filetype = request.data['videoType'],
filesize = request.data['videoSize']
)
It works fine
And in react I tried like this.
<ReactPlayer url={`${baseurl}/media/${videoDetaildata.url}`} playing={true} controls={true} playIcon={true}/>
This works when the url is Youtube url.
Please help me.
Thank you in advance.
During development you have also to append media url and static url to the urlpatterns.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Kindly check the following Serving files uploaded by a user during development.
Make sure not to use the above example in production, check the following gist.

how can I use react router with 'django'

I wanna use react as frontend with django as backend
I tried
urlpatterns = [
path('api/',include('api.urls')),
path('admin/', admin.site.urls),
path('',include('frontend.urls')),
]
frontend is the app contains react
frontend app urls
urlpatterns = [
path('/',index)
]
def index(request):
return render(request,'frontend/index.html')
i wanna use index.html any other route
project/urls.py
urlpatterns = [
path('api/',include('api.urls')),
path('admin/', admin.site.urls),
path('', include('frontend.urls')), # This has to be the last item!
]
frontend/urls.py
#...
from django.urls import re_path
#...
urlpatterns = [
re_path(r".*", index) # RegExpr: any character is correct
]
Django routing and react routing don't have to mix. They are completely separate from each other. You get your API data from the django routes and then create you own routes on the front-end with react-router. Read this for some context: https://www.digitalocean.com/community/tutorials/build-a-to-do-application-using-django-and-react.

viewing images from django models

Im trying to add an image to my polls app, which i have set up as: upload_to='mysite/static/polls_app/question_pics'
but the wrong file path is used when I view the page:
GET /polls/1/static/polls_app/question_pics/
How can I go about editing this so Django uses the url where the image is saved?
Models.py
question_image = models.ImageField(upload_to='static/polls_app/question_pics', default=None, blank=True, null=True)
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
Views.py
model = Question
template_name = 'polls_app/detail.html'
detail.html
<img src="{{ question.question_image.url }}" alt="image">
urls.py
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
Add below in urls.py
from django.views.static import serve
from django.urls import include,re_path
from . import settings
// Your code as it is
urlpatterns += [re_path(r'^media/(?P.*)', serve, {'document_root': settings.MEDIA_ROOT})]
This should help !!

Django adding letters and numbers to imageField url

I have an ImageField in a django model
image = models.ImageField(upload_to='images')
My media root is set like so in settings.py
MEDIA_ROOT = '/art/'
But when I upload select a gif url for the Imagefield, the url does not save as /art/images
I get this error message in Django Admin when I upload the url for the gif "Barnie.gif", which is stored at art/images/Barnie.gif
Art with ID "1/change/images/Barnie_L2fAl.gif" doesn't exist. Perhaps it was deleted?
I had the same problem. I solved it by adding the following imports:
from django.conf import settings
from django.conf.urls.static import static
I also added the following urlpatterns:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I wanted to try to get away with not doing all the config stuff, but you do have to do that.
In my base app urls.py I added:
from django.conf import settings
from django.conf.urls.static import static
and at the end of the urls list I added:
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Then in my settings.py I added:
MEDIA_ROOT = os.path.join(BASE_DIR, '/art/images')
MEDIA_URL = '/images/'

Resources