I'm trying to add a like button to a blog post in Django, but I see this error every time I try to click in the like button. But if I opened the admin page then return to the site, it works properly, and I don't know why that is. Any help please?
The error I'm getting:
TypeError at /like/45 Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x000001BF06424F10>>
views code:
def LikeView(request,pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
post.likes.add(request.user)
models code:
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes= models.ManyToManyField(User,related_name='blog_post')
def total_likes(self):
return self.likes.count()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail',kwargs={'pk':self.pk})
urls:
urlpatterns = [
path('', PostListView.as_view(), name='blog-home'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('about/', views.About, name='blog-about'),
path('like/<int:pk>',LikeView,name='like_post'),
]
The button in the template:
<form action="{% url 'like_post' post.pk %}" , method="POST">
{% csrf_token %}
<button
type="submit"
,
name="post_id"
,
value="{{ post.id }}"
,
class="btn btn-primary btn-ms"
>
Like
</button>
Related
I'm having a huge issue on making for loop on django templates,for some reasone it dont show on the page the categories that i create on database
urls.py
app_name = 'statenews'
urlpatterns = [
path('', views.home, name="home"),
path('', views.category, name = 'category'),]
models.py
class Category(models.Model):
name = models.CharField(max_length=65)
...
class News(models.Model):
...
category = models.ForeignKey(
Category, on_delete=models.SET_NULL, null=True, blank=True,
default=None,
)
views.py
def category(request):
categories = Category.objects.all()
return render(request,'partials/footer.html',{
'categories': categories
})
html template
<div class="col-lg-3 col-md-6 mb-5">
<h4 class="font-weight-bold mb-4">Tags</h4>
{% for category in categories %}
<div class="d-flex flex-wrap m-n1">
({category.name})
</div>
{% endfor %}
</div>
You have two url paths with same url. Change it to:
urlpatterns = [
path('', views.home, name="home"),
path('categories', views.category, name = 'category')
]
Then enter via yourdomain.com/categories. Otherwise it will always show home view.
EDIT:
In you homepage you can simply see home view as it is set in url with ''. If you want to see categories as footer part, then you have to change your home template, render it with {% include 'partials/footer.html' %}. Then you have to pass categories in home view context.
I' wanted to try Django framework and i tried the blog app tutorial. i tried to add a comment feature. i know these questions have been asked several times but couldn't find a solution to my problem.
I got the following error:
No Post matches the given query.
Thanks for your help. Here are the Model and all:
urls.py :
path('', PostListView.as_view(), name='blog-home'),
path('user/<str:username>/', UserPostListView.as_view(), name='user-posts'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('post/<int:pk>/comment/', PostCommentView.as_view(), name='post-comment'),
path('about/', views.about, name='blog-about'),
]
models.py:
class Post(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE) # many to one relation use foreign key
def __str__(self):
return self.title
#property
def get_comments(self):
return self.comment_content.all()
# return the url as string
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comment(models.Model):
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, related_name='comment_content', on_delete=models.CASCADE)
def __str__(self):
return self.content
def get_absolute_url(self):
return reverse('comment-create', kwargs={'pk': self.pk})
forms.py:
class CommentForm(forms.ModelForm):
content=forms.Textarea()
class Meta:
model = Comment
fields=['content']
views.py:
class PostCommentView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['content']
template_name = 'blog/comment_form.html'
success_url = '/'
def form_valid(self, form):
post = get_object_or_404(Post, id=self.kwargs.get('id'))
print(post.id)
form.instance.author = self.request.user
form.instance.post = post
return super().form_valid(form)
comment_form.htlm:
{% extends "blog/base.html" %}
{% load crispy_forms_filters %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Comment tag</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post comment</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Abort the Comment? <a class="ml-2" href="{% url 'blog-home' %}">Back to Main Page</a>
</small>
</div>
</div>
{% endblock content %}
'id' is standard primary key of a Django Model but not of the POST that is created with ModelForm etc.
I suppose you need to put a hidden field "id" in your form to get it sent with the POST request.
Try print(self.kwargs.get('id')) before the 'get_object...' and you will see if 'id' has some content.
Here is the thing i'm trying to do:
There are few tv channels as image links and they will have some information inside channels.
I managed to create tv channels as a list, they look like a link but they don't work like link.
I've created slug area for each channel that takes from it's own name and generates slug auto. And with get_absolute_url i take it's url in the below code you'll see;
This is my model :
class Channels(models.Model):
name = models.CharField(max_length=50, null=False, blank=False, verbose_name="Tv Kanalı")
logo = models.ImageField(upload_to="channels/images/", verbose_name="Tv Logosu", blank=False)
slug = models.SlugField(null=True, unique=True, editable=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Channels, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('channel-list:campaigns', kwargs={'page_slug': self.slug})
This is my main urls:
urlpatterns = [
path('admin/', admin.site.urls),
url(r'', include(('tvekstra.apps.core.urls', 'home'), namespace='home')),
url(r'^user/', include(('tvekstra.apps.user.urls', 'login'), namespace='user')),
url(r'^channels/', include(('tvekstra.apps.tvchannels.urls', 'main'), namespace="channel-list")),
This is channels urls:
urlpatterns = [
url(r'', views.channel_list, name='channels'),
url(r'^(?P<page_slug>[-\w]+)/$', views.campaign_list, name='campaigns'),
]
This is my views:
def channel_list(request):
channels = Channels.objects.all()
return render(request, 'channel.list.html', {'channels': channels})
def campaign_list(request, page_slug):
channel = get_object_or_404(Channels, slug=page_slug)
return render(request, 'campaign.list.html', {'channel': channel})
And this is my template:
{% for channel in channels %}
<div class="col-3 text-center channels">
<a href="{{ channel.get_absolute_url }}">
<img src="{{ channel.get_image }}" alt="Channel Image" class="ch-img">
{{ channel.name }}
</a>
</div>
{% endfor %}
As you can see, a href is channel's getabsoluteurl method. It creates the html but it doesn't go forward page.
I think view is not working for some reason, requesting aid...
url(r'', matches '', but it also matches /channels/fox/ and /something-else/.
You can fix it by adding ^$ to the regex.
url(r'^$', views.channel_list, name='channels'),
In Django 2.0+, it would be better to use re_path, because url is deprecated in Django 3.1:
re_path(r'^$', views.channel_list, name='channels'),
And it would be simpler to use path:
path('', views.channel_list, name='channels'),
I am trying to redirect my page after submitting a like button to the same page but I keep getting a
NoReverseMatch at /score/like/2
Here is the urls
urlpatterns = [
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('', PostListView.as_view(), name='score'),
path('<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('like/<int:pk>', LikeView, name='like_post'),
Here is the views
def LikeView(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
post.likes.add(request.user)
return HttpResponseRedirect(reverse('post-detail', args=[str(pk)])) <-----Error highlighting here
here is the templates
<form action="{% url 'score:like_post' post.pk %}" method='POST'>
{% csrf_token %}
<button type='submit' name='post_id' class= "btn btn-primary btn-sm" value="{{post.id}}"> Like </button>
</form>
<strong>{{post.total_liked}} Likes </strong>
Given the template your urls.py specify an app_name. You need to use that as prefix in the name of the view.
Furthermore you can make use of redirect(…) [Django-doc] which calls reverse and wraps the result in a HttpResponseRedirect (so it removes some boilerplate):
from django.shortcuts import redirect
def LikeView(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
post.likes.add(request.user)
return redirect('score:post-detail', pk=pk)
I'm making a simple blog app with comments on a 'posts detail view' page, but I'm getting a 404 error saying "No comment found matching the query" whenever I try submitting my comment. Everything else in the app works except for the comments. I'm new to django and am making this site to learn, would appreciate any help!
Views.py
class PostDetailView(DetailView):
model = Post
fields = ['content']
class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['content']
template_name = 'blog/comment.html'
def form_valid(self, form):
post = self.get_object()
form.instance.author = self.request.user
return super().form_valid(form)
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ['-date_posted']
def __str__(self):
return f'Comment {self.content} by {self.author.username}'
def get_absolute_url(self):
return reverse('comment', kwargs={'pk': self.pk})
urls.py
from django.urls import path
from .views import (
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView,
UserPostListView,
CommentCreateView
)
from . import views
urlpatterns = [
path('', PostListView.as_view(), name='blog-home'),
path('post/comment/<int:pk>/', CommentCreateView.as_view(), name='create'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('about/', views.about, name='blog-about'),
]
comments.html This is the form. It's supposed to redirect to a different form to comment then back to post detail view
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Comment</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}