HarryLeBadger
HarryLeBadger

Reputation: 25

Why is my Django form posting again from the index page?

I'm new to Django and have been following a few printed and online tutorials to start developing a basic web application. I've gotten to the point where I have:

My form allows me to enter the name of a file and saves it in the database. The form works, it saves the data to the database and the user is returned to the index page. All works fine.

My problem is this:

  1. If I'm returned to the index page after submitting the form and I hit refresh in the browser it tries to submit the same data again, even though the form isn't being displayed.
  2. Even though I can see the index page content the URL in the browser address bar still has the URL of the add_media form.

It's all very odd! Here's some code:

The view functions for index and add_media:

from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.template.context_processors import request

from .forms import MediaForm
from .models import Media

# Create your views here.
@login_required
def index(request):

    media_list = Media.objects.order_by('title')
    context_dict = {'media': media_list}
    return render(request, 'media/index.html', context_dict)

@login_required
def add_media(request):
    form = MediaForm()

    if request.method == 'POST':
        form = MediaForm(request.POST)

        if form.is_valid():
            form.save(commit = True)

            return index(request)
        else:
            print(form.errors)

    return render(request, 'media/add_media.html', {'form': form})

Here's the form:

from django import forms

from .models import Media

class MediaForm(forms.ModelForm):
    media = Media
    title = forms.CharField(max_length=50)

    class Meta:
        # Associate the ModelForm and the Model
        model = Media
        fields = ('title',)

The templates:

{% extends 'base.html' %}

{% block title %}My Media Library{% endblock %}
{% block content %}
    <a href="/media/add_media/" id="id_add_media">Add Media</a> - <a href="/account/logout" id="id_logout">Logout</a>
    <h2 name="pagename">Home Page</h2>
    <div>
    {% if media %}
    <ul>
        {% for item in media %}
            <li>
                {{ item.title }}
            </li>
        {% endfor %}
    </ul>
    {% else %}
        <p>There is no media in the system at present</p>
    {% endif %}    


    </div>

{% endblock %}

The add_media.html template:

{% extends 'base.html' %}

{% block title %}Add Media{% endblock %}

{% block content %}
  <h2>Add Media</h2>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" value="Save Media" name="save">Save Media</button>
  </form>
{% endblock %}

URLs:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'), 
    url(r'^index/$', views.index, name='index'), 
    url(r'^add_media/$', views.add_media, name="add_media"),
    ]

Can someone tell me why, when I hit refresh (F5) on the index page it tries to repost the add_media form?

Thanks in advance

David

Upvotes: 0

Views: 176

Answers (1)

Alasdair
Alasdair

Reputation: 308999

After a successful post request, you should redirect the user, to prevent duplicate form submissions. Currently, you are rendering the index template, instead of redirecting to the index url. Change your view to:

from django.shortcuts import redirect

@login_required
def add_media(request):
    form = MediaForm()

    if request.method == 'POST':
        form = MediaForm(request.POST)

        if form.is_valid():
            form.save(commit = True)
            return redirect('index')

Upvotes: 1

Related Questions