Django wrong imagefield.path - django

i have a model with an image field like this
app_icon = models.ImageField(upload_to='icons/')
the project has 'uploads' as media folder, which has subfolders, including 'icons'.
The image is correctly uploaded to the 'icons' subfolder but when i try to access it using self.app_icon.path it returns .../uploads/imagename.jpg instead of .../uploads/icons/imagename.jpg so i get file not found error. Even the url doesn't include the 'icons' subfolder
my settings:
MEDIA_URL = '/uploads/'
MEDIA_ROOT = BASE_DIR / 'uploads/'
i can't find any answer to this problem, which seems so random to me.

Related

Django CPanel MEDIA_ROOT configuration

I have setup my Django project on CPanel.
On my python setup page on Cpanel,
I have mentioned my Application Root as "example" (where i have uploaded all files)
and my Application Url as "example.com"
settings.py contains
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py under my app contains
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
my models.py contains a field
documentFile = models.FileField(upload_to='documents/files/completed/%Y/%m/%d')
Now I can see two folders on CPANEL
example (where i have uploaded all my files)
example.com (I have not made any changes to it)
I was able to visit example.com, and everything works absolutely fine.
I was able to upload to file to 'documents/files/completed/%Y/%m/%d'
When i check i can physically see that the file is created under the folder example
But i am not able to fetch it back because, when i am trying to fetch the uploaded file, its actually tyring to fetch from example.com
I am new to Django, CPanel..
Changes/Suggestion please

Django turns absolute filepaths into relative, forcing the server to be run from the project folder

I'm trying to create a website where you can add images to models, which will then be in turn loaded on the homepage. However, I've noticed that when I run my server, it tries to get images from my /home folder.
Here's my models.py:
image_directory = join(settings.STATICFILES_DIRS[0], "website/images")
class Item(models.Model):
image = models.FilePathField(path=image_directory, recursive=True)
Here's my home.html (I'm just abbreviating it, item is passed in OK:
<img src="{{ item.image }}">
I run the migrations and run the server, and I'm able to select the image in /admin. The images look like: "sub_img_folder/img.jpg"
Then I go to /home and I get the following errors:
Not Found: /home/...absolute-path-to-project.../static/website/images/sub_img_folder/img.jpg
Not Found: /home/static/website/images/sub_img_folder/img.jpg
Any help would really be appreciated.
EDIT: Here's some of my settings.py contents.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
...
MEDIA_ROOT = os.path.join(BASE_DIR + "/static/website/")
MEDIA_URL = "images/"
EDIT 2: Just to clarify, the images you add to models are already on the server. You just need to clarify which image in the admin page, hence FilePathField instead of FileField. It somehow doesn't find the image when trying to load it on the home page but it successfully shows and selects in the admin page.
EDIT:
Since you are using a FilePathField, it only stores the path on disk, not the URL. The solution would be to use the MEDIA_URL in your template to formulate the URI string, something like this:
<img src="{{ MEDIA_URL }}/{{ FILE_NAME}}">
Where MEDIA_URL is your Media URL from settings.py and FILE_NAME is the name of the file itself.
It may be better to use an actual ImageField or FileField which stores all the information you need, or just have a CharField with the file name and build the URL like above.
PREVIOUS ANSWER:
Try adding the MEDIA elements to your Django settings.py. MEDIA_ROOT and MEDIA_URL tell Django how to handle user uploaded files:
In your settings.py:
MEDIA_ROOT = "/path/to/media/folder"
MEDIA_URL = '/media/'
In your urls.py:
urlpatterns = [
.......
] += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Documentation:
https://docs.djangoproject.com/en/3.0/ref/settings/#media-root

Incorrect URL to file in Django admin

I'm getting the wrong URL to files that have been uploaded to the media-folder in the Django admin.
The URL for the file is:
/media/Users/hammer/Dev/*****/media/attachments/2018/09/12/pdf-test.pdf
But the correct URL to the file is:
/media/attachments/2018/09/12/pdf-test.pdf
It seems like MEDIA_ROOT (/Users/hammer/Dev/*****/media/) is (incorrectly, I guess) added after the first /media/ in the URL.
MEDIA_URL is:
MEDIA_URL = '/media/'
MEDIA_ROOT is:
MEDIA_ROOT = settings.BASE_DIR + '/media/'
The definition of the file-field for the model is:
file = models.FileField(upload_to=settings.MEDIA_ROOT + "attachments/%Y/%m/%d/", null=True)
The incorrect URL for the file-field is appearing on the change-page for the model for the file field.
Any ideas on how to fix this?
You shouldn't include MEDIA_ROOT specifically in your upload_to parameter. See the documentation:
If you are using the default FileSystemStorage, the string value will be appended to your MEDIA_ROOT path to form the location on the local filesystem where uploaded files will be stored.
So, just remove that:
file = models.FileField(upload_to="attachments/%Y/%m/%d/", null=True)
You'll need to recreate the instances with the incorrect value in the db, though.

Django how to display img in template by setting MEDIA_ROOT

here is my settings
MEDIA_ROOT = 'upload/'
MEDIA_URL = '/upload/'
where the path of upload folder is PROJECT_ROOT/myapp/upload.
I successfully upload a file a.jpg to that folder, but in the render page it shows that /upload/a.jpg not found
I'm confused about the media root setting. I think it's similar to STATIC_URL,
my static url setting is like this:
STATIC_URL = '/static/
and the path of static folder is PROJECT_ROOT/myapp/static
and files like /static/a.css can ben rendered successful in web pages.
media_root is the absolute path of the folder where your media files are being stored. 'upload/' is not an absolute path.
If you're storing your media files locally (development server) it would be something like (on windows)
c:\my_app_path\media
You can hard code it or you can use the os.path.join command :
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
more informations here
Francois

MEDIA_ROOT: shall I hardcode the path or use os.path.join?

Django 1.11
The documentation shows that we should place, say, images to
/var/www//media/
https://docs.djangoproject.com/en/1.11/ref/settings/#media-root
But in the book "Two Scoops of Django" they recommend:
# Configuring MEDIA_ROOT
# ’DONT DO THIS! Hardcoded to just one user's preferences
MEDIA_ROOT = "/Users/pydanny/twoscoops_project/media"
And then suggest their way:
root = lambda *dirs: join(abspath(BASE_DIR), *dirs)
# Configuring MEDIA_ROOT
MEDIA_ROOT = root("media")
Do you accept the way Two Scoops of Django recommends?
In this case MEDIA_ROOT will be inside the project itself. This is bad, I think. This is somehow a mix of code and user data.
So, I like what the documentation of Django recommends: just hardcode a path to /var/www/example.com/media/.
MEDIA_ROOT is not even STATIC_ROOT. Static files are collected from inside the project. And they contain something which is more or less (CSS) a code. Whereas user uploaded files are definitely the data, not the code.
Could you comment? What your MEDIA_ROOT looks like?
Shall I use different MEDIA_ROOTS for my local machine and the production serve?
I once used following :
ENV_PATH = os.path.abspath(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(ENV_PATH, 'media/')
This will automatically detect the absolute path to the settings.py file and create media_root path.