Hi there, I am having trouble in debugging my code. In my website, I want to create a comments section where authenticated users can make comments, and everyone else can view the comments.
The current issue is that the viewing of comments is not available, even though authenticated users can submit comments (and I can see the comments in the admin page). I’m not able to point out exactly which part of my code is off. I had to manually test each portion and I figured that there is some issues in my views/urls/html template.
I appreciate if anyone can point me in the right direction!
# import django modules
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.http import HttpResponse
from django.urls import reverse
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
# import respective classes from files in ad
from .forms import CreateForm, CommentForm
from .models import Ads, Comment
from .owner import OwnerListView, OwnerDetailView, OwnerCreateView, OwnerUpdateView, OwnerDeleteView
class AdsListView(OwnerListView):
model = Ads
# By convention:
template_name = "ads/ads_list.html"
class AdsDetailView(OwnerDetailView):
model = Ads
template_name = "ads/ads_detail.html"
#not sure if this get request is ok?
def get(self, request, pk) :
context = Ads.objects.get(id=pk)
comments = Comment.objects.filter(text=context).order_by('-updated_at')
comment_form = CommentForm()
# want to show the detailed view of the ad details, comment header, and comment form
context = { 'ads' : context, 'comments': comments, 'comment_form': comment_form }
return render(request, self.template_name, context)
# Class for the ad creation
class AdsCreateView(OwnerCreateView):
model = Ads
# define the fields in the ad create view
fields = ['title', 'text', 'price', 'picture']
#add from pics
template_name = 'ads/ads_form.html'
success_url = reverse_lazy('ads:all')
def get(self, request, pk=None):
form = CreateForm()
context = {'form': form}
return render(request, self.template_name, context)
def post(self, request, pk=None):
form = CreateForm(request.POST, request.FILES or None)
if not form.is_valid():
context = {'form': form}
return render(request, self.template_name, context)
# Add owner to the model before saving
pic = form.save(commit=False)
pic.owner = self.request.user
pic.save()
return redirect(self.success_url)
class AdsUpdateView(OwnerUpdateView):
model = Ads
fields = ['title', 'text', 'price', 'picture']
#add from pics
template_name = 'ads/ads_form.html'
success_url = reverse_lazy('ads:all')
def get(self, request, pk):
pic = get_object_or_404(Ads, id=pk, owner=self.request.user)
form = CreateForm(instance=pic)
context = {'form': form}
return render(request, self.template_name, context)
def post(self, request, pk=None):
pic = get_object_or_404(Ads, id=pk, owner=self.request.user)
form = CreateForm(request.POST, request.FILES or None, instance=pic)
if not form.is_valid():
context = {'form': form}
return render(request, self.template_name, context)
pic = form.save(commit=False)
pic.save()
return redirect(self.success_url)
class AdsDeleteView(OwnerDeleteView):
model = Ads
def stream_file(request, pk):
pic = get_object_or_404(Ads, id=pk)
print(pic)
response = HttpResponse()
response['Content-Type'] = pic.content_type
response['Content-Length'] = len(pic.picture)
response.write(pic.picture)
return response
# comment related views
class CommentCreateView(LoginRequiredMixin, View):
def post(self, request, pk) :
f = get_object_or_404(Ads, id=pk)
# ads is the foreign key in Comment class under models.py
comment = Comment(text=request.POST['comment'], owner=request.user, ads=f)
print(comment.text)
comment.save()
return redirect(reverse('ads:ads_detail', args=[pk]))
class CommentDeleteView(OwnerDeleteView):
model = Comment
template_name = "ads/ads_comment_delete.html"
# https://stackoverflow.com/questions/26290415/deleteview-with-a-dynamic-success-url-dependent-on-id
def get_success_url(self):
ads = self.object.ads
return reverse('ads:ads_detail', args=[ads.id])
# import django module
from django.urls import path, reverse_lazy
# from current folder, import views
from . import views
# define app name
app_name='ads'
# define urlpatterns
urlpatterns = [
path('', views.AdsListView.as_view(), name='all'),
path('ads/<int:pk>', views.AdsDetailView.as_view(), name='ads_detail'),
path('ads_picture/<int:pk>', views.stream_file, name='ads_picture'),
path('ads/create',
views.AdsCreateView.as_view(success_url=reverse_lazy('ads:all')), name='ads_create'),
path('ads/<int:pk>/update',
views.AdsUpdateView.as_view(success_url=reverse_lazy('ads:all')), name='ads_update'),
path('ads/<int:pk>/delete',
views.AdsDeleteView.as_view(success_url=reverse_lazy('ads:all')), name='ads_delete'),
#path for comments. this has issue, need to fix it
path('comment/<int:pk>',
views.CommentCreateView.as_view(), name='ads_comment_create'),
path('comment/<int:pk>/delete',
views.CommentDeleteView.as_view(success_url=reverse_lazy('ads:all')), name='ads_comment_delete'),
]
my ads_details.html
{% extends "base_menu.html" %}
{% load humanize %} <!-- https://docs.djangoproject.com/en/3.0/ref/contrib/humanize -->
<!-- block head from pics-->
{% block head %}
<style>
.overlay{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
display: none;
background-color: rgba(0,0,0,0.5); /*dim the background*/
}
</style>
{% endblock %}
{% block content %}
<!--Show the ads update&delete if authenticated-->
{% if ads.owner == user %}
<span style="float: right;">
<!-- i class refers to icon, so update = pencil icon, delete = trash icon-->
<a href="{% url 'ads:ads_update' ads.id %}"><i class="fa fa-pencil"></i></a>
<a href="{% url 'ads:ads_delete' ads.id %}"><i class="fa fa-trash"></i></a>
</span>
{% endif %}
<!--want to show the title portion of the ads-->
<h1>{{ ads.title }}</h1>
<!-- this displays the image -->
{% if ads.content_type %}
<img style="float:right; max-width:50%;" src="{% url 'ads:ads_picture' ads.id %}"
onclick="document.getElementById('overlay').style.display = 'block';">
{% endif %}
<!--want to show the text portion of the ads-->
<p>
{{ ads.text }}
</p>
<!--show time of update - refer to humanize -->
<p>
({{ ads.updated_at|naturaltime }})
</p>
<!-- allow user to comment if they are logged in-->
{% if user.is_authenticated %}
<br clear="all"/>
<p>
{% load crispy_forms_tags %}
<form method="post" action="{% url 'ads:ads_comment_create' ads.id %}">
{% csrf_token %}
{{ comment_form|crispy }}
<input type="submit" value="Submit Comment" onclick="window.location.href='{% url 'ads:all' %}';return false;">
<input type="submit" value="All Ads" onclick="window.location.href='{% url 'ads:all' %}';return false;">
</form>
</p>
{% endif %}
<!-- show comments to everyone. there is an issue here, perhaps in naming?-->
{% for comment in comments %}
<p> {{ comment.text }}
({{ comment.updated_at|naturaltime }})
<!-- if user is comment owner, they can delete the comment -->
{% if user == comment.owner %}
<a href="{% url 'ads:ads_comment_delete' comment.id %}"><i class="fa fa-trash"></i></a>
{% endif %}
</p>
{% endfor %}
{% endblock %}
here are the files associated with this app.