Django Admin FileFile not open from listview - django

in my model class i have an attribute like this one:
c_cv = models.FileField(upload_to='mysite/static/docs', max_length=254, validators=[FileExtensionValidator(['pdf']),validate_fsize], verbose_name="CV")
in my admin.py:
list_display = ('c_data', 'c_sur', 'c_name', 'c_dob', 'c_en', 'c_de', 'c_cv')
but when i open from admin my list page, if i click on my c_cv field in list i get an error because link does not start from 127.0.0.1:8000/mysite/static/docs/file.pdf but instead from 127.0.0.1:8000/admin/cv_list/...
How can i force in admin looking my c_cv field using root of domain instad actual path as prefix?
So many thanks in advance

Have you defined a URL for viewing media ? What have you set your MEDIA_URL , MEDIA_ROOT to in the settings.py ?
I have done something like this to access uploaded files:
1.In settings.py :
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
2.Defined a url which is used to serve uploaded media files :
In urls.py:
#login_required
def protected_serve(request, path, document_root=None, show_indexes=False):
return serve(request, path, document_root, show_indexes)
re_path(r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:], protected_serve, {'document_root': settings.MEDIA_ROOT}),
This way I can also stop directory indexing of the list of the files that are uploaded.You can try this

Related

Page 404 error on clicking at the image link in django admins site

We have a django project in which we are storing images in the backend using image field.The image link is being stored on django admin site.However ,when I click on the link ,I get an error page.Here's my code.
models.py
images=models.ImageField(upload_to=upload_to,null=True)
def upload_to(instance, filename):
return 'images/{filename}'.format(filename=filename)
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('app/',include('firstapp.urls')),
path('',include('firstapp.api.urls')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'media')
# URL used to access the media
MEDIA_URL = '/media/'
I have created a folder named media but the images are not being stored there.Please help.
You can try this way:
MEDIA_ROOT=os.path.join(BASE_DIR,'media') #Just add like this
Do pass directly to field instead of creating function of uploat_to.
images=models.ImageField(upload_to="images/",null=True)
Do above things and see if it solves.
Do reply if it is not solved.
From Python Doc. os.path.dirname(...)
Return the directory name of pathname path. This is the first element
of the pair returned by passing path to the function split().
os.path.join() takes first argument as full path becouse of this your MEDIA_ROOT is giving wrong path.
If you're using Django>=3.0 version then you can use pathlib like this
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'

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

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.

upload via admin using FileField in django

I have something very weird. I am on win7 Django 1.4.
I have the following media_root/url settings :
MEDIA_ROOT = 'c:\project\uploads'
MEDIA_URL = '/media/'
My url.py includes :
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT}))
I have a model with the the field :
file = models.FileField(upload_to=MEDIA_ROOT, blank = True)
Now, I am uploading the file via the admin site, the file is uploaded successfully. however , the when accessing the file via the admin I see the link to the file is :
http://127.0.0.1:8000/media/c:\project\uploads\[filename]
I have no clue what I am doing wrong.
I think your model is wrong:
file = models.FileField(upload_to=MEDIA_ROOT, blank = True)
upload_to expects a relative path which is added to the MEDIA_ROOT, so now it expects the file to be at MEDIA_ROOT/MEDIA_ROOT which makes no sense.
Try something like:
file = models.FileField(upload_to='files', blank = True)
docs:
FileField.upload_to A local filesystem path that will be appended to
your MEDIA_ROOT setting to determine the value of the url attribute.

Failing to show images in templates Django

