Hi Everyone
I am building a simple blog app using Django. I have created two pages so far: index.html and posts.html. On the home page, the blog title created date, and blog content is loading dynamically from the database. Now I wish to make sure when a visitor clicks any title from the home page the URL will be something like
yourdomain.com is available for purchase - Sedo.com. I was able to configure the urls.py file. However, when I click any blog title from the home page it doesn’t load anything.
Here is the code details :
urls.py file
urlpatterns = [
path('', views.index, name='index'),
path('<str:pk>', views.post, name='post'),
]
views.py file
def index(request):
posts = Post.objects.all()
return render(request, 'index.html', {'posts': posts})
def post(request, pk):
posts = Post.objects.filter(title=pk.replace('-', ' '))
return render(request, 'posts.html', {'posts': posts})
index.html file :
<div class="media">
<div class="media-body">
{% for post in posts reversed %}
<h3 class="title mb-1"><a style = "text-decoration:none;" href="{% url 'post' post.title|slugify %}">{{post.title}}</a></h3>
<div class="meta mb-1"><span class="date">{{post.created_at}}</span></div>
<div class="intro">{{post.body|truncatewords:30}}</div>
<a class="more-link" href="{% url 'post' post.title|slugify %}">Read more →</a>
{% endfor %}
posts.html file :
{% block content %}
<section class="blog-list px-3 py-5 p-md-5">
<div class="container">
<div class="item mb-5">
<div class="media">
<div class="media-body">
<h1 class="title mb-1"><a style = "text-decoration:none;">{{posts.title}}</a></h1>
<div class="meta mb-1"><span class="date">{{posts.body}}</span></div>
<div class="intro">{{posts.created_at}}</div>
</div><!--//media-body-->
</div><!--//media-->
</div><!--//item-->
</div>
</section>
{% endblock %}
The slugify filter converts the text to lowercase. If the title is “The Title”, then the slugified version is “the-title”. Taking out the hyphen leaves “the title”, which does not match “The Title”. You may want to use a case-insensitive search in your filter.
Thanks for the reply. Can you give an example of a case-insensitive search?
Hi Ken
I did some research on the above mentioned issue without any luck.As far as I am understanding when the visitor click any blog post title from the home page it triggers the post method in views.py file and load that blog post from posts.html file dynamically. In my case here is whats happening :
page URL : www.yourdomain.com/title-of-blog
Page Content : Blank
The page URL format is okay but its not loading any page content. Any clue ?
Thanks
Did you change your post
method as recommended earlier? If so, what does your new post
method look like?
Hi Ken
Here is the new post method :
def post(request, pk):
posts = Post.objects.all()
return render(request, 'posts.html', {'posts': posts})
Since you are now passing a queryset into the template instead of an individual object, did you change your template to account for that? (Actually, I missed that the first time - you were passing a queryset in then too - you had a filter
and not a get
.) When passing in a queryset, you need to iterate over the queryset to render the individual objects.
If my post method is like this :
def post(request, pk):
posts = Post.objects.get(id=pk)
return render(request, 'posts.html', {'posts': posts})
Individual blog page looks like this where the number changes for each post in the URL :
page URL : www.yourdomain.com/1
Page Content : individual blog posts are loading ( i.e: title, body and created date )
However if the post method is like this :
def post(request, pk):
posts = Post.objects.all()
return render(request, 'posts.html', {'posts': posts})
Individual blog page looks like this where the title changed accordingly :
page URL : www.yourdomain.com/blog-post-title
Page Content : nothing loading
I never made any changes in the posts.html template file. Here is the posts.html file :
{% block content %}
<section class="blog-list px-3 py-5 p-md-5">
<div class="container">
<div class="item mb-5">
<div class="media">
<!--img class="mr-3 img-fluid post-thumb d-none d-md-flex" src="{% static '/images/blog/blog-post-thumb-9.jpg' %}" alt="image"-->
<div class="media-body">
<h1 class="title mb-1"><a style = "text-decoration:none;">{{posts.title}}</a></h1>
<div class="meta mb-1"><span class="date">{{posts.created_at}}</span></div>
<div class="intro">{{posts.body}}</div>
</div><!--//media-body-->
</div><!--//media-->
</div><!--//item-->
</div>
</section>
{% endblock %}
Correct, that’s my point.
In your first example, you’re passing in a single object, and so it renders correctly.
In your second example, you’re passing a list of objects. You then need to iterate over the list in your template to retrieve each individual object from that list.
1 Like