How to avoid provide server address when access ImageField url - django

I have created model - Profile - which presents user's profile. I have one field which is models.ImageFiled and I have method to get absolute url to this image. I have server in development role, so I've exposed /media folder.
When I use full server URL it works. Is there any method to avoid put static web server address?
# Profile
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(upload_to='users/%Y/%m/%d',blank=True)
def __str__(self):
return 'Profile for user {}'.format(self.user.username)
#property
def get_absolute_image_url(self):
return "http://127.0.0.1:8000/{0}".format(self.photo.url)
in settings.py
MEDIA_URL = 'media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media/')

You need an absolute path with a leading slash:
MEDIA_URL = '/media/'

After some digging I found the solution.
It based on two things:
1) Media url has to be inside static directory to available to display.
2) Uploaded media has to be inside static directory.
My settings.py looks like below:
STATIC_URL = '/static/'
MEDIA_URL = '/static/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "shop", "static", "media")
A help came from here [a link] Differences between STATICFILES_DIR, STATIC_ROOT and MEDIA_ROOT

Related

Django FileSystemStorage does not save anything to media folder

I'm working on a Django backend deployed on a server, here's my settings:
DEBUG = False
STATIC_URL = "/staticfiles/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
And I want to save the users' images outside the django folder, so I've created a custom FileSystemStorage in this way:
from django.core.files.storage import FileSystemStorage
key_store = FileSystemStorage(location="/home/usr/project/media/", base_url="/media")
Where I put the absolute path of ubuntu server.
def profile_picture_url(instance, *_):
return f"{instance.user.uuid}/profile.picture.png"
picture = models.FileField(
storage=key_store, default=None, upload_to=profile_picture_url
)
But it doesn't create any file inside media folder.
Any solution?

How to make Django load profile image files form "media" directory

I have a directory '/media/profile_image' where profile images uploaded by users are saved. In the template I built the url by using the user object
<img id="profile_image" src="{{ request.user.profile_image.url }}"></div>
# Model
def get_profile_image_filepath(self, filename):
return f'profile_image/{self.pk}/{"profile_image.png"}'
...
profile_image = models.ImageField(max_length=255, upload_to=get_profile_image_filepath, null=True, blank=True, default=get_default_profile_image())
...
which creates the correct url to the desired directory. But it doesn't show the image, why's that?
# rendered url
<img id="profile_image" src="/media/profile_image/1/profile_image.png">
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
dir
Dealing with Django and media files on development like this :
First install pillow
pip install pillow on your activated env.
Specify the MEDIA_ROOT variable in the settings file
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') or MEDIA_ROOT = BASE_DIR / 'media' in Django 3.
Tell Django to serve media file (in development mode)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) in the project urls.py
file.
(Optional) Specify the MEDIA_URL variable too
URL that handles the media served from MEDIA_ROOT.
Exemple :
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media' # or os.path.join(BASE_DIR, 'media/') in Django 2
And in your model, you can define a media file like this :
class Profile(models.Model):
# Others fields
photo = models.ImageField(upload_to="photos/")
Here the upload_to is used to designate the location where the images assigned to the photo attribute will be saved on the hard drive for all instances of the model. If you don't specify a value for upload_to, the images will be saved to the root of MEDIA_ROOT.

Show absolute URL for uploaded file

