I am trying to make it so when I view a blog from any particular link on my website, the url displays www.example.com/view-blog/slug. I have got it working for my images and image title. But I cannot get it to work with blog titles.
It keeps returning the error:
Reverse for 'viewblog' with arguments '('',)' not found. 1 pattern(s) tried: ['view\-blog/(?P[-a-zA-Z0-9_] )/\Z'].
Models.py
class BlogPost(models.Model):
blog_title = models.CharField(max_length=100, null=False, blank=False, default="")
slug = models.SlugField()
blog_article = RichTextUploadingField(null=True, blank=True, default="ici")
blog_image = models.ImageField(null=True, blank=True, upload_to="images", default="default.png")
blog_date = models.DateField(auto_now_add=True)
blog_published = models.BooleanField(default=False)
blog_featured = models.BooleanField(default=False)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.blog_title)
super().save(*args, **kwargs)
def __str__(self):
return self.blog_title
Views.py EDIT: ADDED ALL VIEWS.
def blogPage(request):
posts = BlogPost.objects.filter(blog_date__lte=timezone.now()).order_by('-blog_date')[:4]
context = {'posts': posts}
return render(request, 'blog.html', context)
def blogsPage(request):
posts = BlogPost.objects.filter(blog_date__lte=timezone.now()).order_by('-blog_date')
context = {'posts': posts}
return render(request, 'blogs.html', context)
def searchBlogs(request):
if request.method == "POST":
searched = request.POST.get('searched', False);
searched_blogs = BlogPost.objects.filter(blog_title__icontains=searched)
return render(request, 'search-blogs.html', {'searched': searched, 'searched_blogs': searched_blogs})
def viewBlog(request, slug):
try:
blog = BlogPost.objects.get(slug=slug)
except BlogPost.DoesNotExist:
print("ViewBlog with this slug does not exist")
blog = None
return render(request, 'view-blog.html', {'blog': blog, 'slug': slug})
Urls.py
urlpatterns = [
path('', views.galleryPage, name='gallery'),
path('gallery/', views.galleryPage, name='gallery'),
path('contact/', views.contactPage, name='contact'),
path('blog/', views.blogPage, name='blog'),
path('blogs/', views.blogsPage, name='blogs'),
path('search-blogs/', views.searchBlogs, name='searchblogs'),
path('view-image/<slug:slug>/', views.viewImage, name='viewimage'),
path('view-blog/<slug:slug>/', views.viewBlog, name='viewblog'),
path('thank-you/', views.thankyouPage, name='thankyou'),
path('about-me/', views.aboutmePage, name='aboutme'),
]
**One of my templates I wish to link to viewblog page from ** ( I have tried to replace .id on my urls with .slug but this is what gives me the error.
<body>
<header>{% include 'navbardesktop.html' %}</header>
<div >
<h1 id="all-blog-title" style="text-align: center;">All Blogs</h1>
<br>
<div >
<form method="POST" action="{% url 'searchblogs' %}">
{% csrf_token %}
<i ></i>
<input type="text" placeholder="Search keyword" name="searched">
<button id="search-btn" >Search</button>
</form>
</div>
<br>
<hr id="blog-hr" style="width:50%; margin-left:25% !important; margin-right:25% !important;" />
<div >
<div >
<button type="button" data-bs-toggle="dropdown" aria-expanded="false">
Blog List
</button>
<ul style="background-color: #d6d6d6 ;">
{% for post in posts %} {% if post.blog_published is True %}
<li><a href="{% url 'viewblog' post.id %}">{{post.blog_title}}</a></li>
{% endif %}
{% endfor %}
</ul>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL jjXkk Q2h455rYXK/7HAuoJl 0I4" crossorigin="anonymous"></script>
</div>
<div >
{% for post in posts %} {% if post.blog_published is True %}
<div id="blog-col">
<div >
<div >
<img src="{{post.blog_image.url}}"alt="My image"/>
<h2 >{{post.blog_title}}</h2>
<hr id="blog-hr" style="width: 90%" />
<article >
<p>{{post.blog_article|truncatechars_html:265|safe}}</p>
</article>
<a href="{% url 'viewblog' post.slug %}"type="button">Read More...</a>
<p >Posted on: {{post.blog_date}}</p>
</div>
</div>
</div>
{% endif %} {% empty %}
<h3>No Blog Uploads</h3>
{% endfor %}
</div>
</div>
</div>
</div>
CodePudding user response:
the error message
Reverse for 'viewblog' with arguments '('',)' not found.
Remark: what is '('',)' ??
it is simply the print of a python list () with one empty argument ('',). The comma just indicates it is a list. This is placed in '' to structure the error message text '('',)'
so this is the list of arguments that is extracted from your {% url .... %} statement for the error message
always means you have and url tag pointing to "viewblog" that requires an argument (because definded like that in urlpatterns in urls.py ) but actually one of them is null or "" (which is not accepted to reverse a valid url):
urlpatterns = [
...
path('view-blog/<slug:slug>/', views.viewBlog, name='viewblog'),
...
]
---------------------------------
href="{% url 'viewblog' post.id %}"
Now in your case you had originally post.id as parameter (I understood you changed that to post.slug). That means one of the post database entries has a post.slug that is null or ""
to debug just print the value of post.slug into the html page and you will see what is wrong. the "xxx" and "yyy" are there to mark on the output clearly where some content shoult appear (because without it is more difficult to see if there is an empty output).
{% for post in posts %}
xxx {{ post.slug }} xxx <br>
yyy {{ post.blog_title }} xxx <br>
{% endfor %}
Another way of checking post.slug is to go to the admin page ouf your app and inspect the database entries directly
And a third one would be to print the query result for posts in the view:
def blogsPage(request):
posts = BlogPost.objects.filter(blog_date__lte=timezone.now()).order_by('-blog_date')
context = {'posts': posts}
for post in posts:
print(post)
return render(request, 'blogs.html', context)
which will show the content of posts in the console