Django, Display uploaded image URL in template - python

I'm currently learning how to upload and display images in Django but I've run into a block where I can't figure out how to call the images location from the database and then display it in a template... What am I missing?
settings
MEDIA_ROOT = '/Users/chr/Desktop/DJANGO-APP/media/'
MEDIA_URL = '/media/'
models
class Product(models.Model):
product_name = models.CharField(max_length=200)
product_description = models.TextField()
def __unicode__(self):
return self.product_name
class Image(models.Model):
product_image = models.ForeignKey(Product)
image = models.ImageField(upload_to='image')
views
def productpage(request, product_image_id):
product = get_object_or_404(Product, pk=product_image_id)
render(request, 'polls/productpage.html', {'product': product})
html
<h1>{{ product.product_name }}</h1>
<br>
{{ product.product_description }}
<br>
{{ product.image.url }}
EDIT:
urls.py (main)
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls', namespace="polls")),
url(r'^admin/', include(admin.site.urls)),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

def productpage(request, product_image_id):
product = get_object_or_404(Image, product_image=product_image_id)
render(request, 'polls/productpage.html', {'product': product})
I guess product_image_id refers to the product ID?

Related

Django upload multiple images per post

I want to let the user upload multiple images per post. Similarly to an e-commerce platform with multiple images per product. But till now the images are not sent to the database.
That's my code so far:
models.py:
class Project(models.Model):
title = models.CharField(max_length=200)
describtion = models.TextField(null=True, blank=True)
class ProjectImage(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
image = models.FileField(upload_to="products")
forms.py:
class ProjectForm(ModelForm):
image = forms.ImageField(widget=ClearableFileInput(attrs={'multiple':True}))
class Meta:
model = Project
fields = ['title', 'describtion']
views.py:
def createProject(request):
form = ProjectForm()
if request.method == 'POST':
form = ProjectForm(request.POST)
images = request.FILES.getlist('image')
if form.is_valid():
project = form.save()
for i in images:
ProjectImage(project=project, image=i).save()
context = {'form':form}
return render(request, 'projects/project_form.html', context)
project_form.html:
<form class="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="form__field">
<label for="formInput#text">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<input type="submit" name="" id="">
</form>
settings.py:
STATIC_URL = '/static/'
MEDIA_URL = '/images/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/images')
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
project urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('projects.urls')),
]
app urls.py
urlpatterns = [
path("", views.createProject, name="create-project")
]
Issue:
You have made ProjectForm which relates to Project model, but the image field is in ProjectImage model. So, image field is not even passing to the template and you also haven't passed it in fields=['title','describtion'] in ProjectFrom.
You haven't made configurations for saving the media files in project's urls.py.
Solution:
You should make two forms in forms.py, first ProjectForm which will get the data for Project model and second ProjectImageForm which will get the list of images, then using request.FILES.getlist('image') you can save images which relates to a particular instance one by one in loop as you tried to save.
You should make media configurations in project's urls.py
Try Below Code:
forms.py
from django import forms
from django.forms import ClearableFileInput
from .models import Project, ProjectImage
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['title', 'describtion']
class ProjectImageForm(forms.ModelForm):
class Meta:
model = ProjectImage
fields = ['image']
widgets = {
'image': ClearableFileInput(attrs={'multiple': True}),
}
views.py
from django.http import HttpResponse
from django.shortcuts import redirect, render
from .forms import ProjectImageForm, ProjectForm
from .models import Project, ProjectImage
def createProject(request):
form = ProjectForm()
form2 = ProjectImageForm()
if request.method == 'POST':
form = ProjectForm(request.POST)
form2 = ProjectImageForm(request.POST, request.FILES)
images = request.FILES.getlist('image')
if form.is_valid() and form2.is_valid():
title = form.cleaned_data['title']
describ = form.cleaned_data['describtion']
print(title, describ)
project_instance = Project.objects.create(
title=title, describtion=describ)
print('-------------------------------------------')
print(project_instance)
print('-------------------------------------------')
for i in images:
ProjectImage.objects.create(project=project_instance, image=i)
return redirect('thanks')
context = {'form': form, 'form2': form2}
return render(request, 'projects/project_form.html', context)
def thanks(request):
return HttpResponse('<h1>Form saved.</h1>')
project_form.html or template file:
<form class="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.title.label_tag}}
{{form.title}}
<br><br>
{{form.describtion.label_tag}}
{{form.describtion}}
<br><br>
{{form2.image.label_tag}}
{{form2.image}}
<br><br>
<input type="submit" name="" id="">
</form>
project's urls.py
from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('projects.urls'))
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
app's urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('home.urls'))
]
Your models.py and settings.py can be remain same, but it's recommended to use
MEDIA_URL = 'media/' and MEDIA_ROOT = os.path.join(BASE_DIR, 'media/'), then you should make nested folders inside it to save images or any files.
Note: You should always return HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good practice in general as stated in the tutorial4.
Note: Function based views are generally written in snake_case not camelCase, you may change it to create_project from createProject.
Note: Add / at the end of upload_to as upload_to='products/' in FileField in ProjectImage model.

