Django, problem with the comment form below the post - python

I just can't figure it out for a very long time, I made a conclusion of comments to posts from the admin panel. But I just can't figure out how to make a comment form right under the post for users to comment. Thanks to all!
models.py
class Post(models.Model):
photo = models.ImageField(upload_to='media/photos/',null=True, blank=True)
name_barber = models.CharField(max_length=30)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.description[:10]
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
name = models.CharField(max_length=30)
body = models.TextField(null=True)
add_date = models.DateTimeField(auto_now_add=True)
enter code here
def __str__(self):
return '%s - %s' % (self.post, self.name)
form.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('name', 'body')
views.py
class HomePage(ListView):
model = Post
template_name = 'main/index.html'
context_object_name = 'posts1'
class BarbersPage(ListView):
model = Post
template_name = 'main/barbers.html'
context_object_name = 'posts'
urls.py
urlpatterns = [
path('',views.HomePage.as_view(),name='index'),
path('barbers/',views.BarbersPage.as_view(), name='barbers'),
]
barbers.html
{% for post in posts %}
<img src="{{MEDIA_URL}}{{post.photo.url}}" width="800" />
<h3>
{{ post.name_barber}}
</h3>
<p>{{ post.description}}</p>
<h3> Comments.. </h3>
{% if not post.comments.all %}
no comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.add_date }}
</strong>
<p>{{comment.body }}</p>
<br>
{% endfor %}
{% endif %}
{% endfor %}

You will need to add a form block below the post for users to add a comment.
Something like this:
{% for post in posts %}
<img src="{{MEDIA_URL}}{{post.photo.url}}" width="800" />
<h3>
{{ post.name_barber}}
</h3>
<p>{{ post.description}}</p>
<h3> Comments.. </h3>
{% if not post.comments.all %}
no comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.add_date }}
</strong>
<p>{{comment.body }}</p>
<br>
{% endfor %}
{% endif %}
Add Comment:<br/>
<form method="post" action="/AddComment">
<input type="hidden" id="postid" value="{{post.id}}"/>
<input type="text" id="newcomment" size="50"/><input type="submit" value="Submit"/>
</form><br/>
{% endfor %}
You will need to decide where to submit the comment data and update the action attribute in the form.

Related

How do i make my categories function correctly?

so im trying to seperate my blog posts into different categories but right now it all just appears as my username
blogcategory.html
{% extends "base.html" %}
{% block page_content %}
<div class="col-md-8 offset-md-2">
<h1>{{ category | title }}</h1>
<hr>
{% for post in posts %}
<h2>{{ post.title }}</h2>
<small>
{{ post.created_on.date }} |
Categories:
{% for category in post.categories.all %}
<a href="{% url 'blogcategory' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</small>
<p>{{ post.body | slice:":400" }}...</p>
{% endfor %}
</div>
{% endblock %}
blogdetail.html
{% extends "base.html" %}
{% block page_content %}
<div class="col-md-8 offset-md-2">
<h1>{{ post.title }}</h1>
<small>
{{ post.created_on.date }} |
Categories:
{% for category in post.categories.all %}
<a href="{% url 'blogcategory' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</small>
<p>{{ post.body | linebreaks }}</p>
<h3>Leave a comment:</h3>
<form action="/blog/{{ post.pk }}/" method="post">
{% csrf_token %}
<div class="form-group">
{{ user.username|default:'Guest' }}
</div>
<div class="form-group">
{{ form.body }}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<h3>Comments:</h3>
{% for comment in comments %}
<p>
On {{comment.created_on.date }}
<b>{{ user.username|default:'Guest'}}</b> wrote:
</p>
<p>{{ comment.body }}</p>
<hr>
{% endfor %}
</div>
{% endblock %}
blogindex
{% extends "base.html" %}
{% block page_content %}
<div class="col-md-8 offset-md-2">
<h1>Blog Index</h1>
<hr>
{% for post in posts %}
<h2>{{ post.title }}</h2>
<small>
{{ post.created_on.date }} |
Categories:
{% for category in post.categories.all %}
<a href="{% url 'blogcategory' category.name %}">
{{ category.name }}
</a> blo
{% endfor %}
</small>
<p>{{ post.body | slice:":400" }}...</p>
{% endfor %}
</div>
{% endblock %}
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=20)
class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField("Category", related_name="posts")
class Comment(models.Model):
author = models.CharField(max_length=180)
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey("Post", on_delete=models.CASCADE)
views.py
from django.shortcuts import render
from .forms import CommentForm
from .models import Post, Comment
def blogindex(request):
posts = Post.objects.all().order_by("-created_on")
context = {"posts": posts}
return render(request, "blogindex.html", context)
def blogcategory(request, category):
posts = Post.objects.filter(
categories__name__contains=category
).order_by(
'-created_on'
)
context = {
"category": category,
"posts": posts
}
return render(request, "blog_category.html", context)
def blogdetail(request, pk):
post = Post.objects.get(pk=pk)
comments = Comment.objects.filter(post=post)
form = CommentForm()
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = Comment(
author=form.cleaned_data["author"],
body=form.cleaned_data["body"],
post=post,
)
comment.save()
context = {"post": post, "comments": comments, "form": form}
return render(request, "blogdetail.html", context)
realistically i should be able to make post be of certain categories and click on those categories when i see them. But for some reason, the categories default to the username aof the person who made it and cant be changed. Please help.

