Static and Media Files in Django 1.10 - django

I have a ImageField in my user_accounts/models.py file which i use to store the profile picture of users.It has a upload_to field which calls a function and uploads the file to a media folder in myproj/media/.. . The Image Field also has a default field which is used to set the default profile image from the static folder.
This is an entry of User Table in development server.
In The image the avatar field shows static url but when clicked it /media/ gets attached to the url before /static/ as follows:
In The image the url bar shows /media/ attached before the static url.When i manually remove the /media/ from the url the defaultProfileImage is shown.
This is my project structure
|-myproj
|-myproj
|-__init__.py
|-settings.py
|-urls.py
|-wsgi.py
|-static
|-user_accounts
|-images
|-defaultrofileImage.png
|-user_accounts
|-__init__.py
|-models.py
|-admin.py
|-tests.py
|-views.py
|-urls.py
Models.py File
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import AbstractUser
def get_upload_url(instance , filename):
return 'userProfileImages/%s/%s'%(instance.username , filename)
class User(AbstractUser):
mobileNumber = models.IntegerField(blank = True , null = True)
avatar = models.ImageField(upload_to = get_upload_url , default = '/static/user_accounts/images/defaultProfileImage.png')
def __str__(self):
return self.username
I have the following lines added in my settings.py file
AUTH_USER_MODEL = 'user_accounts.User'
STATIC_URL = '/static/'
STATICFILES_DIRS =[
os.path.join(BASE_DIR,'static'),
]
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'
This is my urls.py file
from django.conf.urls import url,include
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls')),
url(r'^user/',include('user_accounts.urls')),
] + static(settings.MEDIA_URL , document_root = settings.MEDIA_ROOT)
How should i correct the url so that when i click the url in my admin panel it shows the correct url in url bar and i get to see the defaultProfileImage??

ImageField default value refers to 'MEDIA_URL', therefore you should create media folder, place your defaultProfileImage there and use default = 'defaultProfileImage.png' in the model field, as in your example it resolves the picture path as MEDIA_URL + default so you get /media/static/....
You probably could omit default= from the model field and override save method to programmatically define the path to the avatar field.
Usually, user-uploaded media files reside in the MEDIA_ROOT and static assets in STATIC_DIRS.
You can find more info here and read about FileField which is the base class of ImageField here.

Related

Django is showing me a 404 error instead of my image

my friends, this is my first question here.
So, I follow the Django documentation and some questions here, but the problem keep happening.
I did what was said on other similar questions, like this one, for examaple:
Issue with image in django
But the problem persists.
So, my model looks like this:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, primary_key=True)
picture = models.ImageField(blank = True, null = True, upload_to = user_directory_path)
whatsapp = models.PositiveIntegerField(blank = True, null = True)
My settings looks like this:
MEDIA_ROOT = f"{BASE_DIR}/media"
MEDIA_URL = '/media/'
I added
+ static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
to the end of my urls.py file:
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from .views import UserList, FeedbackList, DayList, AttractionList, UserDetail, UserProfileList, ProfileDetail
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns = [
path('users/', UserList.as_view()),
path('user/<str:username>', UserDetail.as_view()),
path('profiles/', UserProfileList.as_view()),
path('profile/<str:user__username>', ProfileDetail.as_view()),
path('feedbacks/', FeedbackList.as_view()),
path('days/', DayList.as_view()),
path('attractions/', AttractionList.as_view()),
path('token/', TokenObtainPairView.as_view()),
path('token/refresh/', TokenRefreshView.as_view()),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
The folder and images are being created on my file system when I add them via the admin, but when I click to see them over there I recieve a 404.
Request URL: http://192.168.15.21:8000/media/uploads/profile_pictures/1-417ee0cb-cd83-4ea6-a692-a4af3b4afcce-eu.jpg
Using the URLconf defined in evento.urls, Django tried these URL patterns, in this order:
event_app/
admin/
The current path, media/uploads/profile_pictures/1-417ee0cb-cd83-4ea6-a692-a4af3b4afcce-eu.jpg, didn’t match any of these.
This is my file structure
I am making a mobile app and serving my data using Django Rest Framework, the images are the only thing giving me a headache right now.
Herer i have change your upload_to = profile_pictures
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, primary_key=True)
picture = models.ImageField(blank = True, null = True, upload_to = profile_pictures)
whatsapp = models.PositiveIntegerField(blank = True, null = True)
I have also change settings as given below
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
In your main project app you can add urlpatterns as given below if you have to
urlpatterns = urlpatterns + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

