codingunicorn
codingunicorn

Reputation: 1

Django Comments Newbie

I started learning Django about a month ago and just finished Django for Beginners by William Vincent. The book ends with Ch.15: Comments and shows how the admin can add comments to posts.

Q: Can someone, please, show me or point me in the right direction as to how I can let registered users also add comments to posts? Is there perhaps a 3rd party app for that?

What I have so far:

Models:

class Article(models.Model):
title  = models.CharField(max_length=255)
body   = models.TextField()
date   = models.DateTimeField(auto_now_add=True)
image  = models.ImageField(upload_to='images/', null=True, blank=True, height_field=None, width_field=None)
upload = models.FileField(upload_to='files/', null=True, blank=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)])

class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comment')
comment = models.CharField(max_length=140)
date    = models.DateTimeField(auto_now_add=True)
author  = models.ForeignKey(
    get_user_model(), on_delete=models.CASCADE,
)

def __str__(self):
    return self.comment

def get_absolute_url(self):
    return reverse('article_list')

forms.py

class PostForm(forms.ModelForm):
class Meta:
    model = Article
    fields = ('title', 'body', 'image', 'upload')

class CommentForm(forms.ModelForm):
class Meta:
    model  = Comment
    fields = ('comment', 'author')

Views:

class ArticleListView(LoginRequiredMixin, ListView):
model         = Article
template_name = 'article_list.html'
comment_form  = CommentForm
login_url     = 'login'

class ArticleDetailView(LoginRequiredMixin, DetailView):
model         = Article
template_name = 'article_detail.html'
login_url     = 'login'

class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model         = Article
fields        = ('title', 'body', 'image', 'upload')
template_name = 'article_edit.html'
login_url     = 'login'

def dispatch(self, request, *args, **kwargs):
    obj = self.get_object()
    if obj.author != self.request.user:
        raise PermissionDenied
    return super().dispatch (request, *args, **kwargs)

class ArticleDeleteView(LoginRequiredMixin, DeleteView):
model         = Article
template_name = 'article_delete.html'
success_url   = reverse_lazy('article_list')
login_url     = 'login'

def dispatch(self, request, *args, **kwargs):
    obj = self.get_object()
    if obj.author != self.request.user:
        raise PermissionDenied
    return super().dispatch (request, *args, **kwargs)

class ArticleCreateView(LoginRequiredMixin, CreateView):
model         = Article
form_class    = PostForm
template_name = 'article_new.html'
login_url     = 'login'

def form_valid(self, form):
    form.instance.author = self.request.user
    return super().form_valid(form)

URLs:

urlpatterns = [
path('<int:pk>/edit/', ArticleUpdateView.as_view(), name='article_edit'),
path('<int:pk>/', ArticleDetailView.as_view(), name='article_detail'),
path('<int:pk>/delete/', ArticleDeleteView.as_view(), name='article_delete'),
path('', ArticleListView.as_view(), name='article_list'),
path('new/', ArticleCreateView.as_view(), name='article_new'),]

Thank you for your attention.

Upvotes: 0

Views: 83

Answers (1)

codingunicorn
codingunicorn

Reputation: 1

Solved. In my views.py I added the following function:

def add_comment(request, pk):
article = get_object_or_404(Article, pk=pk)
if request.method == "POST":
    form = CommentForm(request.POST)
    if form.is_valid():
        comment = form.save(commit=False)
        comment.article = article
        comment.save()
        return redirect('article_detail', pk=article.pk)
else:
    form = CommentForm()
return render(request, 'add_comment.html', {'form': form})

Then the following .html file was added to templates:

add_comment.html

{% extends 'base.html' %}
{% block content %}
<h4>Add a Comment</h4>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.as_p }}</p>
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock content %}

P.S.: Initially I was getting an ImportError: cannot import name 'add_comment' from 'articles.views'. I thought it was a circular import problem and what worked for me was just getting the def add_comment indentation right.

Upvotes: 0

Related Questions