I am working for the first time with aws s3, where I have images to upload from the django admin, everything works perfect on localhost, but once deployed the images are uploaded but not displayed on the web
settings.py
AWS_ACCESS_KEY_ID = 'my acceskey'
AWS_SECRET_ACCESS_KEY = 'my secret key'
AWS_STORAGE_BUCKET_NAME = 'mybucketname'
AWS_DEFAULT_ACL = None
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
AWS_S3_OBJECT_PARAMETERS = {'CacheControl': 'max-age=86400'}
STATIC_LOCATION = 'static'
PUBLIC_MEDIA_LOCATION = 'media'
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{PUBLIC_MEDIA_LOCATION}/'
DEFAULT_FILE_STORAGE = 'portfolio.storages.MediaStore'
models.py
class Project(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=200)
link = models.CharField(max_length=250)
another_link= models.CharField(max_length=250, null= True, blank=True)
image = models.ImageField(upload_to='media/')
views.py
def project(request):
projects = Project.objects.all().order_by('-id').values()
return render(request, "works.html", {"projects": projects})
Template file
{% for project in projects %}
{% csrf_token %}
<div class="row">
<div class="col-md-12 col-md-offset-1">
<div class="row">
<div class="col-xs-12 col-md-6">
<h3>{{project.name}}</h3>
<p style=> {{project.description}} </p>
Source Code
See Live
</div>
<div class="col-xs-6 col-md-4">
<img src="{{project.image.url}}" width="360" height="200" >
</div>
</div>
</div>
</div>
{% endfor %}
In the Html not return a asw link, return this
<img src="" width="360" height="200">
Images are loaded perfectly in the S3 bucket but are not displayed in the HTML.
Related
i tried to insert it via dtl variables but there were html tags on the page
models.py
html code in desciption field
class Vacancy(models.Model):
title = models.CharField(max_length=100)
specialty = models.ForeignKey(Specialty, on_delete=models.CASCADE, related_name="vacancies")
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="vacancies")
skills = models.TextField()
description = models.TextField()
salary_min = models.FloatField()
salary_max = models.FloatField()
published_at = models.DateTimeField()
html
<img src="/media/company_images/{{ vacancy.company.logo }}" width="130" height="80" alt="">
<div class="d-flex align-items-baseline align-content-baseline">
<h1 class="h2 mt-4 font-weight-bold" >{{ vacancy.title }}</h1>
<p class="m-0 pl-3">{{ vacancy.salary_min }}р – {{ vacancy.salary_max }}р</p>
</div>
<p class="mt-2">{{ vacancy.skills }}</p>
<p class="text-muted mb-4">Primal Assault (15-30 человек), Рязань или удаленно</p>
<div style="line-height: 1.8;">
{{ vacancy.description }}
</div>
If you want to render HTML from your database you can use the safe filter in your jinja HTML.
{{ YOUR_HTML_CONTENT_FROM_DATABASE | safe }}
You can also use the autoescape as defined here.
I am trying to get the uploaded image to show in the project template. Here is what my code looks like currently:
projects.html
{% extends "base.html" %}
{% block content %}
<h1>{{ project.title }} HELLO</h1>
<div class="content-section">
<div class="media">
<img src="{{ project.image.url }}" alt="beach" width=250px height=250px />
</div>
<div>
<h5>About the project:</h5>
<p>{{ project.description }}</p>
<br>
<h5>Technology used:</h5>
<p>{{ project.tools }}</p>
</div>
</div>
{% endblock content %}
models.py
class Project(models.Model):
title = models.CharField(max_length=500, unique=True)
description = models.TextField(max_length=500)
tools = models.CharField(max_length=200)
image = models.ImageField(default='default.jpg', upload_to="beach_photos", blank=True)
def __str__(self):
return f'{self.title}'
views.py
from django.shortcuts import render
from django.http import HttpResponse
from projects.models import Project
def projects(request):
project = {
'project':Project.objects.all()
}
return render(request, 'projects/projects.html', context = project)
settings.py configuration (app is installed)
STATIC_URL = 'static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
When I inspect the image element in the webpage, the source shows up as
src=""
None of the other calls to the model are appearing either.
Any help would be appreciated.
i think you forgot to add a for-loop in your template. try this:
{% for p in project %}
{{ p.title %}}
{% endfor %}
Make sure that the image field of your record in the database is full.
Access the required model with the python manage.py shell command and check if this model has a value of variable.image.url.
I made a django app that stores notes of different semesters and branches and I want to display the profile image of the uploader of the post right next to their name in homepage of my website. I am using my staticfiles directly from the S3 bucket
The notes that the users upload is stored in the notes/models.py whereas the user's profile and their profile image is stored in users/models.py
What I want to do is in home.html (below) use something like,
{% static post.uploader.profile.image.url %} but suddenly it does not work.
Settings.py
AWS_ACCESS_KEY_ID='XXXXXXXXXXXXXXXXXX'
AWS_SECRET_ACCESS_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXX'
AWS_STORAGE_BUCKET_NAME='django-XXXXX'
AWS_S3_REGION_NAME = "ap-south-1"
AWS_S3_SIGNATURE_VERSION = "s3v4"
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
# s3 static settings
AWS_LOCATION = 'staticfiles'
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_LOCATION}/'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# s3 public media settings
PUBLIC_MEDIA_LOCATION = 'media'
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{PUBLIC_MEDIA_LOCATION}/'
DEFAULT_FILE_STORAGE = 'django_project.storage_backends.PublicMediaStorage'
# s3 private media settings
PRIVATE_MEDIA_LOCATION = 'private'
PRIVATE_FILE_STORAGE = 'django_project.storage_backends.PrivateMediaStorage'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
notes/models.py
class Notes_Model(models.Model):
"""Store notes of different branches and semesters."""
uploader = models.CharField(max_length=200)
title = models.CharField(max_length=200)
date_posted = models.DateTimeField(auto_now_add=True)
description = models.TextField(max_length=2500)
branch_choice = models.CharField(max_length=50, choices=branch_choices, default='cse')
file_semester = models.IntegerField(choices=semester_choice)
file = models.FileField()
syllabus = models.TextField(max_length=200, default='No Syllabus Availibe Yet')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("notes-detail", kwargs={"pk": self.pk})
users/models.py
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.svg', upload_to='profile-pics')
def __str__(self):
return (f'{self.user.username} Profile')
def save(self):
super.save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
home.html
{% extends "base.html" %}
{% block content %}
{% load static %}
<div>
{% for post in posts %}
<article class="media content-section">
<img class="rounded-circle article-img" <!--this src is posing the issue -->src="{% static post.uploader.profile.image.url %}" width="60" height="60" style="margin-right: 30px">
<div class="media-body">
<p class="mr-2 text-capitalize">{{ post.uploader }}</p>
<small class="text-muted font-italic">{{ post.date_posted }}</small>
<div class="article-metadata">
</div>
<h2><a class="article-title text-info text-capitalize" href="{% url 'notes-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endfor %}
</div>
xml from aws s3 bucket says that no key is present but it is present in the bucket.
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>staticfiles/</Key>
<RequestId>960CD372E7128E16</RequestId>
<HostId>
90tvY+TT6FkefEheQXtuOLv5T8fCvJsDzIOBpam8inz4GGdhpb9QXrkToDCl/3yN+69tJoUUYQo=
</HostId>
</Error>
Url that gets returned is: https://django-xxxxxxx.s3.amazonaws.com/staticfiles/
whereas it should be
Expected url that gets returned: https://django-xxxxxx.s3.amazonaws.com/staticfiles/profile.jpg
Problem:
Top left part of the image is not being rendered
You're using the {% static %} templatetag, for something that is not a static file. It's a media file. The value of post.uploader.profile.image.url should be the actual URL to the image as a media asset. Passing that URL to {% static %} tries looking up the URL as the name of a static asset, which is why you get the NoSuchKey error.
I'm sure i'm obviouly did something very stupid but, when I try to upload my profile picture on my blog website, even when I add one through admin page, the picture doesn't come up..
so here's what's happening,
blog pic:
the picture right next to Kimmc6008, I should see my image, but somehow failed..
here's the code, I will upload more if needed.
models.py
class Author(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_picture = models.ImageField()
def __str__(self):
return self.user.username
class CategoryBlog(models.Model):
title = models.CharField(max_length=20)
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=100)
overview = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
comment_count = models.IntegerField(default=0)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
thumbnail = models.ImageField()
categories = models.ManyToManyField(CategoryBlog)
featured = models.BooleanField(null=True)
def __str__(self):
return self.title
views.py
def blog(request):
post_list = Post.objects.all()
context = {
'post_list': post_list
}
return render(request, 'blog.html', context)
and my html
<!-- post -->
{% for post in post_list %}
<div class="post col-xl-6">
<div class="post-thumbnail"><img src="{{post.thumbnail.url}}" alt="..." class="img-fluid"></div>
<div class="post-details">
<div class="post-meta d-flex justify-content-between">
<div class="date meta-last">20 May | 2016</div>
{% for cat in post.categories.all %}
<div class="category">{{ cat }}</div>
{% endfor %}
</div><a href="/post">
<h3 class="h4">{{ post.title }}</h3></a>
<p class="text-muted">{{ post.overview }}</p>
<footer class="post-footer d-flex align-items-center">
<a href="#" class="author d-flex align-items-center flex-wrap">
<div class="avatar"><img src="{{ post.author.profile_picture.url }}" alt="..." class="img-fluid"></div>
<div class="title"><span>{{ post.author.user.username }}</span></div>
</a>
<div class="date"><i class="icon-clock"></i>{{ post.timestamp|timesince }} ago</div>
<div class="comments meta-last"><i class="icon-comment"></i>{{ post.comment_count }}</div>
</footer>
</div>
</div>
{% endfor %}
Thank you for your help!!
EDIT
I noticed I was missing MEDIA_ROOT in my settings.py.
Would this be the reason why?
Add the upload_to argument in your ImageField
profile_picture = models.ImageField(upload_to='pictures')
And these are the basic settings you need to have in your django project for image/files handling
project/urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [..]
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')
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