Lewati ke konten utama

Blog Articles API — Dokumentasi

Versi: 1.0 • Terakhir diperbarui: 2025-11-05 04:19:30 (Asia/Jakarta)
Host API: https://api-sjs.bizpro.my.id
Resource Base Path (diasumsikan): /blog_articles

Catatan: Blueprint blog_articles_bp = Blueprint('blog_articles', __name__) tidak mendefinisikan url_prefix. Dokumentasi ini mengasumsikan blueprint dipasang pada path dasar /blog_articles. Jika berbeda di aplikasi Anda, sesuaikan contoh URL di bawah.


Ringkasan

API ini mengelola artikel blog dengan dukungan unggah gambar (multipart form) dan metadata lengkap (slug, excerpt, content, author, category, tags, dsb.).

Fitur utama

  • CRUD artikel (list, get by id, create, update, delete)
  • Upload file gambar via field image_file (multipart/form-data)
  • Alternatif: gunakan image_url bila file tidak diunggah
  • Slug otomatis dari title jika tidak dikirim
  • tags aman diparse dengan json.loads (fallback daftar dipisah koma)
  • Pembersihan file lama saat update/delete (bila host sesuai domain API)
  • Kolom published_at dapat dikirim manual atau default UTC now di server

Konvensi respons

  • Sukses: { "success": true, ... }
  • Gagal: { "success": false, "message": "..." }

Skema Tabel

Nama tabel: blog_articles

KolomTipeKeterangan
idINT UNSIGNED (PK)Auto increment
titleVARCHAR(255)Wajib
slugVARCHAR(255) UNIQUEDefault: dari title (lower().replace(' ', '-')) jika tidak dikirim
excerptTEXTRingkasan (opsional)
contentLONGTEXTKonten HTML/Markdown (opsional)
image_urlVARCHAR(255)URL gambar (opsional; diisi saat upload sukses)
image_altVARCHAR(255)Alt text (opsional)
authorVARCHAR(100)Nama penulis (opsional)
published_atDATETIMEWaktu terbit (opsional)
is_featuredTINYINT(1)1=unggulan; default 0
is_activeTINYINT(1)1=aktif; default 1
created_atDATETIMEOtomatis oleh DB
updated_atDATETIMEOtomatis on update
detail_urlVARCHAR(255)Link detail (opsional)
category_idINTFK ke blog_categories.id (opsional)
tagsLONGTEXT (JSON valid)Disarankan JSON array string; DB memeriksa json_valid(tags)

Penyimpanan file gambar

  • Folder: Config.UPLOAD_FOLDER_ARTICLES (default public/img/articles)
  • Nama file: uuid4.ext (aman dengan secure_filename)
  • URL publik dibentuk: https://api-sjs.bizpro.my.id/public/img/articles/<uuid>.<ext>

Format tags

  • Kirim sebagai JSON string: ["hr", "outsourcing"]
  • Jika mengirim string biasa "hr, outsourcing", server akan fallback memisah koma.

Keamanan parsing

  • Tidak menggunakan eval() untuk tags; menggunakan json.loads() (aman).

Endpoints

1) List semua artikel

GET https://api-sjs.bizpro.my.id/blog_articles/

Respons 200

{ "success": true, "data": [ /* array artikel */ ] }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

2) Ambil artikel berdasarkan ID

GET https://api-sjs.bizpro.my.id/blog_articles/{id}

Respons 200

{ "success": true, "data": { /* objek artikel */ } }

Respons 404

{ "success": false, "message": "Not found" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

3) Buat artikel baru (multipart form)

POST https://api-sjs.bizpro.my.id/blog_articles/

Tipe konten: multipart/form-data

Field Form (teks)

  • title (string, wajib)
  • slug (string, opsional; default dari title)
  • excerpt (string, opsional)
  • content (string, opsional)
  • image_alt (string, opsional)
  • author (string, opsional)
  • published_at (string datetime, opsional; default UTC now)
  • is_featured (0/1, opsional; default 0)
  • is_active (0/1, opsional; default 1)
  • detail_url (string, opsional)
  • category_id (int, opsional)
  • tags (string JSON atau daftar dipisah koma; opsional)

