William
William

Reputation: 4036

Django submit form failed tracebacks: didn't return an HttpResponse object

I'm coding a new website.Now I'm coding the news_detail.html.There is a comment function in this page for people to comment to the news.

But I can't submit the comment successfully.

The tracebacks says:

Exception Type: ValueError at /news-11
Exception Value: The view news.views.NewsDetailView didn't return an HttpResponse object. It returned None instead.

Here is my NewsComment model:

class NewsComments(models.Model):
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name=u"用户")
    news = models.ForeignKey(News, on_delete=models.CASCADE, verbose_name=u"新闻")
    comments = models.CharField(max_length=200, verbose_name=u"评论")
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.SET_NULL)
    add_time = models.DateTimeField(auto_now_add=True, verbose_name='发时')
    last_updated_time = models.DateTimeField(auto_now=True, verbose_name='更时')
    is_delete = models.BooleanField(default=False, verbose_name='删否')

    class Meta:
        verbose_name = "新闻评论"
        verbose_name_plural = verbose_name
        ordering = ['-add_time']

    def __str__(self):
        return self.comments

Here is my news/urls.py:

 path('-<int:news_pk>', NewsDetailView.as_view(), name="news_detail"),

Here is the news/views.py:

class NewsDetailView(View):

   def get(self, request, news_pk):
    news = News.objects.get(id=int(news_pk))
    title = news.title
    author = news.author_name
    add_time = news.add_time
    content = news.content
    category = news.category
    tags = news.tag.annotate(news_count=Count('news'))
    all_comments = NewsComments.objects.filter(news=news)

    return render(request, 'news_detail.html',
                  {
                      'title': title,
                      'author': author,
                      'add_time': add_time,
                      'content': content,
                      'tags': tags,
                      'category': category,
                      'all_comments': all_comments
                  })

   def post(self, request, news_pk):
    comment_form = CommentForm(request.POST)
    if comment_form.is_valid():
        comments = comment_form.cleaned_data.get("comment")
        comment = NewsComments(user=request.user,comments=comments,news=News.objects.get(id=news_pk))
        comment.save()
        comment_form = CommentForm

        return render(request, "news_detail.html",
                      {
                          'comment_form': comment_form

                      })

Here is the CommentForm:

def words_validator(comment):
    if len(comment) < 5:
        raise ValidationError("您输入的评论字数太短,请重新输入至少5个字符")


class CommentForm(forms.Form):
    comment = forms.CharField(widget=forms.Textarea(), validators=[words_validator])

And here is my news_detail.html:

                     <form method="post" action="">
                    <div class="form-group">
                        <label for="exampleFormControlTextarea1"><h5>评论 <i class="fa fa-comments"></i></h5></label>
                        <textarea id="js-pl-textarea" class="form-control" rows="4"
                                  placeholder="我就想说..."></textarea>
                        <div class="text-center mt-3">
                            <button type="submit" id='js-pl-submit' class="btn btn-danger comment-submit-button">
                                发表评论
                            </button>
                        </div>
                    </div>
                    {% csrf_token %}
                </form>

Acturaly after I add some comments in admin,I can render the comments in the html successfully.But when I try to submit the form and save the comments in database it always fails.

Upvotes: 0

Views: 50

Answers (1)

Lemayzeur
Lemayzeur

Reputation: 8525

Two options:

1) Send the argument needed through context, useful for form action url

''' codes '''
def get(self, request, news_pk):
    news = News.objects.get(id=int(news_pk))
    ''' codes '''

    return render(request, 'news_detail.html',{
           #codes
           'title': title,
           'news_pk': news_pk})

HTML

<form method="post" action="{% url 'news_detail' news_pk %}">{% csrf_token %}
     <div class="form-group"></ div>
</form>

2) No need to set the url because the template news_detail.html is both the template html that your views rendering, and the view receving the post request.

<form method="post" action="">{% csrf_token %} <!-- Make sure to keep action blank -->
     <div class="form-group"></ div>
</form>

EDIT:

consider to redefine your views like this

Note changes, the function name starts by a lower letter

views.py

def newsDetailView(request,news_pk):

    news = News.objects.get(id=news_pk)
    title = news.title
    author = news.author_name
    add_time = news.add_time
    content = news.content
    category = news.category
    tags = news.tag.annotate(news_count=Count('news'))

    all_comments = NewsComments.objects.filter(news=news)

    comment_form = CommentForm(request.POST or None)
    if request.method == 'POST' and comment_form.is_valid():
        comments = comment_form.cleaned_data.get("comment")
        comment = NewsComments(user=request.user,comments=comments,news=news)
        comment.save()

    return render(request,"news_detail.html",{
                  'title': title,
                  'author': author,
                  'add_time': add_time,
                  'content': content,
                  'tags': tags,
                  'category': category,
                  'all_comments': all_comments
                  'comment_form': comment_form
              })

urls.py

Note changes, call the function the lower letter, and remove .as_view()

path('-<int:news_pk>', newsDetailView, name="news_detail"),

Upvotes: 1

Related Questions