Submit button in template leading to HTTP ERROR 405

Submitted 4 years, 1 month ago
Ticket #8
Views 325
Language/Framework Django
Priority Low
Status Closed

I am adding a comment section for my posts, the issue is after submitting it leads to HTTP ERROR 405 This is the first time to receive this error, I have reviewed the views several times but I think the error might be from the views.py in post detail view

class PostDetailView(DetailView):
    model = Post
    template_name = "post_detail.html"

    def get_context_data(self, *args, **kwargs):
        context = super(PostDetailView, self).get_context_data()
        post = get_object_or_404(Post, slug=self.kwargs['slug'])
        comments = Comment.objects.filter(post=post).order_by('-id')
        total_likes = post.total_likes()
        liked = False
        if post.likes.filter(id=self.request.user.id).exists():
            liked = True

        if self.request.method == 'POST':
            comment_form = CommentForm(self.request.POST or None)
            if comment_form.is_valid():
                content = self.request.POST.get('content')
                comment = Comment.objects.create(
                    post=post, user=request.user, content=content)
                comment.save()
                return HttpResponseRedirect("post_detail.html")
        else:
            comment_form = CommentForm()

        context["total_likes"] = total_likes
        context["liked"] = liked
        context["comments"] = comments
        context["comment_form"] = comment_form
        return context

here is the template


            <div class="main-comment-section">
            {{comments.count}} Comment{{comments|pluralize}}
            {% for comment in comments %}
            <blockquote class="blockquote">
                <p class="mb-0"> {{ comment.content}}</p>
                <footer class="blockquote-footer">by<cite title="Source Title">{{comment.user| capfirst}}</cite></footer>
            </blockquote>
            {% endfor %}

here are the comments models.py

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField(max_length=160)
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '{}-{}'.format(self.post.title, str(self.user.username))
Submitted on May 25, 20
add a comment

2 Answers

Verified

where is the form submission? .. what is your initial analysis on this?

Submitted 4 years, 1 month ago

I have been trying to follow the logic of a function to be implemented in my classed view

- ahmed.hisham87 4 years, 1 month ago

if you still want to stick with this approach , lets add print statement here if self.request.method == 'POST': comment_form = CommentForm(self.request.POST or None) if comment_form.is_valid(): content = self.request.POST.get('content') comment = Comment.objects.create( post=post, user=request.user, content=content) comment.save() print('Its working') return HttpResponseRedirect("post_detail.html")

- Vengat 4 years, 1 month ago

any update on this?

- Vengat 4 years, 1 month ago

it did not print

- ahmed.hisham87 4 years, 1 month ago

Method Not Allowed (POST):

- ahmed.hisham87 4 years, 1 month ago

exactly as its DetailedView, its not allowing to POST, as i mentioned above, can you use different view for POST the comment

- Vengat 4 years, 1 month ago

how do you suggest to do it?

- ahmed.hisham87 4 years, 1 month ago

create another function based view & submit the comment over there and redirect to whatever the page you like to

- Vengat 4 years, 1 month ago

or try this ```def post(self, request, args, *kwargs): form = CommentForm(request.POST, request.FILES) if form.is_valid(): # Write Your Logic here

    self.object = self.get_object()
    context = context = super(Detail, self).get_context_data(**kwargs)
    context['form'] = CommentForm
    return self.render_to_response(context=context)

else:
    self.object = self.get_object()
    context = super(Detail, self).get_context_data(**kwargs)
    context['form'] = form
    return self.render_to_response( context=context)```
- Vengat 4 years, 1 month ago

if you still want to stick with DetailView itself then use above logic

- Vengat 4 years, 1 month ago

i hope this one fix your issue

- Vengat 4 years, 1 month ago

I am getting somewhere but I got Exception Value: post() got an unexpected keyword argument 'slug'

- ahmed.hisham87 4 years, 1 month ago

I am getting somewhere but I got Exception Value: post() got an unexpected keyword argument 'slug'

- ahmed.hisham87 4 years, 1 month ago

show me the code?

- Vengat 4 years, 1 month ago

I think this is right ``` def get_context_data(self, args, *kwargs): context = super(PostDetailView, self).get_context_data() post = get_object_or_404(Post, slug=self.kwargs['slug']) comments = Comment.objects.filter(post=post).order_by('-id') total_likes = post.total_likes() liked = False if post.likes.filter(id=self.request.user.id).exists(): liked = True

    if self.request.method == 'POST':
        comment_form = CommentForm(self.request.POST or None)
        if comment_form.is_valid():
            content = self.request.POST.get('content')
            comment = Comment.objects.create(
                post=post, user=self.request.user, content=content)
            comment.save()
            return HttpResponseRedirect("post_detail.html")
    else:
        comment_form = CommentForm()

    context["total_likes"] = total_likes
    context["liked"] = liked
    context["comments"] = comments
    context["comment_form"] = comment_form
    return context

def post(self, request, args, *kwargs):
    form = CommentForm(request.POST, request.FILES)
    if form.is_valid():  # Write Your Logic here
        self.object = self.get_object()
        context = context = super(
            PostDetailView, self).get_context_data(**kwargs)
        context['form'] = CommentForm
        return self.render_to_response(context=context)
    else:
        self.object = self.get_object()
        context = super(PostDetailView, self).get_context_data(**kwargs)
        context['form'] = form
        return self.render_to_response(context=context)

```

