I am trying to make a blog with an imagefield for my posts. I have imageupload working in the django admin panel but I have broken thumbnails. If I click on the images I got a 404 error with the following:
Using the URLconf defined in firstblog.urls, Django tried these URL patterns, in this order:
^$ [name='home']
^admin/
The current URL, images/heroimage/, didn't match any of these.
in my models.py I have:
from django.db import models
from django.db.models import permalink
class posts(models.Model):
author = models.CharField(max_length = 45)
title = models.CharField(max_length = 100)
bodytext = models.TextField()
timestamp = models.DateTimeField()
image1 = models.ImageField(upload_to="images/heroimage/", default='')
category = models.ForeignKey('blog.Category', default='')
def __unicode__(self):
return '%s' % self.title
#permalink
def get_absolute_url(self):
return ('view_blog_post', None, { 'slug': self.slug })
class Category(models.Model):
title = models.CharField(max_length=100, db_index=True)
slug = models.SlugField(max_length=100, db_index=True)
def __unicode__(self):
return '%s' % self.title
#permalink
def get_absolute_url(self):
return ('view_blog_category', None, { 'slug': self.slug })
What I'm trying to do is to have the image that was uploaded to the post, displayed on the site.
Here is my index.html where I try to call the image to the post.
<div class="container">
<h1>First Blog</h1>
{% for post in posts %}
<div class="posts">
<p> <img src="{{blog.image1.url}}" /> {{ blog }}</p>
<h2>{{ post.title }}</h2>
<h3>Posted on {{ post.timestamp }} by {{ post.author }}</h3>
<p> {{ post.bodytext }}</p>
</div>
<hr>
{% endfor %}
</div>
my django project I created was called firstblog , I then have an app named blog. In the root of my project folder "firstblog" I have a folder for images and then a sub folder inside that one called heroimage.
Can anyone help me get this working?
Thanks
It is appended to your MEDIA_ROOT setting.
https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.FileField.upload_to
Set a media root for uploaded files the to retrieve the files, ill give you an example:
# settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# models
class Blog(models.Model):
main_image = models.ImageField(default='none/none.jpg', upload_to='blog'
# template
<img src="/media/{{ blog.main_image }}">
# media folder after
media/blog/imageuploaded.jpg
media/none/none.jpg # This file was already created
To upload to the static directory change
MEDIA_ROOT = STATIC_ROOT or STATICFILES_DIRS[0]
Though this is absolutely not recommended!
Related
Hello I just put my blog online on cpanel hosting. I managed the display with the whitenoise library of python. The static images work normally. But when I call the image from blogpost to display my image does not appear with post.photo.url. I am under cpanel and I would like to ask for your help to display the images of my blog on my site
class Photo(models.Model):
image = models.ImageField(verbose_name='image')
caption = models.CharField(max_length=128, blank=True, verbose_name='légende')
date_created = models.DateTimeField(auto_now_add=True)
IMAGE_MAX_SIZE = (1900, 1265)
def resize_image(self):
image = Image.open(self.image)
image.thumbnail(self.IMAGE_MAX_SIZE)
image.save(self.image.path)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.resize_image()
def __str__(self):
return self.caption
My models.py
class BlogPost(models.Model):
slug = models.SlugField()
categorie = models.ForeignKey(CategorieBlogs, on_delete=models.CASCADE)
image = models.ForeignKey(Photo, on_delete=models.CASCADE)
title = models.CharField(max_length=500, verbose_name="titre blog")
subtitle = models.CharField(max_length=500, verbose_name="sous titre")
contenu = models.TextField(max_length=1500, verbose_name="contenu blog")
description = models.TextField(max_length=2000, verbose_name="contenu blog 2")
titles = models.CharField(max_length=500, verbose_name="titre 2")
photo = models.ImageField(upload_to="photo blog")
contenus = models.TextField(max_length=2000, verbose_name="paragraph 2", blank=True)
descriptions = models.TextField(max_length=2000, verbose_name="paragraph contenu 2", blank=True)
datepub = models.DateField(verbose_name="Date de publication", auto_now_add=True)
published = models.BooleanField(default=False)
auteur = models.ForeignKey(AuteurPost, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("posts:home")
def __str__(self):
return self.title
class Meta:
ordering = ['-datepub']
verbose_name = "Blog"
My views
class BlogHome(ListView):
model = BlogPost
context_object_name = "posts"
template_name = "blog/list.html"
def get_queryset(self):
queryset = super().get_queryset()
if self.request.user.is_authenticated:
return queryset
return queryset.filter(published=True)
class BlogPostDetail(DetailView):
model = BlogPost
context_object_name = "post"
template_name = "blog/detail.html"
My urls.py
from django.urls import path
from .views import BlogHome, BlogPostDetail
app_name = "posts"
urlpatterns = [
path('', BlogHome.as_view(), name="home"),
path('<str:slug>/', BlogPostDetail.as_view(), name="post"),
]
my html code
<header class="masthead" style="background-image: url('{{ post.image.image.url }}')">
<div class="container position-relative px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<div class="post-heading">
<h1>{{post.title}}</h1>
<h2 class="subheading">{{post.subtitle}}</h2>
<span class="meta">
Publié Par
{{post.auteur }}
le {{ post.datepub}}
</span>
</div>
</div>
</div>
</div>
</header>
<!-- Post Content-->
<article class="mb-4">
<div class="container px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<p> {{ post.contenu }}</p>
<p> {{ post.description }}</p>
<h2 class="section-heading">{{ post.titles }}</h2> <br> <br>
<img class="img-fluid" src="{{ post.photo.url }}" alt="post.photo" />
<p>{{ post.contenus }}</p>
<p> {{post.descriptions}}</p>
</div>
</div>
</div>
</article>
First of all I think you have not configured your static files and media files. Try configuring it as follows. In your settings.py ensure to include STATICFILES_DIR, STATIC_ROOT, MEDIA_URL, MEDIA_ROOT in your settings.py and then add the below lines below STATIC_URL = 'static/'
MEDIA_URL = 'media/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles/'
MEDIA_ROOT = BASE_DIR / 'static/media'
By doing this you are telling django where to get your static files. now your have to add the link of the static files in your project urls.py. you will add that as below.
from django.conf import settings
from django.conf.urls.static import
static
urlpatterns = [
.......
]
urlpatterns +=
static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
One last thing that I assumed you had done is creating static folder in your project root and inside that static folder create media folder where all the images you want to load are. Now run python manage.py collectstatic
Django can be able to display the image if I comment out the product details page.
I would like to know why it does that and how can I make it always display the images.
Product model
item_name = models.CharField(max_length=20)
item_description = models.TextField(
max_length=200, verbose_name="Item Description")
item_price = models.FloatField(default=0.00)
slug = models.SlugField(null=True, unique=True)
item_details = models.TextField(
max_length=1000, verbose_name="Item Details")
item_quantity = models.IntegerField(default=0)
item_availability = models.BooleanField(default=False)
is_item_featured = models.BooleanField(default=False)
is_item_recommended = models.BooleanField(default=False)
# Todo: add Is On Carousel Filter
item_brand = models.ForeignKey(Brand, null=True, on_delete=models.CASCADE)
item_categories = models.ForeignKey(
Category, null=True, on_delete=models.CASCADE)
item_image = models.ImageField(upload_to='images/product/',
default="images/product/image-placeholder-500x500.jpg")
Product Views
class HomePageView(ListView):
model = Product
template_name = 'product/index.html'
class ProductListView(ListView):
model = Product
template_name = 'product/product_list.html'
def product_detail(request, slug):
objec = get_object_or_404(Product, slug=slug)
template_name = 'product/product_detail.html'
return render(request, template_name, context={'object': objec})
Product Templates
{% for product in object_list %}
<div class="col-md-3 col-sm-6">
<div class="product-grid4">
<div class="product-image4">
<a href="product/{{ product.slug }}">
<!-- <img src="{{ product.item_brand.brand_image.url }}" alt="{{ product.item_brand.brand_name }}" width="30px"> -->
<img class="pic-1" src="{{ product.item_image.url }}" alt="{{ product.item_name }}">
</a>
<!-- <span class="product-new-label">Recommended</span> -->
<!-- <span class="product-discount-label">-10%</span> -->
</div>
<div class="product-content">
<h3 class="title">{{ product.item_name }}</h3>
<div class="price">
Kshs. {{product.item_price }}
<!-- <span>$16.00</span> -->
</div>
<a class="add-to-cart" href="{% url 'add-to-cart' product.slug %}">ADD TO CART</a>
</div>
</div>
</div>
{% endfor %}
Product Urls
url(r'product/(?P<slug>.+)$', views.product_detail, name='product-detail'),
url('^$', views.HomePageView.as_view(), name='landing_page'),
url('shop/', views.ProductListView.as_view(), name="product-list")
Settings.py
.....
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
The error I get. Please note the error only comes up when product_detail view and it's url are called. When they are commented out, the images are displayed.
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/media/images/product/airmax_98_bVXgZPB.jpg
Raised by: shop.views.product_detail
No Product matches the given query.
If you don't want have problems when you change urlpattern, you should replace <a href="product/{{ product.slug }}"> to <a href="{{ product.get_absolute_url }}"> and add a bit of code to models.py
*product fields goes here*
def get_absolute_url(self):
return reverse('product-detail', args=[self.slug])
And don't forget from django.urls import reverse
I've noticed that your django is not pretty new, and if Can not import reverse from django.urls
The problem is with how the url is being displayed.
I should Use path instead of url like so:
Product Urls
......
path('product/<slug>/', views.product_detail, name='product-detail'),
path('shop/', views.ProductListView.as_view(), name="product-list"),
......
I still don't have a clear understanding as to why I should use path instead of url
I have model named Book in models.py file.
And based on this model, a view has been created to display images as products.
Which renders books(products) on shop.html template.
Problem is that i am unable to get their cover images which are saved across each publishers id who is seller of those books.
This is code of shop.html (in which i am trying to display image).
<div class="container mt-4">
<div class="row">
{% for b in books|slice:":10" %}
<div class="col-lg-2 col-md-3 col-sm-4">
<div class="book-card">
<div class="book-card__book-front">
<img src={{MEDIA_URL}}{{b.cover.url}} alt="book-image">
</div>
</div>
<div class="book-card__title">
{{ b.title }}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
This is the model in which i am putting covers of books against publisher's ids (names)
def book_cover_path(instance, filename):
return os.path.join(
"covers", instance.publisher.user.username, str(
instance.pk) + '.' + filename.split('.')[-1]
)
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField('Title', max_length=255)
authors = models.ManyToManyField(Author, related_name='books_written')
publisher = models.ForeignKey(Publisher, on_delete=models.DO_NOTHING, related_name='books_published')
price = models.DecimalField('Price', decimal_places=2, max_digits=10)
description = models.TextField('Description')
upload_timestamp = models.DateTimeField('Uploading DateTime', auto_now_add=True)
categories = models.ManyToManyField(Category, related_name='book_category')
cover = models.ImageField(upload_to=book_cover_path, null=True,blank=True)
class Meta:
unique_together = ('title', 'publisher')
get_latest_by = '-upload_timestamp'
This is view in views.py
def shop(req):
bookz = Book.objects.order_by('title')
var = {'books': bookz, 'range': 10}
return render(req, 'bookrepo/shop.html', context=var)
This is media setting in settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
This is my folder structure i did put covers in media/covers/publisher/image.jpg EVEN i tried something like this media/media/covers/publisher/image.jpg
This is structure of media directory
I am getting NOT FOUND error in django console
Not found error like these
I think this have to do something with url i m trying to create must be missing something.
Otherwise b.title is working fine. Issue is just with image retrieval.
IF anyone don't understand book_cover_path function they can just tell me the way to make url as if books are lying in media/covers/image.jpg because i am unable to do this ALSO. As,
cover = models.ImageField(upload_to='covers', null=True,blank=True)
replace this line
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
to
MEDIA_ROOT = os.path.join(BASE_DIR,'media/')
because it is the Absolute path to the directory that will hold the file.
and replace
<img src={{MEDIA_URL}}{{b.cover.url}} alt="book-image">
to
<img src="{{b.cover.url}}" alt="book-image">
and add these lines in projects url.py file
from django.conf import settings
from django.conf. urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
try this on shop.html ,Check the docs here.
<img src="{{ b.cover.url }}" alt="book-image">
Currently using Django 1.9.
Image files in my model are uploading properly to
project\media\FILEPATH.jpg
However, images are attempting to be displayed using the filepath without \media. For example, when I go to my localhost http://127.0.0.1:8000/media/FILEPATH.jpg in my browser, I get a 404 because Django's get request is looking for:
project\FILEPATH.jpg
How do I get django to serve my media files properly with \media\?
More information if it may be of any use:
settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.dirname(os.path.join(BASE_DIR, 'media'))
model:
image = models.ImageField(upload_to='media', blank='true')
project urls.py I have the following after urlpatterns as per the documentation:
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Thank you for any help!
models.py
class Post(models.Model):
ptype = models.ForeignKey('blog.Type', related_name='posts')
title = models.CharField(max_length = 100)
text = models.TextField()
published_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
class Image(models.Model):
post = models.ForeignKey('blog.Post', related_name='images')
image = models.ImageField(upload_to='media', blank='true')
views.py
class Posts(generic.ListView):
model = Post
context_object_name = 'posts'
template_name = 'blog/posts.html'
posts.html
{% extends "blog/base.html" %}
{% block content %}
{% for post in posts %}
<p>{{post.title}}</p>
<p>{{post.text}}</p>
{% for image in post.image_set.all %}
<img src="{{ image.image.url }}">
{% endfor %}
{% endfor %}
{% endblock %}
Ok
When your declare the upload on the model, Django detect automatically that your route of media is BASE_DIR/media, when you put somthing in upload_to on the model you are declare that this image have to saved on BASE_DIR/media/something
Example: if I want to save the user's images into media I have to make this on the model
image = models.ImageField(upload_to='users/', blank='true')
and my image will saved on localhost/media/users/FILEPATH.jpg
All this url after media/ is saved on your field of 'image' so your image field will say just 'users/FILEPATH.jpg' but not the localhost/media/
Thats why you need to write the /media/ in you src
<img src="/media/{{ image.image }}">
and if you save the image on the field named 'image' your will not need the .url.
Try it.
I'm new at Django and I've been following the django tutorial "djangogirl" but i wanted to add pictures so I did a model.py like this:
class Post(models.Model):
author = models.ForeignKey('auth.User')
image = models.ImageField()
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
This is my view.py:
def posts(request):
posts = Post.objects.order_by('published_date')
return render(request, 'my_blog/posts.html', {'posts': posts})
And my_blog.html:
{% extends 'my_blog/base.html' %}
{% load staticfiles %}
{% block content %}
<link rel="stylesheet" href="{% static 'style/css/posts.css' %}">
<div id="postsContainer">
<div id="posts">
{% for post in posts %}
<div>
<h3 class="date">Published the: {{ post.published_date }}</h3>
<h1>{{ post.title }}</h1>
<img src="{{ post.image.url }}"/>
<p>{{ post.text|linebreaks }}</p>
</div>
<div id="button">
<button type="button" class="btn btn-primary">Read more</button>
</div>
<div class="top-divider"></div>
{% endfor %}
</div>
</div>
{% endblock %}
And I insert my image via the Django admin page.
The problem is the URL that is returned in my HTML is really weird like: ./images_SseHlrA.png and it doesn't obviously display the picture correctly. How can I fixed it?
Apparently the picture are 'stocked' at the root level (same level than the file manage.py the question is why? and how can I change it and what is the best way to do so?
alix is right that "You need to specify where to store images uploaded by user" by specifying upload_to in the field constructor. But you don't need a special class to handle all of this. Way too complicated. Let's say you have this in your settings:
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
MEDIA_URL = '/uploads/'
In your template, you should now be able to do something like:
<img src="{{ post.image.url }}">
You need to specify where to store images uploaded by user. Try this in your models.py:
from django.utils.deconstruct import deconstructible
#deconstructible
class PathAndRename(object):
def __init__(self, sub_path):
self.path = sub_path
def __call__(self, instance, filename):
ext = filename.split('.')[-1]
# set filename as random string. change here as you want
filename = '{}.{}'.format(uuid4().hex, ext)
# return file path
return os.path.join(self.path, filename)
path_and_rename = PathAndRename("/images")
And then in model:
image = models.ImageField(upload_to=path_and_rename)
You can read more about ImageField here and here