Field File (opsional)

  • image_file (png/jpg/jpeg/gif/webp; maksimal sesuai konfigurasi server)

Alternatif tanpa upload file

  • Kirim image_url (string) sebagai URL gambar publik.

Contoh (upload file)

curl -s -X POST "https://api-sjs.bizpro.my.id/blog_articles/"   -H "Accept: application/json"   -F "title=Tips Rekrutmen Efisien"   -F "excerpt=Ringkasan singkat artikel"   -F "content=<h1>Konten</h1><p>...</p>"   -F "author=SJS Team"   -F "is_active=1"   -F "is_featured=1"   -F "tags=[\"rekrutmen\", \"outsourcing\"]"   -F "image_file=@/path/to/image.webp"

Contoh (pakai image_url)

curl -s -X POST "https://api-sjs.bizpro.my.id/blog_articles/"   -H "Accept: application/json"   -F "title=Panduan HR 2025"   -F "image_url=https://cdn.example.com/img/hr2025.jpg"   -F "tags=hr, panduan"

Respons 201

{ "success": true, "id": 38, "message": "Article created successfully" }

Respons 400

{ "success": false, "message": "Title is required" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

4) Perbarui artikel (multipart form)

PUT https://api-sjs.bizpro.my.id/blog_articles/{id}

Tipe konten: multipart/form-data

Catatan penting

  • title tetap wajib pada update.
  • Jika mengunggah image_file baru dan image_url lama berasal dari domain API, file lama akan dihapus dari storage.
  • Jika tidak mengunggah file, Anda bisa mengirim image_url baru untuk mengganti tautan gambar.

Contoh (ganti sebagian field + upload gambar baru)

curl -s -X PUT "https://api-sjs.bizpro.my.id/blog_articles/38"   -H "Accept: application/json"   -F "title=Tips Rekrutmen Efisien (Update)"   -F "is_featured=0"   -F "tags=[\"rekrutmen\", \"hr\"]"   -F "image_file=@/path/to/new-image.jpg"

Contoh (tanpa upload, ganti image_url)

curl -s -X PUT "https://api-sjs.bizpro.my.id/blog_articles/38"   -H "Accept: application/json"   -F "title=Panduan HR 2025 (Update)"   -F "image_url=https://cdn.example.com/img/hr2025-new.jpg"

Respons 200

{ "success": true, "affected": 1, "message": "Article updated successfully" }

Respons 404

{ "success": false, "message": "Not found" }

Respons 400

{ "success": false, "message": "Title is required" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

5) Hapus artikel

DELETE https://api-sjs.bizpro.my.id/blog_articles/{id}

Perilaku tambahan

  • Jika image_url adalah URL di domain API (folder upload default), server mencoba menghapus file terkait.

Contoh

curl -s -X DELETE "https://api-sjs.bizpro.my.id/blog_articles/38"

Respons 200

{ "success": true, "affected": 1, "message": "Article deleted successfully" }

Respons 404

{ "success": false, "message": "Not found" }

Respons 500

{ "success": false, "message": "penjelasan kesalahan" }

Validasi & Batasan

  • File type: png, jpg, jpeg, gif, webp (field image_file) — divalidasi oleh allowed_file().
  • Slug: wajib unik di DB (index unik). Jika mengirim slug duplikat, insert/update dari layer model akan gagal (tangani pesan error).
  • Tags: simpan sebagai JSON valid. Pastikan aplikasi frontend mengirim JSON string atau string dipisah koma dengan benar.
  • Category: category_id adalah FK ke blog_categories.id (pastikan id valid).

Praktik Terbaik Produksi

  • Batasi ukuran file upload di konfigurasi server (Nginx/Flask) dan validasi ukuran di aplikasi.
  • Tambahkan auth (JWT/session) & rate limiting.
  • Logging terstruktur untuk audit (request-id, user-id).
  • Jika arsitektur CDN, simpan hanya path relatif pada DB, dan bangun URL publik di frontend.
  • Sanitasi konten content bila HTML (hindari XSS).

Changelog

  • v1.0 — Dokumentasi awal berdasarkan blog_articles_routes.py dan skema blog_articles.