Idenya
Sejauh ini setiap route menjawab GET: "berikan halaman ini". Situs web juga perlu menerima data: pesanan baru, pesan kontak, login. Itulah POST. Method adalah bagian dari setiap request, dan sebuah route bisa memperlakukan setiap method secara berbeda.
| Method | Arti | Aman diulang? | Contoh |
|---|---|---|---|
GET | membaca sesuatu | ya, tidak mengubah apa pun | melihat produk |
POST | mengirim data untuk diproses / membuat sesuatu | tidak | membuat pesanan |
PUT / PATCH | mengganti / memperbarui sesuatu | PUT ya, PATCH tergantung | memperbarui alamat pelanggan |
DELETE | menghapus sesuatu | ya | membatalkan draf |
Aturan yang paling penting: GET tidak boleh mengubah apa pun. Browser melakukan prefetch link, mesin pencari melakukan crawl, pengguna me-refresh halaman. Kalau GET /orders/41/cancel membatalkan pesanan, sebuah crawler bisa membatalkan seluruh tokomu.
Mengizinkan method
Halaman kontak Toko Kita harus melakukan dua hal di URL yang sama: menampilkan formulirnya saat seseorang membukanya (GET), dan menerima pesannya saat mereka menekan Kirim (POST). Secara default sebuah route hanya menerima GET, jadi kamu menyebutkan method yang harus ditanganinya dengan methods=:
from flask import Flask, request
app = Flask(__name__)
MESSAGES = []
@app.route("/contact", methods=["GET", "POST"])
def contact():
if request.method == "POST":
MESSAGES.append(request.form["message"])
return "Thanks, we got your message.", 201
return "<form method='post'><textarea name='message'></textarea><button>Send</button></form>"
client = app.test_client()
print(client.get("/contact").status_code)
r = client.post("/contact", data={"message": "Do you ship to Medan?"})
print(r.status_code, r.get_data(as_text=True))
print(MESSAGES)
print(client.delete("/contact").status_code)
200
201 Thanks, we got your message.
['Do you ship to Medan?']
405
requestadalah objek Flask untuk request yang sedang berjalan.request.methodmenunjukkan method mana yang dipakai.request.formmenyimpan field yang di-POST dari formulir HTML, mirip dict.client.post(path, data={...})mengirim data formulir, sama seperti browser yang men-submit formulir.201 Createdberarti "sesuatu yang baru telah dibuat". Method yang tidak diizinkan otomatis mendapat 405 Method Not Allowed.
Fungsi terpisah per method
Saat logika GET dan POST makin besar, pisahkan. Flask 2+ punya decorator pintas:
from flask import Flask, request
app = Flask(__name__)
ORDERS = []
@app.get("/orders")
def list_orders():
return {"orders": ORDERS}
@app.post("/orders")
def create_order():
product = request.form.get("product", "").strip()
if not product:
return {"error": "product is required"}, 400
ORDERS.append(product)
return {"created": product, "count": len(ORDERS)}, 201
client = app.test_client()
print(client.post("/orders", data={"product": "Ceramic Mug"}).get_json())
print(client.post("/orders", data={}).status_code)
print(client.get("/orders").get_json())
{'count': 1, 'created': 'Ceramic Mug'}
400
{'orders': ['Ceramic Mug']}
@app.get dan @app.post artinya @app.route(..., methods=["GET"]) dan ["POST"]. Mengembalikan dict akan mengirim JSON (lebih lanjut di modul API).
request.form["product"] memunculkan error (400 Bad Request) kalau field-nya tidak ada; request.form.get("product", "") mengembalikan nilai default, sehingga kamu bisa menampilkan pesan yang ramah. Validasi semua hal yang datang dari request: itu input pengguna, dan pengguna (serta penyerang) bisa mengirim apa saja.
Post/Redirect/Get
Setelah POST formulir berhasil, jangan langsung mengembalikan halaman. Kalau pengguna me-refresh, browser akan bertanya "kirim ulang formulir?", dan jawaban "ya" membuat pesanannya dua kali. Sebagai gantinya, redirect ke halaman GET:
from flask import Flask, request, redirect, url_for
app = Flask(__name__)
ORDERS = []
@app.get("/")
def home():
return f"{len(ORDERS)} orders so far"
@app.post("/orders")
def create_order():
ORDERS.append(request.form["product"])
return redirect(url_for("home"))
client = app.test_client()
r = client.post("/orders", data={"product": "Kettle"})
print(r.status_code, r.headers["Location"])
r = client.post("/orders", data={"product": "Mug"}, follow_redirects=True)
print(r.status_code, r.get_data(as_text=True))
302 /
200 2 orders so far
redirect() mengembalikan 302 dengan header Location; browser lalu melakukan GET ke URL itu. Me-refresh sekarang hanya memuat ulang halaman GET yang tidak berbahaya. Pola ini disebut Post/Redirect/Get (PRG), dan hampir semua formulir di web memakainya.
GET membaca dan aman diulang. POST mengubah sesuatu, memvalidasi input-nya, dan menjawab dengan redirect (untuk formulir) atau 201 (untuk API).
Status code untuk operasi tulis
| Situasi | Status |
|---|---|
| berhasil membuat sesuatu | 201 Created |
| formulir sudah ditangani, arahkan pengguna ke halaman lain | 302 Found (redirect) |
| input tidak ada atau tidak valid | 400 Bad Request |
| method tidak didukung di URL ini | 405 Method Not Allowed (otomatis) |
Mengapa ini penting untuk kode yang bersih
Method memberi setiap URL kontrak yang jelas: GET /orders menampilkan daftar, POST /orders membuat. Memisahkan view per method menjaga setiap fungsi punya satu tujuan, validasi mencegah data buruk masuk, dan PRG mencegah pesanan ganda. Ini kebiasaan kecil yang membedakan aplikasi mainan dari aplikasi yang melayani pelanggan sungguhan.
Rangkuman
GETmembaca (tidak pernah mengubah data);POSTmengirim data untuk dibuat atau diproses.methods=["GET", "POST"], atau@app.get/@app.post;request.methodmenunjukkan yang mana.request.formmenyimpan field yang di-POST; utamakan.get(name, default)dan lakukan validasi.- Kembalikan
201untuk data yang dibuat,400untuk input buruk; method yang tidak diizinkan mendapat405. - Setelah POST formulir,
redirect(url_for(...)): Post/Redirect/Get.