I have problems showing images in my Django templates (I'm uploading the images from the admin application). I read the documentation and other posts about the upload_to and still couldn't figure it out. I tried this <img src="{{ a.image}}"/> in my template and then this <img src="{{MEDIA_URL}}{{ a.image}}"/> and same results. Here is my settings.py code :
MEDIA_ROOT = '/home/mohamed/code/eclipse workspace/skempi0/media'
MEDIA_URL = '/media/'
and finally, I tried the following in my models.py and I failed miserably:
image = models.ImageField(upload_to = "ads/")
image = models.ImageField(upload_to = ".")
and when I used image = models.ImageField(upload_to = MEDIA_URL) I got the following error
SuspiciousOperation at /admin/advertisments/banner/add/
Attempted access to '/media/cut.jpg' denied.
EDIT
Generated links are as follows :
<img src="./DSCN6671.JPG">
RE-EDIT
Here is my view:
def index(request):
spotlightAlbum = Album.objects.filter(spotlight = True)
spotlightSong = Song.objects.filter(spotlight = True).order_by('numberOfPlays')
homepage = Song.objects.filter(homepage = True).order_by('numberOfPlays')
ads = Banner.objects.all()
copyright = CopyrightPage.objects.get()
try:
user = User.objects.get(userSlug = "mohamed-turki")
playlists = UserPlaylist.objects.filter(owner = user.userFacebookId)
purchase = Purchase.objects.filter(userName = user.userFacebookId)
user.loginState = 1
user.save()
except:
user = None
playlists = None
context = {'copyright':copyright, 'ads':ads, 'spotlightSong':spotlightSong,'spotlightAlbum': spotlightAlbum, 'homepage':homepage, 'user':user, 'playlists':playlists, 'purchase':purchase }
return render_to_response('index.html',context,context_instance = RequestContext(request))
Could anybody tell me what am I doing wrong??
P.S I'm using Django 1.4
The path you provide in upload_to will be a relative path from the MEDIA_ROOT you set in your project's settings file (typically settings.py).
Your MEDIA_ROOT is where your uploaded media will be stored on disk while the MEDIA_URL is the URL from which Django will serve them.
So if your MEDIA_ROOT is /home/mohamed/code/eclipse workspace/skempi0/media and your model's image attribute is:
image = models.ImageField(upload_to = "ads/")
Then the final home on disk of your uploaded image will be /home/mohamed/code/eclipse workspace/skempi0/media/ads/whatever-you-named-your-file.ext and the URL it will be served from is /media/ads/whatever-you-named-your-file.ext
Setting your upload path to be settings.MEDIA_URL won't work because that's where the media is served FROM not where it is allowed to be stored on disk.
If you want to load your uploaded image in your templates just do this (replace whatever with the name of the variable sent from the view to the template that represents this object):
<img src="{{ whatever.image.url }}"/>
The image attribute on your model isn't actually an image, it's a Python class that represents an image. One of the methods on that ImageField class is .url() which constructs the path to the URL of the image taking into account how you set your MEDIA_URL in your project's settings. So the snippet above will generate HTML like this:
<img src="/media/ads/whatever-you-named-your-file.ext"/>
RequestContext() and settings.TEMPLATE_CONTEXT_PROCESSORS
Since the render_to_response() you are returning from your view is utilizing RequestContext() you need to make sure you have settings.TEMPLATE_CONTEXT_PROCESSORS set correctly. Check out the 1.4 docs for further clarification.
upload_to needs to be an absolute path to the directory, not the web url. So try this:
image = models.ImageField(upload_to = settings.MEDIA_ROOT)
in your templates, just use
<img src="{{ a.image.url }}">
First, I suggest to change the MEDIA_ROOT to be
MEDIA_ROOT = os.path.join(PROJECT_ROOT,'media')
this way you ensure the media directory path is right under your project root. Your MEDIA_URL is set up correctly, but it is not used when uploading a file. MEDIA_ROOT is.
Regarding the file upload, in your model set the field to be
image_field = models.ImageField('Image', upload_to='images/some_sub_folder')
Note that I didn't use neither a leading nor trailing forward slashes. The above will upload the image to PROJECT_ROOT/media/images/some_sub_folder/ with the filename and extension of the original file. Alternatively, you can alter the filename by using a callable - upload_to=filename_convetion - more info here.
In your template, you can access the image using
<img src="/media/{{ your_model.image_field }}" />
Hope this helps, cheers.
I know this question is old but I had the same problem and this solved in my case:
settings.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
PROJECT_DIR = os.path.dirname(__file__)
MEDIA_ROOT = os.path.join(PROJECT_DIR, "media")
MEDIA_URL = '/media/'
urls.py
Then, my urls.py was missing this line of code to discover the /media/ folder and show the content:
urlpatterns += staticfiles_urlpatterns()
urlpatterns = patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}, name="media_url"),
) + urlpatterns
Hope it can help someone.