Django template cannot see model object

models.py
from django.db import models
from django.urls import reverse
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=256)
author = models.CharField(max_length=256)
coverphoto_link = models.CharField(max_length=1000, blank=True)
text = models.TextField()
photo_link = models.CharField(max_length=1000,blank=True)
date = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return reverse("basic_app:article", kwargs = {'pk':self.pk})
class Comment(models.Model):
post = models.ForeignKey(Post,related_name='comments', on_delete = models.CASCADE)
name = models.CharField(max_length=300)
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
article.html
{% include 'base1.html' %}
{% load static %}
<br>
<div class="container" id='container_article'>
<div class="container2">
<h1>{{ article_detail.title }}</h1>
<p class="author_detail" style="color: rgb(0, 4, 255);">{{ article_detail.author }} | {{article_detail.date }}</p>
<br>
<img id="photo" src="{{ article_detail.photo_link }}">
</div>
<p id="articletext">{{ article_detail.text }}</p>
<br>
<br>
<hr>
<!--- HERE --->
<h2>Comments...</h2>
{% if not post.comments.all %}
No comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong> {{ comment.name }} - {{ comment.date_added }}</strong>
<br>
{{ comment.body }}
<br>
{% endfor %}
<hr>
{% endif %}
</div>
{% include 'footer.html' %}
THe main problem is that I created comments at the admin secction, all good, but the page is still displaying "No comments yet...".See the <!--- HERE ---> part, there is the problem.I also registered the app and the model at admin.py.
I would ty this instead:
{% for comment in post.comments.all %}
<strong> {{ comment.name }} - {{ comment.date_added }}</strong>
<br>
{{ comment.body }}
<br>
{% empty %}
No comments yet...Add one
{% endfor %}
I don't think this is correct:
{% if not post.comments.all %}

Not being able to display comments in template

