jiyi
jiyi

Reputation: 101

Django: url in "form action" doesn't work

In detail.html:

<form id="answer_form" class="form-horizontal" action="{% url 'puzzle:update' puzzle.id %}" method="POST" onSubmit="return ValidateAnswer();">
    {% csrf_token %}
    <p>Please entry your answer below: (Case insensitive)</p>
    <div class="form-group col-xs-12">
        <input id="player_answer" maxlength="30" name="player_answer" type="text">
    </div>
    <div class="form-group col-xs-12">
        <button id="submit_answer_btn" class="btn btn-success" type="submit">Submit</button>
    </div>
</form>

<script>
function ValidateAnswer() {
    var player_answer = document.getElementById("player_answer");
    if(player_answer.value == {{ puzzle.answer }}) {
        alert("Congratulations!");
    } else {
        alert("Wrong answer!");
        return false;
    }
}
</script>

In url.py

app_name = 'puzzle'

urlpatterns = [
    url(r'^(?P<pk>[0-9]+)/$', login_required(views.PuzzleDetailView.as_view()), name='detail'),
    url(r'^(?P<puzzle_id>[0-9]+)/update/$', views.update_user_game_history, name='update'),
]

In views.py

class PuzzleDetailView(DetailView):
    model = Puzzle
    template_name = 'puzzle/detail.html'


def update_user_game_history(request, puzzle_id):
    player_game_history = PlayerGameHistory.objects.get(user=request.user)
    solved_puzzle = Puzzle.objects.get(id=puzzle_id)
    player_game_history.score += solved_puzzle.point
    player_game_history.save()
    return HttpResponseRedirect('/')

What I am trying to do is to click on Submit button, via 2nd url, go to the update_user_game_history function in views.py.

However, everytime I submit, the flow tries to, via 1st url, go to the PuzzleDetailView. And I get Method Not Allowed (POST): /2/ in terminal

Upvotes: 0

Views: 2544

Answers (2)

Mauricio Cortazar
Mauricio Cortazar

Reputation: 4213

I am not sure if that solved your problem but basically in the view you don't have a way to ensure if the method is 'POST' or not. To solve that you can add this line in your code:

def update_user_game_history(request, puzzle_id):
    if request.method == 'POST':
        player_game_history = PlayerGameHistory.objects.get(user=request.user)
        solved_puzzle = Puzzle.objects.get(id=puzzle_id)
        player_game_history.score += solved_puzzle.point
        player_game_history.save()
        return HttpResponseRedirect('/')

But according with your example is not necessary call a form because you aren't using it. My recommendation is to improve this view because only with a url you can score many times you want

Upvotes: 1

jiyi
jiyi

Reputation: 101

Many thanks to Alasdair. After checking the rendered form tag, I found out the problem. Value of action attribute in form tag was wrong. It was still "#". It seems like Chrome back button doesn't retrieve the lastest page from server. It only reload what it received before.

Upvotes: 0

Related Questions