- ahmed.hisham87 4 years, 1 month ago

so you are able to render the detail view but not able to POST right?

- Vengat 4 years, 1 month ago

no I am getting post() got an unexpected keyword argument 'slug' with a wrong url http://127.0.0.1:8000/score/score/hthththt76/

- ahmed.hisham87 4 years, 1 month ago

I quickly reproduce the logic , see below its perfectly working to me. you can check at your end with slight change instead id, it should be slug, class DetailPostView(DetailView): model = Post template_name = 'tutorial/tutorial_detail.html' fields = ['title']

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # favorite = Favorite.objects.filter(add_favorite=True)
        form = CommentForm(self.request.POST or None)
        id = self.kwargs['pk']
        obj_post = Post.objects.get(id=id)
        context['form'] = form
        return context

    def post(self, request, *args, **kwargs):
        form = CommentForm(request.POST, None)
        if form.is_valid():
        # Write Your Logic here
            print('Its Saved')
            self.object = self.get_object()
            context = super(DetailPostView, self).get_context_data(**kwargs)
            return self.render_to_response(context=context)
- Vengat 4 years, 1 month ago

I have followed your logic and amended somethings : The views: ``` class PostCommentCreateView(CreateView): model = Comment fields = ['content']

def get(self, request, slug, *args, **kwargs):
    raise Http404

def post(self, request, slug, *args, **kwargs):
    self.post = Post.objects.get_or_404(slug=slug) <-----Error 'Manager' object has no attribute 'get_or_404'
    self.user = request.user

    super().post(request, *args, **kwargs)

def form_valid(self, form):
    form.instance.post = self.post
    form.instance.user = self.user
    return super(PostCommentCreateView, self).form_valid(form)

Here is the urls: path('post/<slug:slug>/comment', PostCommentCreateView.as_view(), name='post-comment'), here is the template: <form action={% url 'score:post-comment' post.slug %} method="post" class="comment-form" action=".">
{% csrf_token %} {{ comment_form.as_p }} {% if request.user.is_authenticated %} <input type="submit" value="Submit" class="btn btn-outline-success"> {% else %} <input type="submit" value="Submit" class="btn btn-outline-success" disabled> You must be Logged in to Comment {% endif %} </form> ```

- ahmed.hisham87 4 years, 1 month ago

why you are sending slug to POST.. see if its POST request then you just need to save the data using the form just like below def post(self, request, args, *kwargs): form = TaskForm(request.POST, None) if form.is_valid(): new_form = form.save(commit=False) new_form.user = request.user new_form.save()

    return redirect('/todo/')
- Vengat 4 years, 1 month ago

still not working I've tried everything

- ahmed.hisham87 4 years, 1 month ago

then may be i will setup a meeting sometime tomorrow. I am pretty sure, you are missing something in your code.

- Vengat 4 years, 1 month ago

that will be great

- ahmed.hisham87 4 years, 1 month ago

Can we connect around 5.30 PM PST today?

- Vengat 4 years, 1 month ago

sure

- ahmed.hisham87 4 years, 1 month ago

Awesome ..will send you the invite

- Vengat 4 years, 1 month ago

sorry i have to postponed the meeting.. how about 7 PM PST or we can connect tomorrow?

- Vengat 4 years, 1 month ago

I am ok with 7 PM PST

- ahmed.hisham87 4 years, 1 month ago

sent you the invite

- Vengat 4 years, 1 month ago

Thank you for this solution really appreciate it ``` class PostCommentCreateView(LoginRequiredMixin, CreateView): model = Comment fields = ['content', ] success_url = reverse_lazy('score:post-detail')

def post(self, request, *args, **kwargs):
    form = CommentForm(request.POST)
    if form.is_valid():
        post = form.save()
        post.save()
    print(args, kwargs, request.POST)
    return redirect('score:post-detail', slug=kwargs['slug'])

```

- ahmed.hisham87 4 years, 1 month ago

Welcome. As you can always support us Donate . If you want :)

- Vengat 4 years, 1 month ago

here is the template

{% csrf_token %} {{ comment_form.as_p }} {% if request.user.is_authenticated %} {% else %} You must be Logged in to Comment {% endif %}
{{comments.count}} Comment{{comments|pluralize}} {% for comment in comments %}

{{ comment.content}}

by{{comment.user| capfirst}}
{% endfor %}

Submitted 4 years, 1 month ago

right way to submit the comment form to different views not to same Detailed view. That is not recommended one

- Vengat 4 years, 1 month ago


Latest Blogs