I'm making a Post and Comment model by taking reference from internet. i created and Post and Comment model and it looks ok in django admin panel. i can add post and also a comment to any particular post. but getting trouble when I'm trying to display the comment under the post in templates(under post detail views). PLEASE HELP
models.py
class Post(models.Model):
author = models.ForeignKey(User,on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = RichTextField()
tags = models.CharField(max_length=50,blank=True,null=True)
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail',kwargs={'pk':self.pk})
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE)
author = models.ForeignKey(User,max_length=50,on_delete=models.CASCADE)
text = models.TextField()
create_date = models.DateTimeField(default=timezone.now)
def get_absolute_url(self):
return reverse('discuss')
views.py
class PostDetailView(DetailView):
model = Post
def add_comment_to_post(request,pk):
return get_object_or_404(Post,pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post= post
comment.save()
return redirect('post-detail',pk=post.pk)
else:
form = CommentForm()
return render(request, 'discuss/comment_form.html',{'form':form})
def comment_remove(request,pk):
comment = get_object_or_404(Comment,pk=pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post-detail', pk=post_pk)
post_detail.html
{% extends 'index.html' %}
{% block content %}
<article class="media content-section">
<div class="medaia-body">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}" alt="image not found">
<div class="article-metedata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{object.author}}</a>
<small class="text-muted">{{ object.date_posted|date:"F d, Y"}}</small>
</div>
<h2 class="article-title">{{ object.title }}</h2>
<img class="query-img" src="{{ object.image.url }}" alt="image not found">
<p class="article-content">{{ object.content|safe }}</p>
</div>
</article>
{% if object.author == user %}
<div class="post-update-delete">
<button class="btn btn-outline-primary">Edit Post</button>
<button class="btn btn-outline-primary">Delete Post</button>
</div>
{% endif %}
<hr>
<a class="btn btn-primary btn-comment" href="{% url 'add_comment_to_post' pk=post.pk %}">Add Comment</a>
<!-- ############################### ABOVE CODE IS WORKING ############################# -->
<!-- ########################## GETTING PROBLEM IN BELLOW CODE ######################### -->
{% for comment in object.comments.all %}
{% if user.is_authenticated %}
{{ comment.create_date }}
{{ comment.text|safe|linebreaks }}
{{ comment.author }}
{% endif %}
{% empty %}
<p>No Comment</p>
{% endfor %}
{% endblock %}
in post_deatil.html i also tried {% for comment in post.comments.all %} but it is also not working
Since you did not specify a related_name=… parameter [Django-doc], the related_name is by default comment_set, so you iterate over the comments with:
{% for comment in object.comment_set.all %}
…
{% endfor %}
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

How to limit the number of items displayed in Django app

I have this Django model in my newspaper app:
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
It currently displays all articles but I want to limit what is displayed to the 3 most recent articles. How is that done?
This is my view:
class ArticleListView(LoginRequiredMixin, ListView):
model = Article
template_name = 'article_list.html'
login_url = 'login'
This is the html template:
{% extends 'base.html' %}
{% block title %}Articles{% endblock title %}
{% block content %}
{% for article in object_list %}
<div class="card">
<div class="card-header">
<span class="font-weight-bold">{{ article.title }}</span> ·
<span class="text-muted">by {{ article.author }} | {{ article.date }}</span>
</div>
<div class="card-body">
<p>{{ article.body }}</p>
Edit
Delete
</div>
<div class="card-footer">
{% for comment in article.comments.all %}
<p>
<span class="font-weight-bold">{{ comment.author }} ·</span>
{{ comment }}
</p>
{% endfor %}
</div>
</div>
<br />
{% endfor %}
{% endblock content %}
In your (assumed) ListView you should define the queryset, something like
class ArticleListView(LoginRequiredMixin, ListView):
model = Article
template_name = 'article_list.html'
login_url = 'login'
queryset = Article.objects.order_by('-date')[:3]
More on this here.

How to apply upvote functionality with corresponding Model in Template?

I am developing a quora like app in Django but facing two problem. I want, in Question DetailView if user have not upvoted the answer then it will show the option of upvote and the total vote.
Here is my html template.
{% extends 'base.html' %}
{% block title %} {{ question.title }} {% endblock %}
{% block body %}
<h3><i>{{ question.title }}</i></h3>
{{ question.description }}
{% for answer in question.answer_set.all %}
<br>
<div>
<p>{{ answer.answer_text }} <span style="font-size: 15px">by [{{ answer.user }}]</span></p>
<form method="post" action="{% url 'answer:detail' question.id %}">
{% csrf_token %}
<input type="hidden" name="type" value="vote">
<input type="hidden" name="answer_id" value="{{ answer.id }}">
{% for upvote in answer.upvote_set.all %}
{% if upvote.user == request.user %}
<input type="submit" class="btn btn-sm btn-warning"
value="Downvote|{{ answer.upvote_set.all.count }}">
{% else %}
{% if forloop.counter == 1 %}
<input type="submit" class="btn btn-success" value="Upvote|{{ answer.upvote_set.all.count }}">
{% endif %}
{% endif %}
{% empty %}
<input type="submit" class="btn btn-sm btn-success" value="Upvote|{{ 0 }}">
{% endfor %}
</form>
{% endfor %}
{% endblock %}
models.py
from django.contrib.auth.models import User
from django.db import models
from django.shortcuts import reverse
# Create your models here.
class Question(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=200, blank=True, null=True)
description = models.TextField()
pub_date = models.DateTimeField()
def __str__(self):
return self.title
class Answer(models.Model):
answer_text = models.TextField()
questions = models.ForeignKey(Question)
pub_date = models.DateTimeField(auto_now_add=True)
# upvote = models.IntegerField(null=True, blank=True)
user = models.ForeignKey(User)
def __str__(self):
return self.answer_text
def get_absolute_url(self):
return reverse('answer:answer_by_me', kwargs={'pk': self.user.id})
class Upvote(models.Model):
user = models.ForeignKey(User)
answers = models.ForeignKey(Answer)
def __str__(self):
return self.user.username
It's showing both upvote and downvote button if user and any other user voted already.
I can't use break keyword if user's vote found in the answer.upvote_set.all even I can't use membership operator like if request.user in answer.upvote_set.all because it returns upvote object queryset. How should i solve this?
You have to create a custom tag for that.
Create a file in templatetags folder of your app named upvote_tags.py.
from django import template
register = template.Library()
#register.simple_tag
def has_upvoted(user, answer):
return user.id in list(answer.upvote_set.all().values_list("user", flat=True))
Now in your template you can use it like.
# load tag at top of your html.
{% load upvote_tags %}
...
# remove your loop and use condition as below
{% if has_upvoted request.user answer %}
# show downvote button for this answer
{% else %}
# show upvote button for this answer
{% endif %}
You also have to make entry of your tag file in TEMPLATE list under libraries keyword in your settings.py.
TEMPLATES = [
{
...
'OPTIONS': {
'libraries':{
# make your file entry here.
'upvote_tags': 'app_name.templatetags.upvote_tags',
}
},
},
]

Categories

Resources