Unable to show in frontend images uploaded via Django REST framework

I'm trying to create Django REST app, however I cannot manage to allow the url of the image to be accessible.
I managed to get the upload done, however when I have the URL there is no way to access the photo from browser. I stored them in folder profile_pictures and I was thinking of loading the image from localhost:8000/profile_pictures/image_name.jpg but I'm not sure how to setup this, as I tried linking static files to the urls but nothing seems to work.
settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static")
MEDIA_URL = '/profile_pictures/'
MEDIA_ROOT = os.path.join(BASE_DIR,"profile_pictures")
urls.py
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
However, it says that the static name is not defined even tho I import it using:
from django.conf import settings
from django.conf.urls.static import static
I upload the images with Simple REST API which I only created for testing:
class UploadPictureAPI(generics.GenericAPIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
x = AdditionalUser(user=request.user, profile_picture=request.data['profile_picture'])
x.save()
print(x)
return Response({"message": "uploaded"})
and I store them in a database as such:
class AdditionalUser(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile_picture = models.ImageField(upload_to='profile_pictures')
user_bio = models.CharField(max_length=300)
user_instagram = models.CharField(max_length=300)
They get uploaded to the DataBase and in the folder, but I cannot get access to them from the url(which I get as profile_picture.url) of the database, it says page not found

Why cannot I see the image file in django?

I tried to load an image file, but it didn't work. I uploaded the image file by admin. Thanks for the help!
here is my code
in urls.py
path('main/archive/<int:video_id>/', views.loadphoto, name='loadphoto'),
in views.py
def loadphoto(request, video_id):
target_img=get_object_or_404(Record, pk=video_id)
context={'target_img':target_img.picture}
in models.py
class Record(models.Model):
record_text = models.CharField(max_length=50)
pub_date = models.DateTimeField('date published')
picture=models.ImageField(blank=True)
def __str__(self):
return self.record_text
in img.html
<img src="target_img">
Main
First You Need To Join Your Media directory to your app
Here is the Way You Can Do That:
First You Need To Add This in Your Setting.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASEDIR,'your folder directory')
#for example app/media or something
Then You Need To Create Media Url Here is The Way:
Then You Need To Add in your urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('main/archive/<int:video_id>/', views.loadphoto,name='loadphoto'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Then You Need To Add This in Your Html File
<img src='{{ target_img.url }}'>
You Can See More Details Here:
https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.fields.files.FieldFile.url
ImageField is derived from FileField. In order to display the image in your template, you should provide its url, see https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.fields.files.FieldFile.url
The source attribute should instead by populated as follow:
<img src="target_img.url">

Django ImageField Image Not Displaying

I'm trying to use Django 2.0. I'm using the development 'runserver' right now, so please keep in mind that I'm not in production yet. I am familiar with the differences between the two with regard to static files.
I have a Blog Post model. In the admin, I want to be able to add an image to my model using ImageField. I'd like it to be optional, and provide a default image if none is added.
I am able to load images in admin. I am unable to render my image in my template. The console shows that Django is trying to GET my image, but my configurations have not worked so far.
Here's my model and relevant field:
from PIL import Image
class Post(models.Model):
....
thumbnail = models.ImageField(default='/img/default.png', upload_to='img', blank=True, null=True)
....
My model works well aside from the ImageField. My View works well, and I don't think there is any issue there.
Here is my urls.py
....
from django.conf.urls.static import static
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from . import views
urlpatterns = [
....
path('posts/', views.PostListView.as_view(), name='post_list'),
path('post/<int:pk>/', views.PostDetailView.as_view(), name='post_detail'),
path('post/random/', views.random_post, name='random_post'),
]
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I'm not at all sure about how to handle static files vs. media files in my urls.py, especially with changes to Django in version 2.0.
Here's my relevant settings.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
....
'django.contrib.messages.context_processors.media',
....
]
},
},
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
MEDIA_URL = '/media/'
I am equally unsure of what to put in my settings.py concerning media. My static CSS files are working just fine. I have a logo image in my static files that is rendering in my base template.
Here is my template tag for the ImageField:
<img class="card-image mr-3" src="{{ post.thumbnail.url }}" alt="Generic placeholder image">
Lastly, my /static folder and my /media folder are in the same directory. These are both in my app directory, /blog.
Can anyone see any blaring errors here, or can they make suggestions? My issue is the default image is not loading. The default image IS in the correct directory /media/img/. The console warning says "Not Found: /media/img/default.png".
Thanks in advance. Any suggestions will be helpful.
Django ImageField for Admin Panel
There is important thing you have to define your MEDIA_URL in urls.py.
Without this definition framework doesn't gives to you permission to access image
Setting.py
MEDIA_URL = '/uploads/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
urls.py
if settings.DEBUG: # new
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Models.py
class Product(models.Model):
title = models.CharField(max_length=150)
image=models.ImageField(blank=True,upload_to='images/')
def __str__(self):
return self.title
def image_tag(self):
return mark_safe('<img src="{}" height="50"/>'.format(self.image.url))
image_tag.short_description = 'Image'
Admin.py
class ProductAdmin(admin.ModelAdmin):
list_display = ['title','image_tag']
readonly_fields = ('image_tag',)
Printing the media root helped me solve this issue. Thanks Alasdair.
I don't think there was any issue with my model field above.
The urls.py code that I ended up using is directly from Django docs for Django 2.0 in handling static files https://docs.djangoproject.com/en/2.0/howto/static-files/.
The changes I made to Settings were done thanks to printing my MEDIA_ROOT in the console. I changed the syntax and the direction of a slash (blog\media). I also deleted the context processor shown above in my TEMPLATES options.
Here's what works for me:
models.py
thumbnail = models.ImageField(default='img/default.png', upload_to='img', blank=True, null=True)
urls.py
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [...] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'blog\media')
MEDIA_URL = '/media/'
print(MEDIA_ROOT)
Template tag
<img class="card-image mr-3" src="{{ post.thumbnail.url }}" alt="Generic placeholder image">