Serving Static Images from Application in Django

I am following a Django book which builds a web application. When I build a template, I get the same result as that of the book, except for my images - they are not there.
I am wondering what can be causing this issue. The images have correct URL's but when I try to open them, Django states "Page NOT found 404".
I am pasting the relevant code below. In addition, I include a screenshot of my directory tree.
shop/models.py:
class Product(models.Model):
category = models.ForeignKey(Category,
related_name='products')
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True)
image = models.ImageField(upload_to='products/%Y/%m/%d',
blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField()
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
template:
<a href="{{ product.get_absolute_url }}">
<img src=" {% if product.image %}
{{ product.image.url }}
{%else %}
{% static 'img/no_image.png' %}
{% endif %}
">
</a>
views.py
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category=category)
return render(request, 'shop/product/list.html',
{'category': category,
'categories': categories,
'products': products})
Edit (settings.py and urls.py):
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
urls.py
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'^admin/', admin.site.urls),
url(r'^shop/', include('shop.urls', namespace='shop')),
url(r'^cart/', include('cart.urls', namespace='cart')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)

Django object.image.url not displaying even though path is correct

I have images I uploaded through django admin, but they are not displaying. The weird thing is that I have another project with the EXACT same code and it works. object.image.url outputs /media/media/image.jpg as does my other project. But this project does not show the image. if I put an image from my static folder or if I hardcode an image, it works fine. The problem is only when I try an image uploaded from the admin it does not work. Am I missing something in my settings.py file? or anywhere?
Models.py:
from django.db import models
# Create your models here.
class Connect(models.Model):
title = models.CharField(max_length=70)
short_description = models.TextField(null=True, blank=True)
description = models.TextField()
image = models.ImageField(upload_to='media', blank=True, null=True)
def __str__(self):
return self.title
views.py:
def index(request):
about = About.objects.all()
staff = Staffmembers.objects.all()
ministries = Ministries.objects.all()
connect = Connect.objects.all()
context = {
'template': 'home',
'connect': connect,
'about': about,
'staff': staff,
'ministries': ministries,
}
return render(request,'home/index.html', context)
template(index.html):
<div class="connect-wrapper row">
<h1 class="title connect-title">Connect</h1>
{% for object in connect %}
<div class="home-div connect-div col-md-4">
<h4>{{ object.title }}</h4>
<p>{{ object.short_description }}</p>
{% if object.image %}
<img class="connect-image-home" src="{{object.image.url}}" alt="connect">
<p>{{object.image.url}}</p> //sanity check
{% endif %}
</div>
{% endfor %}
</div>
settings.py:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('home.urls'), name="home"),
]
I believe you need to add the media urls to your urls.py. Something like:
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('home.urls'), name="home"),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
On production environment Django does not load the media root automatically so that we can we can overcome that issue by adding following after url patterns:
urlpatterns = [
''''
your urls
''''
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
If you are using more than one app and including app urls on main app url, just add this on main project url.

Django: uploaded image is not showing in template

I'm trying to write a simple blog using a Django framework. I want to have a cover image for a every post.
I uploaded an image via Admin site and everything seems to be fine but image is not rendering in a browser.
Here is my files:
models.py
(...)
class Post(models.Model):
author = models.ForeignKey('Author', on_delete=models.CASCADE)
title = models.CharField(max_length=250)
slug = models.SlugField(unique=True, blank=True, max_length=250)
created = models.DateTimeField(auto_now=False, auto_now_add=True)
modified = models.DateTimeField(auto_now=True, auto_now_add=False)
image = models.ImageField(upload_to="images/%Y/%m/", blank=True, null=True)
content = models.TextField()
(...)
django_blog_project\urls.py
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'^admin/', admin.site.urls),
url(r'^', include('blog.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
blog\urls.py
(...)
urlpatterns = [
url(r'^posts/create/$', PostCreate.as_view(), name="post_create"),
url(r'^posts/([\w-]+)/$', AuthorPostList.as_view(), name="posts_by_author"),
url(r'^(?P<slug>[-\w]+)/$', PostDetailView.as_view(), name="post_detail"),
url(r'^', PostListView.as_view(), name="post_list"),
]
settings.py
(...)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
(...)
post_detail.html
{% extends "blog/base.html" %}
{% block content %}
<h1>{{ post.title }}</h1>
<img src="{{ post.image.url }}" >
<p>{{ post.content }}</p>
<p>Autor: {{ post.author }}</p>
<p>Opublikowano: {{ post.modified }}</p>
{% endblock %}
Dir tree
My directory tree
URL of the image resolving to
<img src="/media/images/2016/12/fotolia_97812586.jpg">
Adding $ char in pattern solved a problem.
blog\urls.py
(...)
urlpatterns = [
url(r'^posts/create/$', PostCreate.as_view(), name="post_create"),
url(r'^posts/([\w-]+)/$', AuthorPostList.as_view(), name="posts_by_author"),
url(r'^(?P<slug>[-\w]+)/$', PostDetailView.as_view(), name="post_detail"),
# url(r'^', PostListView.as_view(), name="post_list"), # WRONG!
url(r'^$', PostListView.as_view(), name="post_list"), # CORRECT!
]

Django Class-based ViewCreate and ViewUpdate file upload

I have a project where I wish to upload an image with the Django auto generated class-based views, and it works on the admin side, but I don't know what I'm missing to make it work from an HTML page. I've searched the web with a little luck or not enough clarification.
So maybe someone can tell me what I'm missing. Here is my code:
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'project/app/media_cdn')
models.py
from django.db import models
from django.core.urlresolvers import reverse
class Article(models.Model):
title = models.CharField(max_length = 200)
...
thumbnail = models.FileField(null = True, blank = True)
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('articles_detail', kwargs={'pk': self.pk})
class Meta:
ordering = ['-pk']
views.py
from django.shortcuts import render
from app.models import Article
from django.views.generic import *
from django.core.urlresolvers import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
# Create your views here.
def index(request):
return render(request, 'index.html')
class ArticleList(ListView):
model = Article
class ArticleDetail(DetailView):
model = Article
class ArticleCreate(LoginRequiredMixin, CreateView):
model = Article
fields = ['title', 'description', 'abstract', 'thumbnail', 'author', 'category', 'publishDate']
class ArticleUpdate(LoginRequiredMixin, UpdateView):
model = Article
fields = ['title', ..., 'thumbnail', ...]
class ArticleDelete(LoginRequiredMixin, DeleteView):
model = Article
success_url = reverse_lazy('articles_list')
urls.py
from django.conf.urls import url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from app import views, auth
urlpatterns = [
url(r'^admin/',admin.site.urls),
...
url(r'^articles/(?P<pk>[0-9]+)/$', views.ArticleDetail.as_view(), name = 'articles_detail'),
url(r'^articles/create/$', views.ArticleCreate.as_view(), name = 'articles_create'),
url(r'^articles/update/(?P<pk>[0-9]+)/$', views.ArticleUpdate.as_view(), name = 'articles_update'),
url(r'^articles/delete/(?P<pk>[0-9]+)/$', views.ArticleDelete.as_view(), name = 'articles_delete'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
article_form.html
{% extends 'layout.html' %}
{% block content %}
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
As much as I was able to gather, I managed to follow all the steps but I still can't get the thumbnail to update when uploading from articles/create/ and articles/update/.../
Thanks in advance.

Categories