I'm trying to allow users to download a PDF file that I've previously uploaded to the MEDIA_ROOT folder via the admin console. I've emulated the answer in this post, however it's incomplete and I can't figure out how to fix this. Hoping someone can spot my issue in the code below.
settings.py
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = str(BASE_DIR) + "/media/"
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'
# Absolute path to the directory that holds static files.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = str(BASE_DIR) + "/static/"
# URL that handles the static files served from STATIC_ROOT.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
models.py
from django.db import models
# Create your models here.
class ResumeModel(models.Model):
pdf = models.FileField(upload_to="resume_app/media/resume/")
# So this file gets uploaded to root > media > resume_app > media > resume
admin.py
from django.contrib import admin
from .models import ResumeModel
# Register your models here.
admin.site.register(ResumeModel)
views.py
from django.shortcuts import render
from .models import ResumeModel
# Create your views here.
def resume(request):
resume = ResumeModel.objects.all() # < Not sure if this part is needed?
return render(request, 'resume.html', context={'resume':resume})
template.html
...
Click here to download PDF
...
When I hover over this link, the url it's pointing to is localhost:8083/resume/, which is the name of the page we're currently on, so I think the <a href="{{ resume.pdf.url }}"> is not pointing to the correct url of the PDF file I've uploaded. The upload DOES work, the file IS in the root > media > resume_app > media > resume folder. What do I need to make the link work?
UPDATE
Thanks to the help of #tonio below, and apart from my oversight, I changed the line(s):
def resume(request):
resume = ResumeModel.objects.all() # < Not sure if this part is needed?
return render(request, 'resume.html', context={'resume':resume})
to
def resume(request):
resume = ResumeModel.objects.last()
return render(request, 'resume.html', context={'resume':resume})
...which is fine for me as I will only have 1 resume in there, and the last entry will be the most recent upload. I then went into that app's folder, and deleted the __pycache__ and migrations folders, performed python manage.py makemigrations resume_app and python manage.py migrate resume_app, restarted the server, opened app in incognito window and it worked as desired!
You're sending all resume objects stored in the database to the template:
resume = ResumeModel.objects.all()
You can send an specific resume identified by their primary key (see this):
def resume(request, resume_id):
resume = get_object_or_404(ResumeModel, resume_id)
return render(request, 'resume.html', context={'resume':resume})
Anyway, you can test the template sending the first resume in the database:
def resume(request):
resume = ResumeModel.objects.first()
return render(request, 'resume.html', context={'resume':resume})
Related
I am working on image handling in Django. I am using normal image model storing method.
So, my model is something like,
class PictureModel(models.Model):
def user_directory_path(instance, filename):
return 'images/{0}/{1}'.format(instance.user.username, filename)
user = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to=user_directory_path)
The view.py is somewhat like,
#login_required(login_url='/accounts/login/')
def myMethod(request):
user = request.user
myImage = PictureModel.objects.get(user=request.user)
return render(request, 'main/myPage.html', {'myImage': myImage})
I have a media root setup as,
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
The url.py setup is as follows,
url(r'^static/(?P<path>.*)$', django.views.static.serve, {'document_root': settings.STATIC_ROOT, 'show_indexes': settings.DEBUG})
Now in normal flow, the image uploading and fetching are working as expected. But the issue is regarding the user validation/authentication while fetching the media file.
Suppose, I am getting an image by the URL,
media/images/user_1/mypic.jpg
But the whole media folder gets exposed without any validations and I can access,
media/images/user_2/mypic.jpg
also through the browser. I have searched on this over the net and found there are some random third party libraries are available but they are not so standard/popular. Can anyone suggest the best practices and libraries to handle the situation.
Add this in your template
it solves the problem
<img style="height:200px; width:200px; border-radius:50%; margin:auto" src="{{ appname.function_name.image.url }}" alt="Photo">
I know that derivatives of this question have already been asked. But those questions are outdated and I would like to hear some new answers for new versions.
I have a model and it has a file field in it.
class MyModel(models.Model):
field = models.FileField()
I can upload files with this model by using the admin panel of django and I can set its location with the MEDIA_ROOT settings variable. But I can't download this file in the view. I have tried given its URL but I usually get the "404 not found" error.
def download(request):
file = # code to get the the model instance.
context = {'file': file}
return render(request, template, context)
Here is the code in template:
Download Link
This throws a 404 error. I know why it throw this error. Because no url deffinitions exist for that url.
So, how can I download this file?
Django 1.8.7, Python 3.4.3, ubuntu 14.04
In development, you can do this to get MEDIA_URL active
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)
I'm working on a Django application, which permits to manage music files (upload, read, delete, ...).
I'm using MEDIA_ROOT system for the music uploads, which works perfectly !
But, to read or delete a file in MEDIA_ROOT, I don't know ... (except with variable in script..).
For example, if I need to read a music with Mplayer, my actual solution in views.py :
media_root = "/home/music/"
command = ("sudo /usr/bin/mplayer "+media_root)
path = music.path
p = subprocess.Popen(command+str(music.path), shell=True)
Is there any (secure) way to access to the MEDIA_ROOT from views.py / models.py ??
Thanks
You can access the settings by simply doing
from django.conf import settings
settings.MEDIA_URL
https://docs.djangoproject.com/en/dev/topics/settings/#using-settings-in-python-code
I have a simple Django admin page that uploads images to a product description. Everything works until I try to view the image by clicking on its path in the products information. I get this error:
Page not found (404)
Request URL: http://0.0.0.0:6666/the_image.jpg
I'm guessing I need to declare something in urls.py, but I have no idea where to start. I also tried changing my media paths in settings.py but I always get errors if I change to anything other than '/'
model.py
class Image(models.Model):
product_image = models.ForeignKey(Product)
image = models.ImageField(upload_to='/')
settings.py
MEDIA_ROOT = '/'
MEDIA_URL = '/'
admin.py
class InlineImage(admin.TabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [InlineImage]
Docs are here https://docs.djangoproject.com/en/dev/ref/settings/#media-root
You need to set MEDIA_ROOT and MEDIA_URL in your settings file like this
MEDIA_ROOT = /var/www/example.com/media/
MEDIA_URL = /media
and your upload_to should probably be the model name or something to identify it.
image = models.ImageField(upload_to='image')
Then the link should point the /media/image/NAME_OF_IMAGE.png
You will also need to have urls.py setup to server media files. For production you would want to do this in nginx with an alias. See https://docs.djangoproject.com/en/dev/howto/static-files/#serving-files-uploaded-by-a-user-during-development
Which says:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I'm writing a view that displays a set of images on a page.
This is the model
#models.py
class Movie(models.Model):
title = models.CharField(max_length = 500)
poster = models.ImageField(upload_to = 'qanda/static/movie_posters')
#index.html
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster }}"></a>
When I runserver, the image doesn't appear. The URL the image is trying to load is
http://127.0.0.1:8000/static/movie_posters/qanda/static/movie_posters/image.jpg
When the URL it should be trying to load is
http://127.0.0.1:8000/static/movie_posters/image.jpg
My assumption is that since movie.poster is located at 'qanda/static/movie_posters', when I render it on HTML, it is loading the Static URL (127.0.0:8000/static) and then the location 'qanda/static/movie_posters' at the end. How do I make the image render correctly?
There are two pieces of how image url is calculated.
First in your settings.py you define MEDIA_ROOT. MEDIA_ROOT specifies an absolute folder on your computer where media will be stored. So for example for these settings:
MEDIA_ROOT = '/abs/path/to/media/'
and if you have a field
models.ImageField(upload_to='movie_posters')
then images will be stored at:
/abs/path/to/media/movie_posters/
/abs/path/to/media/movie_posters/poster.jpg <- example
This deals with where media is stored on your hard drive.
Second piece is how to calculate urls for these media files. For that you define MEDIA_URL in your settings.py. That essentially maps a URL to your MEDIA_ROOT location. So then if your MEDIA_URL is:
MEDIA_URL = 'http://localhost/media/'
Then if you want to access an image stored at movie_posters/poster.jpg which has an absolute path of /abs/path/to/media/movie_posters/poster.jpg, its URL should be http://localhost/media/movie_posters/poster.jpg. You can compute the URL by doing:
{{ MEDIA_URL }}{{ movie.poster }}
Please note that I am using MEDIA_URL instead of STATIC_URL. Those are not the same thing. Computing urls like that however is not very neat. Thats why Django's ImageField and FileField have an url attribute:
{{ movie.poster.url }}
Django will then compute the proper url depending on your MEDIA_URL setting.
Note:
For all of this to work, you have to have a separate media server running. Django does not serve any media files. In development it is only capable of serving static file (not same as media files). So in development one nice trick to serve media files is to use Python's simple web server. For that, open a new terminal (on Linux and Mac) or Command Prompt (on Windows) window/tab and navigate to your media folder. Then just execute the following command there:
python -m SimpleHTTPServer 8090
and make sure your setting is:
MEDIA_URL = 'http://localhost:8090/'
and then Python will serve your media files. That works nice for development.
If you want to serve your media just using the development server you can add this for the time being to your urls.py
urlpatterns = patterns( ...all your awesome urls...) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
you can define a custom template tag which returns the basename of the URL like this:
from django import template
import os
register = template.Library()
#register.filter
def getBasename(myURL):
return os.path.basename(myURL)
this should go in your custom template tags (eg. customTemplateTags.py) file within your templatetags directory of your app.
Then you can use the filter in order to get only the image filename, not the entire URL.
{% load customTemplateTags %}
<img src = "{{ STATIC_URL }}movie_posters/{{ movie.poster.url|getBasename }}"></a>