This content originally appeared on DEV Community and was authored by Suman
Utilizing Bootstrap Accordion for adding comments in the UI
In post_view.html:
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
Comments : {{post.cmt_count}}
</a>
</p>
<div class="collapse" id="collapseExample">
{% for comment in post.comment_set.all %}
<div class="card card-body">
{{comment.content}}
</div>
{% endfor % }
</div>
<form method="POST">
{% csrf_token %}
<div class="col-md-8">
{{ c_form }}
</div>
<input type="submit" class="btn btn-secondary" value="Comment"/>
</form>
Create a model to link user and post to the comment :
class Comments(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
post = models.ForeignKey(UserPost,on_delete=models.CASCADE)
content = models.CharField(max_length=500)
def __str__(self):
return self.content
*Register your model to the admin site *
from django.contrib import admin
from .models import UserPost,Comments
admin.site.register(Comments)
*Make Migrations : *
python manage.py makemigrations
python manage.py migrate
In case you face operational error delere all migraions folder to restart your database
delete respectively :
db.sqlite3
in your app/migrations
delete all files except init
make migrations again, that’s it.
Go to the Django admin panel and add some data in them models
Reverse Relationship to get number of comments on a post :
class UserPost(models.Model):
title = models.CharField(max_length=150,null=False)
content = models.TextField()
author = models.ForeignKey(User,on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to=get_image_path )
class Meta:
ordering = ('-created_at',)
def cmnt_count(self):
return self.comments_set.all().count()
def __str__(self):
return self.title
views.py to render post:
from .forms import PostForm
def post_view(request,pk):
post = get_object_or_404(UserPost,id=pk)
context={
'post':post,
}
return render(request,'post_view.html',context)
Include the count as well as Comments on the UI using this reverse mapping
<p>Comments : {{post.cmt_count}}</p>
{% for comment in post.comment_set.all %}
<div class="card card-body">
{{comment.content}}
</div>
{% endfor % }
** Now to let users comment on the post :**
in app/forms.py
from .models import Comments
class CommentForm(forms.ModelForm):
content = forms.CharField(label="", widget=forms.TextInput(attrs={'placeholder': 'Write Your Thoughts on This Blog','class':'mt-2 focus:ring-1 focus:ring-blue-500'}))
class Meta:
model = Comments
fields = ['content']
in views.py
from .forms import PostForm,CommentForm
def post_view(request,pk):
post = get_object_or_404(UserPost,id=pk)
if request.method == "POST":
if not request.user.is_authenticated:
messages.warning(request, "Please log in to send a message.")
login_url = f"{redirect('new_login').url}?{urlencode({'next': request.path})}" # Preserve return URL
return redirect(login_url)
c_form = CommentForm(request.POST)
if c_form.is_valid():
instance = c_form.save(commit=False)
instance.user = request.user
instance.post = post
instance.save()
return redirect('post_view',pk=post.id)
else:
c_form = CommentForm()
context={
'post':post,
'c_form':c_form
}
return render(request,'post_view.html',context)
Render this form in the UI :
<form method="POST">
{% csrf_token %}
<div class="col-md-8">
{{ c_form }}
</div>
<input type="submit" class="btn btn-secondary" value="Comment"/>
</form>
That’s it, Happy Coding you all 🙂
This content originally appeared on DEV Community and was authored by Suman