1

I have a problem when I was creating the comment form with django. After I wrote my view.py, models.py and html, I got an ValueError that said:

Cannot assign "<class 'blog.models.post'>": "Comment.post" must be a "post" instance". 

Below are my codes.

HTML

{% block content %}
<h1>Add New Comment:</h1>
<form method='POST' action=''>
    {% csrf_token %}
    {{ form.as_p }}
<button type='submit'>Submit</button>
</form>
{% endblock %}

views.py

def add_comment(request, slug):
    po = get_object_or_404(post, slug=slug)
    if request.method == 'POST':
        form = CommentForm(request.POST or None)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = post
            comment.save()
            return redirect('blog:post', slug=post.slug)
    else:
        form = CommentForm()
    return render(request, 'blog/post/add_comment.html', {'form': form})

models.py

class Comment(models.Model):
    post = models.ForeignKey(post, related_name='comments', on_delete=models.CASCADE)
    user = models.CharField(max_length=250)
    email = models.EmailField() 
    body = models.TextField() 
    created = models.DateTimeField(auto_now_add=True) 
    approved = models.BooleanField(default=False) 

    def approved(self):
        self.approved = True
        self.save()

    def __str__(self):
        return self.user
Alasdair
  • 298,606
  • 55
  • 578
  • 516
Ann
  • 11
  • 1
  • Your method `approved` clashes with the field. Rename so it doesn't clash, for example to `def approve(self):`. – Alasdair Mar 19 '19 at 12:44

2 Answers2

1

The post you fetched from the database is po:

po = get_object_or_404(post, slug=slug)

Therefore you should set form.post = po:

def add_comment(request, slug):
    po = get_object_or_404(post, slug=slug)
    if request.method == 'POST':
        form = CommentForm(request.POST or None)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = po
            comment.save()

Note that normally in Django you would use Post for your model and post for the instance you fetch from the database.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • after I changed 'post' to 'po'. But, I got another error 'NoReverseMatch' which said Reverse for 'post' not found. 'post' is not a valid view function or pattern name. – Ann Mar 19 '19 at 17:00
  • That's a separate issue. Make sure the URL pattern you want to redirect to has `name='post'`. [This question](https://stackoverflow.com/questions/38390177/what-is-a-noreversematch-error-and-how-do-i-fix-it) might help. If not, you need to show your URL patterns. – Alasdair Mar 19 '19 at 17:04
  • I tried to do it but didn't work. This is my URL pattern: url(r'^(?P[-\w]+)/comment/$', views.add_comment, name='add_comment') – Ann Mar 19 '19 at 17:39
  • That’s the URL where you add the comment. Either it’s the URL pattern that you’re trying to redirect to that has the issue, or you don’t have `app_name = 'blog'` in the `blog/urls.py`. – Alasdair Mar 19 '19 at 19:20
  • Now I get it. Thank you:)) – Ann Mar 19 '19 at 20:43
0

Try it:

class Comment(models.Model):
    post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)