I implemented a file upload endpoint with DRF the issue is the documents do not show the absolute url of the file as shown below on the screenshot. I expect the absolute url start with http://localhost ....
Here is my django settings
STATIC_URL = '/static/'
# The folder hosting the files
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
## Serving the STATIC FILES
# As declared in NginX conf, it must match /src/static/
STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), 'static')
MEDIA_URL = '/media/'
# do the same for media files, it must match /opt/services/djangoapp/media/
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
models.py
class Document(models.Model):
"""This represents document class model."""
file = models.FileField(upload_to='documents/inspections/%Y/%m/%d')
timestamp = models.DateTimeField(auto_now_add=True)
#property
def name(self):
name = self.file.name[33:]
return name
Django doesn't provide absoluteurl for image stored in models.ImageField. But you can modify your serializer and do this with serializer.SerializerMethodField. as you didn't provide your serializer so i assume it maybe look like this:
class Document(seralizer.ModelSerializer):
file_url = serializer.SerializerMethodField()
class Meta:
model = Document
fields = ('id','name','timestamp','file_url')
def get_file_url(self, document):
request = self.context.get('request')
file_url = document.file.url
return request.build_absolute_uri(file_url)
Django rest framework, by default, builds absolute URLs for file field if you pass request in serializer context. Try to pass the request in serializer like this.
serializer = YourSerializer(<OTHER_ARGS>, context={'request': request})
You will get the absolute URL automatically.
To make things easier I used cloudinary to host my images since eventually I will store them in the cloud in production.
Therefore:
Installed required cloudinary python packages i.e cloudinary and dj3-cloudinary-storage
Added cloudinary in installed apps:
INSTALLED_APPS = [
......
'rest_framework',
'django_extensions',
'corsheaders',
'cloudinary', # Add cloudinary
'drf_yasg',
'celery',
'django_prometheus',
'debug_toolbar',
]
Changed the default file storage in settings.py and added cloudinary configs:
CLOUDINARY_STORAGE = {
'CLOUD_NAME': '*******',
'API_KEY': '*********',
'API_SECRET': '*********',
}
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
Removed below don't need it anymore in root urls.py
urlpatterns+= static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
After testing an upload here are the results:

Return the correct url of static file in Django

model.py:
class Album(models.Model):{
poster = models.ImageField upload_to='static/images/album/%Y/%m/%d')
}
serializer.py
class AlbumSerializer(serializers.ModelSerializer):
doc = DoctorSerializer()
class Meta:
model = Album
fields = '__all__'
setting.py
STATIC_URL = '/static/'
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static')
]
views.py
class index(viewsets.ModelViewSet):
serializer_class = AlbumSerializer
queryset = Album.objects.all()
When I upload the image under http://127.0.0.1:8008/admin/qa/album/, the image show as 'static/images/album/2018/06/27/xxxxxx.jpg' at the poster field in the database. And I can access to the image through http://127.0.0.1:8008/static/images/album/2018/06/27/xxxxxx.jpg.
However, in the index view, the Django Rest Framework API return the url of the image as:
http://127.0.0.1:8008/api/index/static/images/album/2018/06/27/xxxxxx.jpg, which make the image 404.
Why the /api/index/ has been added to the url? What's wrong with my setting? Need your help...
To propely serve media files you need to add MEDIA_URL and MEDIA_ROOT to your settings also:
MEDIA_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR,'static')
Note if you set static directory with MEDIA_ROOT setting in upload_to path you can skip static:
poster = models.ImageField(upload_to='images/album/%Y/%m/%d')
In urls.py:
from django.conf import settings
urlpatterns = [
# your urls here
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
UPD
As #brunodesthuilliers said in comment, you'd better divide media and static files and use media url and directory instead of static:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'medial')

ImageField not uploading correctly

I am trying to upload an image to the server. No matter what I do, it doesn't appear to properly upload the image. Here is my field in the model:
image = models.ImageField(upload_to='uploads/images/staff', verbose_name='Staff Member Photo', help_text='Required Dimensions: Square, about 275px height/width')
Here are my settings in the settings.py file:
STATIC_URL = "/static/"
STATIC_ROOT = 'static'
MEDIA_URL = STATIC_URL + "media/"
MEDIA_ROOT = 'static/media/'
I can't figure out what's going on--it's driving me crazy!!
You should use the absolute path in the MEDIA_ROOT property. For example:
MEDIA_ROOT = '/var/www/mysite/static/media/'
BTW, what error you get then uploading the image? Is it a path-related problem?