Django MEDIA_ROOT, MEDIA_URL etc - django

This is my first time using MEDIA_ROOT/MEDIA_URL and I'm a little confused by the configuration. I have an image upload form which saves the original image plus a resized copy. I want to save both images to my MEDIA folder, but separate them. Current structure:
project/
----apps/
--------appOne/
------------static/
------------templates/
------------__init__.py
------------models.py
------------urls.py
------------views.py
--------__init__.py/
----MEDIA/
----project/
--------__init__.py
--------settings.py
--------urls.py
----manage.py
I would like to save the original uploaded image to MEDIA/ and the resized image to a folder inside the MEDIA folder, like MEDIA/media/. Right now, it's nesting 3 times:
original image goes to ---> MEDIA/media/
resized image goes to ---> MEDIA/media/media
I'm almost positive I have my settings wrong but I've been fiddling with it for too long and nothing is working. It seems every tutorial configures things differently and I'm just not sure what the preferred structure is or why my current config isn't working the way I expect.
Here is my settings.py:
MEDIA_ROOT = os.path.join(BASE_DIR,'MEDIA')
MEDIA_URL = "media/"
models.py:
from django.conf import settings
from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor
class Image(models.Model):
client = models.ForeignKey(Client, null=True, blank=True)
model_pic = fields.ImageField(upload_to=settings.MEDIA_URL, dependencies=[
FileDependency(processor=ImageProcessor(
format='PNG', scale={'max_width': 500, 'max_height': 500}))
])
views.py:
def upload(request):
form = ImageUploadForm(request.POST, request.FILES)
if form.is_valid():
client = Client.objects.get(id=request.session['id'])
image = Image.objects.create(client=client, model_pic=form.cleaned_data['image'])
return redirect(reverse('cphh:gallery'))
def show_images(request):
context = {
'images': Image.objects.all().order_by('-created_at'),
'media_url': settings.MEDIA_URL,
}
return render(request,'cphh/gallery.html', context)
The triple-nested uploaded images do render properly on my template:
{% for image in images %}
<img class="gallery-image" src="{{media_url}}{{ image.model_pic }}"
{% endfor %}

As per the documentation
MEDIA_ROOT is the Absolute filesystem path to the directory that will hold user-uploaded files.
Your code that pushes the uploaded Images to the root should have settings.MEDIA_ROOT/<sub-folder> instead of settings.MEDIA_URL
MEDIA_URL on the other hand is a placeholder for the url a client should hit to access your media. This is useful when you don't want to keep your media on your local filesystem, but to an external storage like amazon s3.
Using {{MEDIA_URL}} in your templates gives you a good way of not hard-coding the eventual media location.

first of all in the settings.py MEDIA_URL must be like this:
MEDIA_URL = "/media/"
Then delete MEDIA folder. Only media folder is enough.
and also if you need thumbnails for your uploaded images you can use Django easy_thumbnails package for this

Related

How to display images from an ImageField in Django?

Before I explain, I have a question. I am making a blog and the posts have a heading image. I upload this image using admin when I create a post for my blog. Is this image 'static' or 'media'?
Anyway, I have my project set up as follows:
mysite is my project, blog is my app. I have a folder named static inside blog. Inside this static folder are four more folders- css, images, fonts, js.
In settings.py, I have this set up:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
My models.py looks like this:
class Post(models.Model):
...
header_image = models.ImageField('article_header_image', upload_to = 'blog/static/images/articleimages')
Now when I try to load this image in a template, it doesn't show up.
I am doing this the following way:
{% for post in posts %}
<img src="{{post.header_image.url}}">
{% endfor %}
Another thing, how can I use the upload_to argument to upload images into the app's static folder without explicitly stating it? I think thats where the issue is. If I use upload_to = 'static/images/articleimages', a new static folder is created in the mysite folder containing manage.py.
Any help is greatly appreciated!
You can import the STATIC_ROOT from settings file, and use that to biuld the path. In addition to that, you can use a callable, and build path there instead:
import os.path
from django.conf import settings
def generate_upload_path(instance, filename):
return os.path.join(settings.STATIC_ROOT, 'images/articleimages/')
class Post(models.Model):
...
header_image = models.ImageField('article_header_image', upload_to = generate_upload_path)
Ok, if you want to upload images to static directory of your app, you can use __path__ attribute of your app:
import blog
def generate_upload_path(instance, filename):
return os.path.join(blog.__path__, 'static/images/articleimages/')

Django - Images not displaying properly

