I'm working on a simple blog, I have this model for the blog post:
class BlogPost(models.Model):
title = models.CharField(max_length=150, unique=True)
body = models.TextField()
cover_image = models.ImageField(upload_to='blogposts/')
created_on = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
category = models.ManyToManyField('PostCategory', related_name='posts')
slug = models.SlugField(null=True, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("blog_detail", kwargs={"slug": self.slug})
In the settings file, I have the following configuration for static and media files:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
I'm creating the blog models and views in a separate app I named "blog"
I'm using a Django classed-based list view to display the posts on the page:
class BlogListView(ListView):
model = BlogPost
template_name = "blog/blog_list.html"
And I have the URL files working just fine:
The problem is in displaying it in my template view, primarily for the post's cover image:
{% for post in object_list %}
<div class="single-blog-item style-2 d-flex flex-wrap align-items-center mb-50">
<!-- Blog Thumbnail -->
<div class="blog-thumbnail">
<a href="{{ post.get_absolute_url }}">
<img src="{{ post.cover_image }}" alt="">
</a>
</div>
<!-- Blog Content -->
<div class="blog-content">
{{ post.title }}
<p>We'll come back to this...</p>
<div class="post-meta">
<i class="icon_clock_alt"></i> {{ post.created_on }}
<i class="icon_chat_alt"></i> 3 Comments
</div>
</div>
</div>
{% endfor %}
Every other tag is working just fine except for the cover image. The {{ post.cover_image }} template tag is not displaying any image, after inspecting the page for one of the posts, I find it is linking to:
http://127.0.0.1:8000/blog/blogpost/12.png
the page above doesn't exist, the image was actually uploaded to the media folder. Hence, the uploaded image from the model is found here:
http://127.0.0.1:8000/media/blogpost/12.png
but the {{ post.cover_image }} tag is linking elsewhere to the inexistent page below:
http://127.0.0.1:8000/blog/blogpost/12.png
How do I resolve this to allow the tag link to the right location to display the correct image URL?
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I figured out the answer from Ivan's comment;
Using {{ post.cover_image }} does not render the URL of the image (or media file) generally, it only renders the file name and location in the media root.
Hence,
{{ post.cover_image }} = blogposts/12.png
which automatically joins with the blog page URL to produce the inexistent link for the image shown in the post.
However,
{{ post.cover_image.url }}
fixes this, with the .url addition, it renders the URL of the media file and displays it correctly.
Thus:
{{ post.cover_image.url }} = http://127.0.0.1:8000/media/blogpost/12.png
This works fine!
Related
This is my first Django project and I have one problem. file1 is saved to media folder\files however when I try to download the file I'm getting 404. Any help is appreciated!
127.0.0.1:8000/about/files/2021/01/22/pyqt_tutorial_EB2ZapN.pdf
models.py
class Links(models.Model):
file1 = models.FileField(upload_to = 'files/%Y/%m/%d/')
is_published = models.BooleanField(default = True)
publish_date = models.DateTimeField(default = datetime.now, blank = True)
html
{% for link in links %}
<div class="links1">
<h3>Download Link</h3>
<p>{{ link.publish_date }}</p>
</div>
{% endfor %}
urls.py>
urlpatterns = [
path('admin/', admin.site.urls),
path('about/', about, name = 'about')
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
settings.py>
# Media Folder Settings
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Update: from the admin panel if I click on the link I can see it. Maybe In the {{ link.file1 }} url something need to be changed?
The href in your template should be {{ link.file1.url }} to properly construct the path to the file.
I'm preparing a blog component of a site, it is created inside an app of a project. It seems that there is no problem except the images are not displayed.
while running, all things are OK, but just the image "alt" is displayed instead of the image. I have images without problem in other pages of this project.
There is a report on Terminal:
"Not Found: /article/static/images/growth_EWAl68g.png
[14/Apr/2019 17:44:38] "GET /article/static/images/growth_EWAl68g.png HTTP/1.1" 404 6164"
As you can see, Django uses a false address (static folder is located in root of projects) to access the images.
class BlogArticle(models.Model):
title = models.CharField(max_length=150)
headline = models.CharField(max_length=300)
body = models.TextField()
post_image = models.ImageField(upload_to ="static/images")
date = models.DateTimeField(auto_now_add=True)
author = models.CharField(max_length=100)
def __str__(self):
return self.title
class ArticleListView(ListView):
model = BlogArticle
template_name = 'article_list.html'
urlpatterns = [
path('', views.HomeView, name= 'home'),
path('article/', views.ArticleListView.as_view(), name='article_list'),
path('article/<int:pk>/', views.ArticleDetailView.as_view(), name='article_detail'),
.
.
.]
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('contactus', include('sendemail.urls')),
path('', include('myapp.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
{% block content %}
<div <div class="container mt-5 bg-light">
{% for article in object_list %}
<div class="form-row">
<div class="form-group col-sm-9 ">
<div class="post-entry">
<h5 > <a href = "{% url 'article_detail' article.pk %}" > {{ article.title }}</a></h5>
<div>
<p class="font-weight-bold"> {{article.headline }} </p>
</div>
<div>
<span class="text-muted">by {{article.author }} | {{ article.date|date:"M d, Y"}}</span>
</div>
</div>
</div>
<div class="form-group col-sm-3 ">
<div class="thumbnail">
<img src="{{article.post_image}}" width=100 height=100 class="rounded" alt="{{article.title}}">
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
.
DEBUG = True
ALLOWED_HOSTS = []
.
.
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
.
.
I can't understand this condition, It seems that Django should go to static/images/ but it has an extra word (article) at the beginning of the address.
This problem was simply solved by adding
urlpatterns +=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
to project's urls.py and
MEDIA_URL = '/media/'
in settings.py.
I'm trying to display a form, using a model form in django. Everything looks like it's setup properly, and I'm not getting any error. Simply, the form is not showing, although the url is updated...
views.py
from rulz.models import Rulz
class rules_create(CreateView):
model = Rulz
fields=['title', 'content']
models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Rulz(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
country = models.CharField(max_length=255,default='France')
city = models.CharField(max_length=255,default='Paris')
player_num = models.IntegerField(default=2)
complexity = models.IntegerField(default=1)
created_on = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User,on_delete=models.CASCADE,default=1)
def get_absolute_url(self):
return reverse('rulz:rulz_detail',kwargs={'pk':self.pk})
urls.py (in the app)
app_name = 'rulz'
urlpatterns = [
#/rulz/
url(r'^', views.rules_index.as_view(), name='rulz_index'),
url(r'^index/$', views.rules_index.as_view(), name='rulz_index'),
# /rulz/details
url(r'^(?P<pk>[0-9]+)/$',views.rules_detail.as_view(),name='rulz_detail'),
#rulz/create
url(r'^create/',views.rules_create.as_view(),name='rulz_create'),
]
urls.py (root folder)
...
url(r'^rules/',include('rulz.urls')),
...
app/templates/app/rulz_form.html
{% extends 'rulz/Rulz_base.html' %}
{% block body %}
{% load staticfiles %}
{% include 'rulz/form-template.html' %}
{% endblock %}
app/templates/app/form-template.html
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<div class="validate-input m-b-26" >
<label class="label-input100">{{ field.label_tag }}</label>
<div class="input100">{{ field }}</div>
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.help_text }}</span>
</div>
</div>
</div>
and finally the button with the link in my page to access the form :
Go create Rule
I really don't know what I am missing. When I click this button, the url is uploaded to http://127.0.0.1:8000/rules/create/ but the displayed page is exactly the same.
Any clue ?
Thanks
You need to terminate your index regex. At the moment it matches every string the has a start, which of course means every string. Use the $:
url(r'^$', views.rules_index.as_view(), ...
(As an aside, you should avoid having two patterns for the same view.)
In the documentation you can find the list of the attributes needed to correctly rendering your form using CreateView.
So, you need to modify your class based view to look like at least this example:
from rulz.models import Rulz
class rules_create(CreateView):
form_class = YOUR_FORM # The form that will be used with this class
model = Rulz
fields=['title', 'content']
success_url = 'YOUR_SUCCESS_URL' # If success redirect to this URL
I have two apps in my project.
They are:
Blog app
Accounts app
In accounts app contains user profiles like Images, Bio, DOB etc, In blog app each user has their own blog page and Each page must have comments so any user can comment any blog. In comments section, it shows username and his unique profile URL.Now my problem is I can't load their profile images.
models.py
class comments(models.Model):
blogger= models.ForeignKey(blog,on_delete=models.CASCADE)
user = models.ForeignKey(User)
created = models.DateTimeField(auto_now_add=True)
comment = models.TextField()
def get_absolute_url(self):
return reverse('blog:comments',args = [ self.id])
views.py
commentz = comments.objects.filter(blogger= id).all().order_by('-created')[:10]
for pic in commentz:
image = UserProfile.objects.filter(user = pic.user)
I know this is insane :-/
annotate can help to look up relational fields
from django.db.models import F
# include image field in queryset
commentz = comments.objects.annotate(image=F('user__image')).filter(blogger= id).all().order_by('-created')[:10]
# Access image
commentz[0].image
My problem is solved.when we render an image from one app to another.we need to use absolute URL and inside hyperlink, we have to call models name.In my case model name is UserProfile.
<a href="{% url 'accounts:view_profile' username=c.user %}"><img src="{{
c.user.userprofile.image.url }}"></a>
{% if class_comments %}
{% for c in class_comments %}
<div class="row">
<div class="col-lg-1 col-xs-6">
<div class="thumbnail">
<img class="img-responsive user-photo" src="{{ c.user.userprofile.image.url }}">
{% endfor %}
{% endif %}
I am trying to display images that have been uploaded by the user, but no matter what I try I am getting the broken link icon. I have searched and searched through the documentation, on SO and elsewhere for a couple of days now to no avail. I am new to Django and currently in development so I'm sure I've made some other rookie mistakes, but right now the only thing I care about is displaying uploaded images in templates.
Here are the relevant snippets of my code:
settings.py
MEDIA_URL = '/media/media_root/'
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "media", "media_root")
urls.py
urlpatterns = [
url(r'^admin/?', admin.site.urls),
url(r'^accounts/', include('registration.backends.simple.urls')),
url(r'^about/?', profiles.views.about, name='about'),
url(r'^properties/single/?', properties.views.single, name='single_mens'),
url(r'^properties/married/?', properties.views.married, name='married'),
url(r'^properties/add/add_photos/?', properties.views.add_photos, name='add_photos'),
url(r'^properties/add/?', properties.views.add_rental, name='add_rental'),
url(r'^', profiles.views.home, name='home'),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += staticfiles_urlpatterns()
models.py
class RentalPicModel(models.Model):
def __unicode__(self):
return self.image.url
image = models.ImageField(upload_to="pics/originals/", null=True)
rental = models.ForeignKey(RentalModel, on_delete=models.CASCADE)
forms.py
class AddPhotosForm(forms.ModelForm):
class Meta:
model = RentalPicModel
fields = ['image', 'rental']
def clean_image(self):
return self.cleaned_data['image']
def clean_rental(self):
return self.cleaned_data['rental']
views.py
def add_photos(request):
form = AddPhotosForm
current_rental = None
current_photos = []
if request.method == "POST":
form = AddPhotosForm(request.POST, request.FILES)
if request.POST.get('another'):
if form.is_valid():
cleaned_image = form.cleaned_data['image']
cleaned_rental = form.cleaned_data['rental']
current_rental = cleaned_rental
pic = RentalPicModel(image=cleaned_image, rental=cleaned_rental)
pic.save()
current_photos = RentalPicModel.objects.filter(rental=current_rental)
current_photos = [rental.image for rental in current_photos]
for photo in current_photos:
print photo
context = {
'form' : form,
'photos' : current_photos,
}
return render(request, "add_photos.html", context)
Here the output of the print statement (after uploading one photo) is: pics/originals/DSC_1376.jpg and I can see the file is saved to that location.
add_photos.html
<div class="container">
<h1>Upload your photos here.</h1>
<br>
<div class='row'>
<form method="POST" action="" enctype="multipart/form-data"> {% csrf_token %}
{{ form|crispy }}
<div class='col col-xs-3'></div>
<div class='col col-xs-3'>
<input class="btn btn-block btn-info" name="another" type="submit" value="Save and Add Another">
</div>
<div class='col col-xs-3'>
<input class="btn btn-block btn-primary" name="finish" type="submit" value="Save and Finish">
</div>
<div class="col col-xs-3"></div>
</form>
</div>
{% if photos|length > 0 %}
<h2>Uploaded photos:</h2>
{% for photo in photos %}
<div class='row'>
<img src="{{ photo.url }}" alt="">
</div>
{% endfor %}
{% endif %}
</div>
When I inspect the <img> element, I see src="/media/media_root/pics/originals/DSC_1376.jpg" which gives me a url of http://127.0.0.1:8000/media/media_root/pics/originals/DSC_1376.jpg. This seems to be the correct file location to me, but it is still not displaying.
Like I say, everything seems to me to be set up how it is described in the Django documentation and in every other question I've read on SO. What am I missing?
Thank you in advance.
EDIT
Do I need to modify my STATICFILES_DIRS setting at all for uploaded media? Here is what I have right now:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static_files"),
)
which is where I've put all my CSS and javascript files.
You forgot to concatenate the MEDIA_URL and the {{ photo.url }}.
Try:
<img src="{% get_media_prefix %}{{ photo.url }}" alt="">
More about {% get_media_prefix %} HERE in the docs.
My urls were the problem. When it was trying to retrieve the media files, it matched url(r'^', profiles.views.home, name='home') before it matched any of the media urls. A simple $ fixed it:
url(r'^$', profiles.views.home, name='home')