DEV Community

Pavitha P
Pavitha P

Posted on

PRG pattern

🌀 Demystifying POST–REDIRECT–GET in Flask

Ever submitted a form in your Flask app and then hit refresh—only to get a browser warning about resending data? Welcome to the world of POST resubmission, a sneaky little side effect that’s solved beautifully by the Post–Redirect–Get (PRG) pattern.

Let’s break it down 👇


📬 The Problem with POST: Form Resubmission

Imagine this flow:

  1. User fills out a form (e.g., update profile).
  2. You handle the form with POST.
  3. You use render_template() to show the dashboard directly.
  4. Then... the user refreshes the page.

🔁 Result: The browser resubmits the form, triggering a second POST!

This can:

  • Cause duplicate database writes
  • Repeat email or username changes
  • Show misleading flash messages again
  • Annoy users with “Confirm form resubmission” alerts

✅ Enter the Hero: Post–Redirect–Get (PRG)

Instead of rendering the updated page right after the POST, PRG introduces a redirect step so the browser only refreshes with a safe GET.

PRG flow:

POST → Redirect → GET
Enter fullscreen mode Exit fullscreen mode

✨ Example: Updating Profile

@app.route('/account', methods=['GET', 'POST'])
@login_required
def account():
    form = UpdateProfileForm()
    if form.validate_on_submit():
        current_user.username = form.username.data
        current_user.email = form.email.data
        db.session.commit()
        flash('Your account has been updated!', 'success')
        return redirect(url_for('account'))  # 🔄 Redirect fixes refresh bug
    return render_template('dashboard.html', form=form, user=current_user)
Enter fullscreen mode Exit fullscreen mode

📌 Why This Works

  • User submits form → POST runs and updates DB
  • Server sends a redirect to /account
  • Browser follows redirect → does a GET
  • Refreshing now re-runs the GET, not the form submission

🧪 Bonus Tip: Use DevTools to Watch the Flow

In your browser's developer tools:

  • Check the Network tab
  • Watch for the POST request, followed by a 302 Found redirect
  • The next request will be GET—clean and safe for refreshes

Top comments (0)