I read a lot about including image files, but i still don't get it :(
my models.py
class Movie(models.Model):
image_url = models.URLField(max_length=1024, blank=True, null=True)
image_file = models.ImageField(upload_to='poster/', blank=True)
my index.html
{% load staticfiles %}
<img src="{% static "{{movie.image_file}}" %}" />
The pictures are saved on harddisk /myapp/poster
Thanks for helping.
Got it!
<img src="
{% if movie.image_file %}
{{ movie.image_file.url }}
{% else %}
another-image.jpg
{% endif %}"
/>
urls.py
+static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
added MEDIA_URL
Thanks a lot!
You just need to do:
<img src="{{ movie.image_file.url }}" />
User uploaded files go to your MEDIA_ROOT + the upload_to parameter in your model field, which is typically a different location that static files are served from when using the {% static %} template tag.
Since your field allows for blank=True you can use a conditional to show a different image, or no image at all: (spaces added to avoid wrapping)
<img src="
{% if movie.image %}
{{ movie.image_file.url }}
{% else %}
another-image.jpg
{% endif %}"
/>
alternatively, you could add a model property that does the same thing, or you can just wrap the entire image tag in the if statement to hide it if the field is empty.
Set MEDIA_ROOT and add following lines at the end of your urls.py
+static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Example:
urlpatterns = patterns('',
url(r'^$', views.index, name='Index'),
url(r'^admin/', include(admin.site.urls)),
) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In img src write {{MODEL_NAME.FIELD_NAME.url}}
This is only for development.
Refer https://docs.djangoproject.com/en/1.8/howto/static-files/
Related
I am trying to build an e-commerce website using python's Django framework as part of a practice project. However, I am not being able to display my product's image on my landing page.
Django version: 3.2.4
models.py:
class Listing(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
description = models.TextField()
image = models.ImageField(upload_to="auctions/images/", default="")
settings.py:
STATIC_URL = '/static/'
# Managing media
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
urls.py:
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("auctions.urls"))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
views.py
def index(request):
listings = Listing.objects.all()
return render(request, 'auctions/index.html', {
"listings": listings
})
index.html
{% extends "auctions/layout.html" %}
{% load static %}
{% block body %}
<h2>Active Listings</h2>
{% for listing in listings %}
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{% static listing.image %}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{ listing.title }}</h5>
<p class="card-text">{{ listing.description }}</p>
<p class="card-text">Price - {{ listing.price }}</p>
Bid
</div>
</div>
{% endfor %}
{% endblock %}
I am only getting the alt attribute for the img tag.
As mentioned by #Pruthvi Barot you need to change the code you are using in your html from
src="{% static listing.image %}"
to
src="{% url listing.image.url %}"
That is because you image as a media and allowing them to served via a url as you define here:
# Managing media
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
The static file are in this case images that you placed in the directory and do not manage (upload and delete) from the Django Admin Panel.
another solution mentioned by #MojixCoder is to replace the above mention line of code with
src="{{ listing.image.url }}"
This is the preferred solution and is the one specified in Djangos official documentation on MEDIA_URL (version 3.2)
I'm using an inlineformset so that a user can upload multiple images at once. The images are saved and functionality is as expected, except on the front-end side. When I loop through my formset with a method resembling {{ form. image }}, I can clearly see that my image is saved and when I click the url, I am redirected to the uploaded file. The problem seems to be that the absoulte url is not stored when I try to set the image's URL as a src for an image element.
Trying to log MEDIA_URL and MEDIA_ROOT in a <p> tag yields no results.
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
ROOT_URLCONF = 'dashboard_app.urls'
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
urls.py
from django.conf.urls import url, include
from . import views
from django.conf.urls.static import static
from django.conf import settings
app_name = 'Accounts_Namespace'
urlpatterns = [
url(r'^$', views.Register, name='Accounts_Register'),
url(r'^change-password/$', views.ChangePassword, name="Accounts_Change_Password"),
url(r'^login/$', views.Login, name='Accounts_Login'),
url(r'^logout/$', views.Logout, name='Accounts_Logout'),
url(r'^profile/$', views.ViewProfile, name='Accounts_View_Profile'),
url(r'^profile/edit/$', views.EditProfile, name="Accounts_Edit_Profile"),
url(r'^school/', include('student_map_app.urls', namespace="Student_Maps_Namespace")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
models.py
class Gallery(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
image = models.ImageField(upload_to="gallery_images")
uploaded = models.DateTimeField(auto_now_add=True)
views.py
def EditProfile(request):
user = request.user
galleryInlineFormSet = inlineformset_factory(get_user_model(), Gallery, form=GalleryForm)
selectedUserGallery = Gallery.objects.filter(user=user).order_by('uploaded')
userGallery_initial = [{'image': selection.image} for selection in selectedUserGallery] # Using this syntax because formset initials accept dictionaries
if request.method == "POST":
profile_form = ProfileEditForm(request.POST, instance=request.user)
gallery_inlineformset = galleryInlineFormSet(request.POST, request.FILES) # Essentially, we're passing a queryset
if profile_form.is_valid() and gallery_inlineformset.is_valid():
# Altering the User model through the UserProfile model's UserProfileForm representative
user.first_name = profile_form.cleaned_data['first_name']
user.last_name = profile_form.cleaned_data['last_name']
user.save()
new_images = []
for gallery_form in gallery_inlineformset:
image = gallery_form.cleaned_data.get('image')
if image:
new_images.append(Gallery(user=user, image=image))
try:
Gallery.objects.filter(user=user).delete()
Gallery.objects.bulk_create(new_images)
messages.success(request, 'You have updated your profile.')
except IntegrityError:
messages.error(request, 'There was an error saving your profile.')
return HttpResponseRedirect('https://www.youtube.com')
else:
profile_form = ProfileEditForm(request.user)
gallery_inlineformset = galleryInlineFormSet(initial=userGallery_initial)
args = { 'profile_form':profile_form, 'gallery_inlineformset':gallery_inlineformset }
return render(request, 'accounts_app/editprofile.html', args)
editprofile.html
{% block main %}
<section class="Container">
<section class="Main-Content">
<form id="post_form" method="POST" action='' enctype='multipart/form-data'>
{% csrf_token %}
{{ gallery_inlineformset.management_form }}
{% for gallery_form in gallery_inlineformset %}
<div class="link-formset">
{{ gallery_form.image }} <!-- Show the image upload field -->
<p>{{ MEDIA_ROOT }}</p>
<p>{{ MEDIA_URL }}</p>
<img src="/media/{{gallery_form.image.image.url}}">
</div>
{% endfor %}
<input type="submit" name="submit" value="Submit" />
</form>
</section>
</section>
{% endblock %}
Again, when I try:
<img src="{{ MEDIA_URL }}{{ gallery_form.image.url }}">
I get a value of "unknown" as the source, but I can click the link that "{{ gallery_form.image}}" generates and see the image that was uploaded. Trying to log both "MEDIA_URL" and "MEDIA_ROOT" yields no results. Not quite sure where the issue lies.
Use <img src="{{ gallery_form.image.url }}"> and make sure image is not None
add this line in your urls.py
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
No need to add {{MEDIA_URL}} before address of your image. because by default it will add /media before your image url path.
Also be sure to add all path starting media to your urls.
from django.conf import settings
if settings.DEBUG:
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT}))
also when trying to print an image url in django template, handle situations that image not exist like this:
<img src="{% if gallery_form.image %}{{ gallery_form.image.url }}{%else%} <default-image-path-here> {%endif%}"
While I didn't figure out why I couldn't use the .url() method Django has predefined, I did however, end up using another solution suggested to me by a user in a previous question of mine. Basically, after a user has uploaded images and we have them stored in a database, we make a variable storing the URL attribute of those images, and access that variable from the template. It looks something like this:
views.py
selectedUserGallery = Gallery.objects.filter(user=user) # Get gallery objects where user is request.user
userGallery_initial = [{'image': selection.image, 'image_url':selection.image.url} for selection in selectedUserGallery if selection.image]
if request.method == "GET":
print("--------GET REQUEST: PRESENTING PRE-EXISTING GALLERY IMAGES.-------")
profile_form = ProfileEditForm(request.user)
gallery_inlineformset = galleryInlineFormSet(initial=userGallery_initial)
template.html
<form id="post_form" method="POST" action='' enctype='multipart/form-data'>
{% csrf_token %}
{{ gallery_inlineformset.management_form }}
{% for gallery_form in gallery_inlineformset %}
<div class="link-formset">
{{ gallery_form.image }} <!-- Show the image upload field, this is not he image var from views.py -->
{% if gallery_form.image is not None %}
<p>The image should be below:</p>
<img src="{{ gallery_form.initial.image_url }}">
{% endif %}
</div>
{% endfor %}
<input type="submit" name="gallery-submit" value="Submit" />
</form>
Also, I ended up replacing most of code from the original post as I'm no longer using bulk_create().
Images cannot be shown in html.I wrote codes in models.py
class POST(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(upload_to='images/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
in views.py
def top(request):
content = POST.objects.order_by('-created_at')[:5]
return render(request, 'top.html',{'content':content})
in top.html
<div>
{% for item in content %}
<div>
<h2>{{ item.title }}</h2>
<img src="{{ item.image }}"/>
</div>
{% endfor %}
</div>
When I access in browser, html is shown.<h2>{{ item.title }}</h2> is shown but <img src="{{ item.image }}"/> is not there.When I see page source in GoogleChrome,<img src="/images/photo.jpg"/> is shown. But when I click the url,404 error happens.My application has image/images folder, in images folder surely my uploaded picture is in there.I really cannot understand why this happens.I wrote MEDIA_ROOT&MEDIA_URL in settings.py so I think image is shown in browser. How should I fix this?
make sure your /images folder is visitable in Django. an easy way to get it done is to add the "images" folder in settings.py. like:
IMAGE_URL = '/images/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "images"),
'/images/',
]
Then in your html file add {% load images %} on the top.
First make sure you have these lines in your project urls file
# Your imports ....
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [.......]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
And in your template use
{{ item.image.url }}
Use relative folder:
<img src=".{{ item.image }}"/>
resulting in
<img src="./images/photo.jpg"/>
and check if the upload worked and the image is there.
Try this: <img src="/image{{ item.image }}"/>
/ : means "Root"
. : means "Current directory"
so if your root application has image folder you need to start your path with /image
In my project i had set my media folder like this:
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
urlpatterns = [
....
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
then in my models.py i create a class like this one:
class PD_Pictures(models.Model):
pic_IDmod = models.ForeignKey(PD_Models, related_name='modello')
pic_image = models.ImageField()
pic_descr = models.CharField(max_length=50)
def __str__(self):
return self.pic_descr
at this point in my function in views.py I extract all values in db related to PD_Picture:
prod_img = PD_Pictures.objects.all()
.....
return render(
request,
'base_catalog.html',
{
'bike_mod': bike_models,
'prod_img': prod_img,
'cat_list': cat_list,
'menu_list': menu_list['menu'],
'pcontent': menu_list['cont'],
'form': c_form
},
context
)
and in my template, i would ti display related images:
{% for pic in prod_img %}
<div class="4u">
<span class="image fit"
<img src="{{ pic.pic_image }}" alt="" />
</span>
</div>
{% endfor %}
Well, at this point when I insert a new image in db, in table the path is newimage.jpg, physically on my server the image was stored in /media/newimage.jpg, how can I extract the value from the table and concatenate to the media path in my template? (<server>/media/newimage.jpg)
I have tried to use upload_to='/models/' in my ImageField but the only effect is to save image into another model folder into main model.
just try like this
{% for pic in prod_img %}
<img src="{{ pic.pic_image.url }}" alt="" />
{% endfor %}
From django official doc:
FieldFile.url
A read-only property to access the file’s relative URL by calling the url() method of the underlying Storage class.
if you try to print in your template {{ pic.pic_image }} you'll receive the db field value, while with {{ pic.pic_image.url }} the url() method from django.core.files.storage.Storage will call, and your base settings
would seem to be correct
Can you make this into your template and see what path is given?
{% for pic in prod_img %}
<p>{{ pic.pic_image }</p>
{% endfor %}
Image uploaded by user is not displaying though i have not done wrong in template. Also i have defined MEDIA_URL and MEDIA_ROOT. What might be the reason for not getting image displayed?
Code
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
project/urls.py(urls.py of main project)
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('shop.urls', namespace='shop')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
Settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
templates/shop/product/list.html
<a href="{{ product.get_absolute_url }}">
<img src="{% if product.image %} {{ product.image.url }} {% else %} {% static 'img/no_image.png' %} {% endif %}" >
</a>
I know this question is asked multiple times but my code took after the documentation and still i could not display image. Could anyone help me, please?
It is working now after fresh restart of the server. So the above code and process of serving media files is correct.