Michael
Michael

Reputation: 11

Simple Django Form POST - Not posting

I am fairly new to Django, and programming in general, and I am attempting to increment an IntegerField up by one, every time someone clicks a button from the template. I have researched this for about 10 hours (I know, ridiculous) with no luck... I'm thinking it is just something extremely simple that I have just looked over. I thought I had solved it with either this or this question, but I still couldn't get it.

Here is my template (which I am using to {% include %} in a separate template):

{% block body %}
<form method="post" action="/vote/">{% csrf_token %}
    <input type="submit" name="endorsers" value="Endorse" />
</form>
{% endblock %}

Models.py:

class IdeaID(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=30)
    description = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published', auto_now_add=True)
    endorsers = models.IntegerField(default=0)
    contributors = models.IntegerField(default=0)
    backers = models.IntegerField(default=0)

    def __unicode__(self):
        return self.name

My url is set up like this:

url(r'^vote/$', 'ideaMachine.views.vote'),

And Views.py:

@login_required
def vote(request):
    if (request.method == 'POST') and ("endorsers" in request.POST):
        idea_list = request.POST.getlist('ideaid')

        for idea in idea_list:
            ideaVote = IdeaID.objects.get(pk=idea)
            ideaVote.endorsers += 1
            ideaVote.save()
    return render_to_response(
        'vote_success.html', RequestContext(request)
    )

From django's dev server, I am getting a "'POST /vote/ HTTP/1.1' 200 58". I'm not sure if that helps solve my problem. The post is not actually updating my endorsers field like I am wanting, but is sending me to the vote_success.html, successfully. I'm lost at this point, any help would be greatly appreciated. Thanks ahead of time!

Upvotes: 1

Views: 2629

Answers (1)

fragles
fragles

Reputation: 680

You are probably trying to implement a functionality which allows endorsement of different users.

Here is how you could modify the code to make it work:

in the vote.html template modify to:

<form method="post" action="/vote/">{% csrf_token %}
{% for ideaid in ideaids %}
    <li>{{ ideaid.user }} - {{ ideaid.endorsers }}
    <input type="checkbox" name="ideaid" value="{{ ideaid.id }}" /></li><br />
{% endfor %}
<input type="submit" name="endorsers" value="Endorse" />
</form>

I assume that vote_success.html looks something like

{% for ideaid in ideaids %}
    <li>{{ ideaid.user }} - {{ ideaid.endorsers }}
{% endfor %}

Then you could modify views.py

  • Use render(request, instead of render_to_response
  • Populate ideaids in the context with data from IdeaID
  • Always return an HttpResponseRedirect after successfully dealing with POST data. This prevents data from being posted twice if a user hits the Back button.

views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.template import Context, RequestContext, loader
from django.core.urlresolvers import reverse
from django.shortcuts import render, render_to_response

def vote(request):

    if (request.method == 'POST') and ("endorsers" in request.POST):
        idea_list = request.POST.getlist('ideaid')

        for idea in idea_list:
            ideaVote = IdeaID.objects.get(pk=idea)
            ideaVote.endorsers += 1
            ideaVote.save()
        return HttpResponseRedirect(reverse('ideaMachine.views.vote_success', args=()))

    ideaid = IdeaID.objects.all()
    return render(request, 'vote.html', {'ideaids':ideaid})

def vote_success(request):
    ideaid = IdeaID.objects.all()
    return render(request, 'vote_success.html', {'ideaids':ideaid})

You need also one more entry in urls:

    url(r'^success/$', 'ideaMachine.views.vote_success'),

Upvotes: 1

Related Questions