DataLens

HTTP method: GET dan POST

Tangani pembacaan dan pengiriman data di URL yang sama, baca data formulir yang di-POST, ikuti pola Post/Redirect/Get, dan kembalikan status code yang tepat.

Level: Dasar · 8 menit baca

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

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.

MethodArtiAman diulang?Contoh
GETmembaca sesuatuya, tidak mengubah apa punmelihat produk
POSTmengirim data untuk diproses / membuat sesuatutidakmembuat pesanan
PUT / PATCHmengganti / memperbarui sesuatuPUT ya, PATCH tergantungmemperbarui alamat pelanggan
DELETEmenghapus sesuatuyamembatalkan 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

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.

Ide utama

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

SituasiStatus
berhasil membuat sesuatu201 Created
formulir sudah ditangani, arahkan pengguna ke halaman lain302 Found (redirect)
input tidak ada atau tidak valid400 Bad Request
method tidak didukung di URL ini405 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

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Berikutnya: Template dengan Jinja2 →