1

I use the POST method since I need to change the database. But each time I used the POST method, this error occurred. Every time I click the button, the page will not be loading and saying "POST /book/go-action/ HTTP/1.1" 405 0. There is no difference when I use q = request.POST["quantity"] or q = request.POST.get('quantity', ''). If I use GET method, the issue will not occur but the GET method cannot meet the needs. Also I don't need action in the form, cos I don't need the page to redirect to somewhere and I'm using ajax to call the function view. How can I fix the issue?

Updated:

The problem was caused by missing action="{% url 'cart:add_to_cart' %}". But I don't want it to redirect to another page, that's why I'm using Ajax instead of using action. If using action then Ajax will become pointless I guess.

book/detail.html:

<script>
    $(document).ready(function () {
        $("#add").click(function () {
            alert('clicked');
            $.ajax({
                url: '{% url "cart:add_to_cart" %}',
                type: "POST",
                dataType: 'json',
                success: function (response) {
                    $("#cartButton").text("Cart" + "(" + response.quantity + ")");
                },
                error: function (response) {
                    alert('Got an error');
                }
            });
        });
    });
</script>

<form method="post"> {% csrf_token %}
    <select name="quantity">
        <option>1</option>
        <option>2</option>
        <option>3</option>
    </select>
    <input name="bookID" value=" {{ book.id }} " hidden>
    <button id="add" type="submit"> Add to Cart</button>
</form>

cart/views.py:

def add_books(request):

    c = Cart.objects.get(user=request.user)

    if request.method == 'POST':
        # q = request.POST["quantity"]
        # book_id = request.POST["bookID"]

        q = request.POST.get('quantity', '')
        book_id = request.POST.get('bookID', '')

       # the rest of the code here         

        return JsonResponse(response)

cart/urls.py:

app_name = 'cart'
urlpatterns = [
    path('add_books/', views.add_books, name='add_to_cart')
]

book/urls.py:

app_name = 'book'
urlpatterns = [
    path('<slug:slug>/', views.BookDetailView.as_view(), name='detail'),
 name='category_search'),
]
SpellTheif
  • 595
  • 7
  • 19

1 Answers1

1

The issue is that your form submits and sends the request to /book/go-action/, which I assume is the route for the view the form is on, but the route that the POST should go to is /add_books as defined in your urls.py.

To fix this, you need to add an action attribute to your <form>. Here's an example:

<form method="post" action="/add_books"> {% csrf_token %}
    <select name="quantity">
        <option>1</option>
        <option>2</option>
        <option>3</option>
    </select>
    <input name="bookID" value=" {{ book.id }} " hidden>
    <button id="add" type="submit"> Add to Cart</button>
</form>

Edit: Ajax Code (independent of my above code)

I think the main issue here is that while the click event function will work properly (as far as I can tell), after it executes, the submit event is still triggered and the default action ensues. To fix you need to add event as an argument to the function and call preventDefault on that event so that the default submit does not happen.

Here's what that looks like:

<script>
    $(document).ready(function () {
        $("#add").click(function (event) {
            event.preventDefault();
            alert('clicked');
            $.ajax({
                url: '{% url "cart:add_to_cart" %}',
                type: "POST",
                dataType: 'json',
                success: function (response) {
                    $("#cartButton").text("Cart" + "(" + response.quantity + ")");
                },
                error: function (response) {
                    alert('Got an error');
                }
            });
        });
    });
</script>
Henry Woody
  • 9,777
  • 6
  • 27
  • 37
  • yeah I see, thanks. But I want it to stay in the same page instead of redirecting to another page once I add books. That's why I'm using Ajax. I'll upload my Ajax code as well. – SpellTheif Sep 21 '18 at 22:35
  • @Jinx ah well if you can't get Ajax to work, you can have the `add_books` function return `HttpResponseRedirect('book/go-action')` so the user is kept on the current page. – Henry Woody Sep 21 '18 at 22:39
  • sorry for bothering u really. cos I want to learn how to use ajax, and I think I may need it a lot in the future. Can u please take a look at my ajax code as well? – SpellTheif Sep 21 '18 at 22:46
  • @Jinx yeah no worries. When you submit the form, do you get the expected behavior once before the error? Meaning is a book created? I'm wondering if the form is submitting twice – Henry Woody Sep 21 '18 at 22:51
  • no, it can't load anything immediately after I press the button. `This page isn’t working. If the problem continues, contact the site owner. HTTP ERROR 405`. And there is no change in the database. – SpellTheif Sep 21 '18 at 22:53
  • @Jinx right but if you put a `print` statement in your `add_books` function can you see it being called twice in a row? – Henry Woody Sep 21 '18 at 22:53
  • that's the other problem, I tried to print something as what you said. But PyCharm sucks, I can't see any output on the Python Console. On the terminal, it said `Method Not Allowed (POST): /book/swift-programming-big-nerd-ranch-guide/` and `Method Not Allowed: /book/swift-programming-big-nerd-ranch-guide/ `. – SpellTheif Sep 21 '18 at 22:57
  • I added it. Now nothing happens if I click the button, the button does nothing. – SpellTheif Sep 21 '18 at 23:00
  • ah sorry, I forgot the alert statement, the alert worked but the rest not working – SpellTheif Sep 21 '18 at 23:05
  • @Jinx I think the line in the `success` handler may need a `$` at the beginning of it? – Henry Woody Sep 21 '18 at 23:10
  • like `$success: function (response) `?, no difference hahaha can't be bothered – SpellTheif Sep 21 '18 at 23:12
  • @Jinx like `$("#cartButton")` – Henry Woody Sep 21 '18 at 23:13
  • ah yes sure, but the problem is that it is not submitting anything, no books added on the background. my view works fine (tested using `action`). – SpellTheif Sep 21 '18 at 23:15
  • ah in the browser console it says `2(index):31 Uncaught TypeError: $.ajax is not a function at HTMLButtonElement. ((index):31) at HTMLButtonElement.dispatch (jquery-3.2.1.slim.min.js:3) at HTMLButtonElement.q.handle (jquery-3.2.1.slim.min.js:3)` – SpellTheif Sep 21 '18 at 23:20
  • @Jinx yep that'll be it I think. It looks like you're using the slim build if jQuery, which I think does not support ajax, so you can just change to the normal build. – Henry Woody Sep 21 '18 at 23:25
  • yeah now the `error` section worked, still need to work on it? how? – SpellTheif Sep 21 '18 at 23:27
  • I tried this. `error: function (response) { alert(response.quantity); }`, then the alert says 'undefined' – SpellTheif Sep 21 '18 at 23:29
  • @Jinx you'll need to log the response to see what it looks like and possibly check your servers logs and debug from there. However this is getting beyond the scope of the original question. If you can identify a new problem that you need help with, I'd suggestion starting a new question on SO – Henry Woody Sep 21 '18 at 23:31