Currently working on a small Django e-commerce project and run into a small issue. For reference, I am using the Tango with Django book available online free.
I have an ImageField set in my models in order to specify an image for a product for the model of Product. I also have a model called Category which is referenced to the Product model using a ForeignKey.
The image uploads to the /static/products_img folder in the model, however, when the image is displayed in my template, the image links to /static/static/products_img folder. However, when I remove the /static in the model, and then upload an image through the admin interface, it uploads it to /products_img and not the static folder, in which of course it displays fine. But... it gets weirder, when I delete the newly created directory and place the image in the /product_img folder in the static folder, it still displays!
I'm so confused.
models.py
class Product(models.Model):
...
image = models.ImageField(upload_to='static/products_img', blank=True)
template.html
<img src="{{ STATIC_URL }}{{ product.image }}" alt="{{ product.name }}" />
settings.py
...
SETTINGS_DIR = os.path.dirname(__file__)
PROJECT_PATH = os.path.join(SETTINGS_DIR, os.pardir)
PROJECT_PATH = os.path.abspath(PROJECT_PATH)
...
STATIC_PATH = os.path.join(PROJECT_PATH,'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
STATIC_PATH,
)
I think you have a confusion between static and media files. Static files are bundled with your apps (CSS, JS...), while media files are uploaded by users.
From what I understand, your products images are Media files, not Static files.
What if you replace your template part with:
<img src="{{ product.image.url }}" alt="{{ product.name }}" />
and your model with :
image = models.ImageField(upload_to='products/img', blank=True)
And add the corresponding settings into your settings.py :
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
# with this, your media directory will be the same directory than your settings.py file
# you can also use a standard path like "/var/www/media"
# IMPORTANT : In any case, you have to create the directory by hand
MEDIA_ROOT = os.path.join(PROJECT_PATH, "media")
MEDIA_URL = "/media/"
If you upload an image into a product, it should now be saved under MEDIA_ROOT directory. The URL displayed in template should be /media/projects/img/image_name.

django 1.4.3 file structure?how to access the images?

i am using django 1.4.3 version and i am not able set the media path so that i can access my images.i have searched in the Google but nothing is helped me to solve this. My project structure is like below
indianstartup
indianapp
admin.py
models.py
views.py
templates/
index.html
h.html
media/
abc.jpg
indianstartup
settings.py
urls.py
now in models.py i am using imagefield like below
pic=models.ImageField(upload_to="media/")
the above one is not working, how can i save or upload a image to my media folder which is in "indianapp" folder and how can i show the same image in the html file?
Settings file
MEDIA_ROOT = os.path.join(SITE_ROOT, 'media')
MEDIA_URL = '/media/'
added view.py
views.py
def singlepost(request, year, month, slug2):
posts, pagedata = init()
img=posts.get
post = posts.get(date_created__year=year,
date_created__month=int(month),
slug=slug2,)
pagedata.update({'post': post})
return render_to_response('singlepost.html', pagedata)
so iam trying to get the image by post.pic in like
<img src="{{post.pic}}">
but not working

upload images to template directory

I have a model with this field:
image=models.ImageField(upload_to='company-category')
company-category is a folder in uploads folder,but I want to upload images to template directory .I think this way users that visit my website can't access images and download them.
in settings:
TEMPLATE_DIRS = (
"C:/ghoghnous/HubHub/Theme"
)
how can I do this?
Here I'm giving two solutions. The one you asked and then my suggestion.
Use the following code to set the upload location to your templates folder.
from django.conf import settings
image=models.ImageField(upload_to = settings.TEMPLATE_DIRS[0])
The above code will upload image to your template directory.
My Suggestion:
Upload images to your media folder. Then use the MEDIA_URL to allow users to download them. Use the following code to define them.
settings.py
MEDIA_ROOT = 'C:/ghoghnous/HubHub/media'
MEDIA_URL = 'site_media'
urls.py
from django.conf import settings
urlpatterns += patterns('',
url(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
)
models.py
class SampleModel(models.Model):
image = models.ImageField(upload_to = 'images')
If you use this, the images will be uploaded to the folder C:/ghoghnous/HubHub/media/images/. Then get your required images by using objects.get or objects.filter.
record = SampleModel.objects.get(id = 1)
If I print record.image, the output will be images/filename.jpg.
Pass this to your template. Then you can display the image or give download link as follows:
<a href="{{ record.image.url }}/" >Download</a> #Download link
<img src="{{ record.image.url }}/" /> #To display image
<a href="/site_media/images/file.jpg" >Download</a> #Download static files
I suggest you using the second method, since saving images in templates folder is not adviced.
Template directory is not a preferred place to store media as per Django good practices.
Also, any images that you display on the web page will have a path and can be downloaded. Some people use scripting to stop right clicks and stuff like this but as far as I understand source code always give you image paths.
Oh, I think you'd like to upload the file to a temporary folder and then do something with it. Right?
You need to override method clean_image in forms. Then you can write your own code with any path you want using File storage

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.