MEDIA_URL Page 404 Error Django

I am running on a local server and when I go to http://127.0.0.1:8000/media/ in my browser it says page not found.
Settings:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
STATIC_URL = '/static/'
Root URL:
from django.conf.urls import url, include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^polls/', include('mysite.polls.urls')),
url(r'^admin/', admin.site.urls),
url(r'^submit/', include('mysite.uploads.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Model for User Upload:
from django.db import models
class Document(models.Model):
description = models.CharField(max_length=255, blank=True)
document = models.FileField(upload_to='documents/')
uploaded_at = models.DateTimeField(auto_now_add=True)
Following the Django documentation:
Serving files uploaded by a user during development
During development, you can serve user-uploaded media files from MEDIA_ROOT using the django.contrib.staticfiles.views.serve() view.
This is not suitable for production use! For some common deployment strategies, see Deploying static files.
For example, if your MEDIA_URL is defined as /media/, you can do this by adding the following snippet to your urls.py:
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)
https://docs.djangoproject.com/en/1.10/howto/static-files/
As pointed above in the comments by Alasdair, This is the normal behaviour of Django. If you visit the full file path like 127.0.0.1/media/file.jpg, Django will render the file instead of raising a 404 error.
Why is this happening?
If you look at the source of the view that serves the media/static files, you'll find these lines:
if os.path.isdir(fullpath):
if show_indexes:
return directory_index(newpath, fullpath)
raise Http404(_("Directory indexes are not allowed here."))
What it does is, it checks if the path requested is a directory or not. If yes, then it checks if the variable show_indexes is True, then it will return the index of the files inside the media directory. Since, show_indexes is False by default, it raises 404.
To set show_indexes to True, you can do this:
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT, show_indexes=True)
This won't raise the 404 and will display a list of files inside media dir.
P.S.: I don't think displaying file indices is a good idea, unless, of course, that's something you really want. It puts server under extra load to generate the indices. And someone can download the files recursively using a program like wget etc. Even those files that are meant to be private.