Menghasilkan dokumentasi API yang komprehensif dan akurat adalah bagian penting namun seringkali membosankan dalam pengembangan perangkat lunak. Spesifikasi OpenAPI (sebelumnya dikenal sebagai Swagger) telah muncul sebagai standar industri untuk mendefinisikan API RESTful. Spesifikasi ini menyediakan format yang dapat dibaca mesin yang memungkinkan manusia dan komputer untuk menemukan dan memahami kemampuan suatu layanan tanpa akses ke kode sumber, dokumentasi, atau melalui inspeksi lalu lintas jaringan.1
Meskipun banyak kerangka kerja menawarkan plugin untuk menghasilkan spesifikasi OpenAPI dari anotasi kode (seperti docstrings), ada skenario di mana Anda mungkin memerlukan kontrol yang lebih langsung dan terprogram atas pembuatan spesifikasi. Ini bisa jadi karena Anda bekerja dengan sistem lama, kerangka kerja non-standar, atau Anda perlu menghasilkan spesifikasi untuk API yang terdiri dari beberapa layanan mikro.
Di sinilah pyswagger
berperan. Ini adalah pustaka Python yang kuat yang berfungsi sebagai toolkit untuk OpenAPI. Meskipun sering digunakan sebagai klien API untuk mengonsumsi layanan yang ditentukan oleh spesifikasi OpenAPI, kekuatan sebenarnya terletak pada model objeknya, yang memungkinkan Anda membangun, memanipulasi, dan memvalidasi spesifikasi secara terprogram.
Dalam tutorial komprehensif ini, kita akan membahas proses penggunaan pyswagger
untuk secara manual, namun otomatis, menghasilkan spesifikasi OpenAPI 3.0 yang lengkap untuk aplikasi web Python sederhana yang dibangun dengan Flask. Kita akan membangun spesifikasi dari awal, bagian demi bagian, menunjukkan bagaimana objek pyswagger
memetakan langsung ke komponen standar OpenAPI. Pada akhirnya, Anda tidak hanya akan memiliki file openapi.json
yang dihasilkan, tetapi juga UI dokumentasi interaktif langsung yang disajikan langsung dari aplikasi Anda.
Ingin platform Terintegrasi, All-in-One untuk Tim Developer Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
Bagian 1: Menyiapkan Lingkungan Proyek
Sebelum kita mulai menghasilkan spesifikasi, kita perlu menyiapkan lingkungan pengembangan yang tepat. Ini melibatkan pembuatan lingkungan Python yang terisolasi untuk mengelola dependensi kita dan menginstal pustaka yang diperlukan.
Membuat Ruang Kerja Anda ⚙️
Pertama, mari kita buat direktori untuk proyek kita. Buka terminal atau command prompt Anda dan jalankan perintah berikut:Bash
# Create a new directory for our project
mkdir pyswagger-tutorial
cd pyswagger-tutorial
# Create a Python virtual environment
# On macOS/Linux
python3 -m venv venv
# On Windows
python -m venv venv
Lingkungan virtual adalah struktur direktori mandiri yang mencakup instalasi Python dan sejumlah file pendukung. Menggunakan lingkungan virtual memastikan bahwa paket yang kita instal untuk proyek ini tidak berkonflik dengan paket yang diinstal untuk proyek lain.
Sekarang, aktifkan lingkungan virtual:Bash
# On macOS/Linux
source venv/bin/activate
# On Windows
.\venv\Scripts\activate
Setelah diaktifkan, prompt terminal Anda akan berubah untuk menampilkan nama lingkungan virtual (misalnya, (venv)
), menunjukkan bahwa Anda sekarang bekerja di dalamnya.
Menginstal Pustaka yang Diperlukan
Dengan lingkungan kita aktif, kita dapat menginstal pustaka Python yang akan kita perlukan untuk tutorial ini. Kita memerlukan pyswagger
itu sendiri untuk membangun spesifikasi, Flask
untuk membuat API web sederhana kita, dan PyYAML
karena pyswagger
menggunakannya untuk operasi YAML.Bash
pip install "pyswagger[utils]" Flask PyYAML
Bagian [utils]
saat menginstal pyswagger
adalah praktik yang baik karena mencakup utilitas yang berguna, seperti validator yang akan kita gunakan nanti untuk memeriksa kebenaran spesifikasi yang kita hasilkan.
Untuk manajemen proyek yang baik, disarankan untuk menentukan dependensi Anda dalam file requirements.txt
.Bash
pip freeze > requirements.txt
File requirements.txt
Anda sekarang akan berisi pustaka dan versi spesifiknya, membuat proyek Anda mudah direproduksi oleh orang lain.
Membuat Aplikasi Flask Dasar
Sekarang, mari kita buat aplikasi Flask minimal. Ini akan berfungsi sebagai fondasi API yang akan kita dokumentasikan.
Di direktori proyek Anda, buat file baru bernama app.py
dan tambahkan kode berikut:Python
# app.py
from flask import Flask, jsonify
# Initialize the Flask application
app = Flask(__name__)
@app.route("/")
def index():
""" A simple endpoint to check if the app is running. """
return jsonify({"message": "API is up and running!"})
if __name__ == "__main__":
# Runs the Flask app on http://127.0.0.1:5000
app.run(debug=True)
Kode ini menyiapkan server web yang sangat sederhana dengan satu endpoint. Untuk menjalankannya, pastikan lingkungan virtual Anda masih aktif dan jalankan perintah berikut di terminal Anda:Bash
python app.py
Anda akan melihat output yang menunjukkan bahwa server sedang berjalan, sesuatu seperti ini:
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
Anda sekarang dapat membuka browser web Anda atau menggunakan alat seperti curl
untuk mengunjungi http://127.0.0.1:5000
. Anda akan melihat respons JSON: {"message": "API is up and running!"}
.
Dengan lingkungan dasar dan kerangka aplikasi kita di tempat, kita sekarang dapat mendalami konsep inti pyswagger
.
Bagian 2: Memahami Model Objek pyswagger
Untuk menggunakan pyswagger
secara efektif untuk menghasilkan spesifikasi, Anda harus terlebih dahulu memahami bagaimana model objeknya sesuai dengan struktur dokumen OpenAPI. Spesifikasi OpenAPI pada dasarnya adalah objek JSON atau YAML besar dengan skema tertentu. pyswagger
menyediakan kelas dan objek Python yang mencerminkan skema ini, memungkinkan Anda membangun spesifikasi dengan cara yang lebih intuitif dan berorientasi objek.
Konsep Inti Spesifikasi OpenAPI 3.0 📜
Dokumen OpenAPI 3.0 memiliki beberapa bidang tingkat atas utama:
openapi
: String yang menentukan versi Spesifikasi OpenAPI (misalnya,'3.0.0'
).info
: Objek yang menyediakan metadata tentang API. Ini mencakuptitle
,version
,description
, dan informasi kontak.servers
: Array objek server, yang mendefinisikan URL dasar untuk API.paths
: Bidang yang paling penting. Objek ini menampung semua endpoint API yang tersedia (paths) dan operasi HTTP (GET, POST, PUT, DELETE, dll.) yang dapat dilakukan padanya.components
: Objek yang menampung sekumpulan objek yang dapat digunakan kembali untuk bagian-bagian spesifikasi yang berbeda. Ini kunci untuk menjaga spesifikasi Anda DRY (Don't Repeat Yourself). Anda dapat mendefinisikanschemas
(model data) yang dapat digunakan kembali,responses
,parameters
,examples
, dan lainnya.
Memetakan OpenAPI ke Objek pyswagger
pyswagger
menyediakan pemetaan yang bersih dari konsep OpenAPI ini ke objek Python. Mari kita jelajahi yang utama yang akan kita gunakan.
Objek sentral dalam pyswagger
adalah App
. Anda dapat menganggap instance App
sebagai akar dokumen OpenAPI Anda.Python
from pyswagger import App
# The root of the specification document
# We initialize it with a version, but it can also load from a URL or file
root_app = App(version='3.0.0')
Setelah Anda memiliki objek App
Anda, Anda dapat mulai mengisi atributnya, yang secara langsung sesuai dengan bidang OpenAPI. pyswagger
menggunakan pola builder, memungkinkan sintaks yang lancar dan mudah dibaca.
Info dan Servers
Bagian info
dan servers
mudah diisi.Python
# Populating the 'info' object
root_app.info.title = "User API"
root_app.info.version = "1.0.0"
root_app.info.description = "A simple API to manage users, used for the pyswagger tutorial."
# Populating the 'servers' array
# You create a Server object and append it
server = root_app.prepare_obj('Server', {'url': 'http://127.0.0.1:5000', 'description': 'Local development server'})
root_app.servers.append(server)
Paths dan Operations
Paths didefinisikan pada objek App
. Anda menambahkan paths baru dan kemudian mendefinisikan operasi (metode HTTP) di dalamnya. Setiap operasi dikonfigurasi dengan detail seperti summary
, description
, parameters
, requestBody
, dan responses
.Python
# Defining a path and an operation
# This doesn't execute anything; it just builds the object structure.
path_item = root_app.define_path('/users')
get_op = path_item.define_op('get')
get_op.summary = "Retrieve a list of all users"
Components: Schemas, Parameters, dan Responses
Kekuatan sebenarnya dari spesifikasi OpenAPI yang terstruktur dengan baik berasal dari komponen yang dapat digunakan kembali. Alih-alih mendefinisikan struktur objek "User" setiap kali muncul dalam respons, Anda mendefinisikannya sekali dalam components/schemas
dan kemudian mereferensikannya menggunakan pointer $ref
. pyswagger
menangani ini dengan elegan.
Schema
: Objek Schema
mendefinisikan model data. Anda dapat menentukan tipenya (object
, string
, integer
) dan propertinya.Python
# Preparing a Schema object for a User
user_schema = root_app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'id': {'type': 'integer', 'format': 'int64'},
'username': {'type': 'string'},
'email': {'type': 'string', 'format': 'email'}
},
'required': ['id', 'username', 'email']
})
# Add it to the reusable components
root_app.components.schemas['User'] = user_schema
Parameter
: Objek Parameter
mendefinisikan satu parameter operasi. Anda menentukan namanya, di mana ia berada (in
: 'path'
, 'query'
, 'header'
, atau 'cookie'
), dan skemanya.Python
# Preparing a Parameter object for a user ID in the path
user_id_param = root_app.prepare_obj('Parameter', {
'name': 'user_id',
'in': 'path',
'description': 'ID of the user to retrieve',
'required': True,
'schema': {'type': 'integer'}
})
Response
: Objek Response
mendefinisikan struktur respons untuk kode status HTTP tertentu. Ini mencakup description
dan content
, yang menentukan jenis media (misalnya, application/json
) dan skemanya.Python
# Preparing a Response object for a 200 OK response returning a single user
# Note the use of '$ref' to point to our reusable User schema
ok_user_response = root_app.prepare_obj('Response', {
'description': 'Successful retrieval of a user',
'content': {
'application/json': {
'schema': {'$ref': '#/components/schemas/User'}
}
}
})
Memahami pemetaan ini adalah kunci untuk membangun spesifikasi Anda. Anda pada dasarnya sedang membangun grafik objek Python yang nantinya akan diserialisasikan oleh pyswagger
menjadi file JSON atau YAML OpenAPI yang valid.
Bagian 3: Membangun API Sederhana dengan Flask
Untuk membuat latihan dokumentasi kita praktis, kita memerlukan API yang sebenarnya untuk didokumentasikan. Kita akan memperluas aplikasi Flask sederhana kita dari Bagian 1 menjadi API REST minimal untuk mengelola daftar pengguna. API ini akan berfungsi sebagai "sumber kebenaran" yang akan kita deskripsikan dengan pyswagger
.
Merancang API "Pengguna" Sederhana 📝
Kita akan mengimplementasikan empat endpoint dasar yang mewakili operasi CRUD (Create, Read, Update, Delete) umum:
GET /users
: Mengambil daftar semua pengguna.POST /users
: Membuat pengguna baru.GET /users/{user_id}
: Mendapatkan satu pengguna berdasarkan ID mereka.DELETE /users/{user_id}
: Menghapus pengguna berdasarkan ID mereka.
Untuk kesederhanaan, kita akan menggunakan kamus Python sederhana sebagai "database" dalam memori kita. Dalam aplikasi dunia nyata, ini akan menjadi koneksi ke database seperti PostgreSQL atau MongoDB.
Mengimplementasikan Endpoint Flask
Mari kita perbarui file app.py
kita untuk menyertakan logika untuk endpoint ini. Ganti konten app.py
dengan yang berikut:Python
# app.py
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
# --- In-Memory Database ---
# A simple dictionary to store our users.
# The key is the user_id (integer), and the value is the user data (dict).
USERS_DB = {
1: {"username": "alice", "email": "alice@example.com"},
2: {"username": "bob", "email": "bob@example.com"},
3: {"username": "charlie", "email": "charlie@example.com"},
}
# A counter to simulate auto-incrementing IDs for new users
LAST_INSERT_ID = 3
# --- API Endpoints ---
@app.route("/users", methods=["GET"])
def get_users():
""" Returns a list of all users. """
# We need to convert the dictionary to a list of user objects, including their IDs.
users_list = []
for user_id, user_data in USERS_DB.items():
user = {'id': user_id}
user.update(user_data)
users_list.append(user)
return jsonify(users_list)
@app.route("/users", methods=["POST"])
def create_user():
""" Creates a new user. """
global LAST_INSERT_ID
if not request.json or 'username' not in request.json or 'email' not in request.json:
abort(400, description="Missing username or email in request body.")
LAST_INSERT_ID += 1
new_user_id = LAST_INSERT_ID
new_user = {
"username": request.json["username"],
"email": request.json["email"],
}
USERS_DB[new_user_id] = new_user
# The response should include the ID of the newly created user
response_user = {'id': new_user_id}
response_user.update(new_user)
return jsonify(response_user), 201
@app.route("/users/<int:user_id>", methods=["GET"])
def get_user(user_id):
""" Returns a single user by their ID. """
if user_id not in USERS_DB:
abort(404, description=f"User with ID {user_id} not found.")
user_data = USERS_DB[user_id]
user = {'id': user_id}
user.update(user_data)
return jsonify(user)
@app.route("/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
""" Deletes a user by their ID. """
if user_id not in USERS_DB:
abort(404, description=f"User with ID {user_id} not found.")
del USERS_DB[user_id]
# A 204 No Content response is standard for successful deletions
return '', 204
if __name__ == "__main__":
app.run(debug=True, port=5000)
Sekarang, jika Anda menjalankan python app.py
lagi, Anda akan memiliki API yang berfungsi penuh (meskipun sederhana). Anda dapat mengujinya dengan curl
atau alat serupa:
- Dapatkan semua pengguna:
curl http://127.0.0.1:5000/users
- Dapatkan pengguna tertentu:
curl http://127.0.0.1:5000/users/1
- Buat pengguna:
curl -X POST -H "Content-Type: application/json" -d '{"username": "david", "email": "david@example.com"}' http://127.0.0.1:5000/users
- Hapus pengguna:
curl -X DELETE http://127.0.0.1:5000/users/3
Dengan API kita yang telah diimplementasikan, kita memiliki target konkret untuk upaya dokumentasi kita. Langkah selanjutnya adalah menggunakan pyswagger
untuk mendeskripsikan setiap endpoint ini secara detail.
Bagian 4: Menghasilkan Spesifikasi OpenAPI Secara Otomatis dengan pyswagger
Ini adalah inti dari tutorial kita. Kita sekarang akan membuat skrip Python terpisah yang mengimpor pyswagger
, mendefinisikan struktur API kita menggunakan model objeknya, dan kemudian menserialisasikan struktur tersebut menjadi file openapi.json
yang lengkap. Pendekatan ini memisahkan pembuatan spesifikasi dari logika aplikasi, yang bisa menjadi pola yang sangat bersih dan mudah dikelola.
Membuat Generator Spesifikasi
Di direktori proyek Anda, buat file baru bernama generate_spec.py
. Skrip ini akan bertanggung jawab untuk membangun dan menyimpan spesifikasi OpenAPI kita.
Membangun Spesifikasi, Langkah demi Langkah
Mari kita bangun skrip generate_spec.py
bagian demi bagian.
1. Impor dan Menginisialisasi App
Pertama, kita perlu mengimpor objek App
dari pyswagger
dan PyYAML
untuk membantu membuang file akhir. Kita akan membuat objek App
akar kita dan mengisi bagian info
dan servers
dasar, persis seperti yang kita bahas di Bagian 2.Python
# generate_spec.py
import json
from pyswagger import App
from pyswagger.contrib.client.requests import Client
# --- 1. Initialize the root App object ---
app = App(version='3.0.0')
# --- 2. Populating the Info & Servers sections ---
app.info.title = "User API"
app.info.version = "1.0.0"
app.info.description = "A simple API to manage users, for the pyswagger tutorial."
server = app.prepare_obj('Server', {
'url': 'http://127.0.0.1:5000',
'description': 'Local development server'
})
app.servers.append(server)
2. Mendefinisikan Komponen yang Dapat Digunakan Kembali (Schemas)
Desain API yang baik menghindari pengulangan. Kita akan mendefinisikan model data User
kita sekali dan menggunakannya kembali. Kita juga akan mendefinisikan skema Error
generik untuk respons kesalahan kita (seperti 404 Not Found).
Tambahkan kode berikut ke generate_spec.py
:Python
# --- 3. Defining Reusable Components (Schemas) ---
# Schema for the Error response
error_schema = app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'code': {'type': 'integer', 'format': 'int32'},
'message': {'type': 'string'}
}
})
app.components.schemas['Error'] = error_schema
# Schema for a single User. Note the properties match our USERS_DB structure.
user_schema = app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'id': {
'type': 'integer',
'description': 'Unique identifier for the user.',
'readOnly': True # The client cannot set this value
},
'username': {
'type': 'string',
'description': 'The user\'s chosen username.'
},
'email': {
'type': 'string',
'description': 'The user\'s email address.',
'format': 'email'
}
},
'required': ['id', 'username', 'email']
})
app.components.schemas['User'] = user_schema
# Schema for creating a user (doesn't include the 'id' field)
new_user_schema = app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'username': {
'type': 'string',
'description': 'The user\'s chosen username.'
},
'email': {
'type': 'string',
'description': 'The user\'s email address.',
'format': 'email'
}
},
'required': ['username', 'email']
})
app.components.schemas['NewUser'] = new_user_schema
3. Mendokumentasikan Endpoint /users
Sekarang kita akan mendefinisikan path /users
dan dua operasinya: GET
dan POST
.
- Untuk
GET
, responsnya adalah array objekUser
. - Untuk
POST
, badan permintaan akan mengharapkan objekNewUser
, dan respons yang berhasil akan menjadi objekUser
tunggal (termasuk ID baru).
<!-- end list -->Python
# --- 4. Documenting the Paths ---
# -- Path: /users --
path_users = app.define_path('/users')
# Operation: GET /users
op_get_users = path_users.define_op('get')
op_get_users.summary = "List all users"
op_get_users.description = "Returns a JSON array of all user objects."
op_get_users.tags.append('Users')
op_get_users.responses.A('200').description = "A list of users."
op_get_users.responses.A('200').content.A('application/json').schema.A(
'array', items={'$ref': '#/components/schemas/User'}
)
# Operation: POST /users
op_post_users = path_users.define_op('post')
op_post_users.summary = "Create a new user"
op_post_users.description = "Adds a new user to the database."
op_post_users.tags.append('Users')
op_post_users.requestBody.description = "User object that needs to be added."
op_post_users.requestBody.required = True
op_post_users.requestBody.content.A('application/json').schema.set_ref('#/components/schemas/NewUser')
op_post_users.responses.A('201').description = "User created successfully."
op_post_users.responses.A('201').content.A('application/json').schema.set_ref('#/components/schemas/User')
op_post_users.responses.A('400').description = "Invalid input provided."
op_post_users.responses.A('400').content.A('application/json').schema.set_ref('#/components/schemas/Error')
Perhatikan penggunaan set_ref
dan A
(yang merupakan singkatan dari "access") untuk sintaks yang lebih ringkas untuk membangun struktur objek bersarang.
4. Mendokumentasikan Endpoint /users/{user_id}
Selanjutnya, kita akan mendokumentasikan path untuk berinteraksi dengan satu pengguna. Path ini mencakup parameter path, {user_id}
.
- Untuk
GET
, kita perlu mendefinisikan parameter path ini. Responsnya adalah satu objekUser
atau kesalahan404
. - Untuk
DELETE
, kita juga memerlukan parameter path. Respons yang berhasil adalah204 No Content
.
<!-- end list -->Python
# -- Path: /users/{user_id} --
path_user_id = app.define_path('/users/{user_id}')
# We can define the parameter once and reuse it for all operations on this path.
user_id_param = app.prepare_obj('Parameter', {
'name': 'user_id',
'in': 'path',
'description': 'ID of the user',
'required': True,
'schema': {'type': 'integer'}
})
path_user_id.parameters.append(user_id_param)
# Operation: GET /users/{user_id}
op_get_user_id = path_user_id.define_op('get')
op_get_user_id.summary = "Find user by ID"
op_get_user_id.description = "Returns a single user."
op_get_user_id.tags.append('Users')
op_get_user_id.responses.A('200').description = "Successful operation."
op_get_user_id.responses.A('200').content.A('application/json').schema.set_ref('#/components/schemas/User')
op_get_user_id.responses.A('404').description = "User not found."
op_get_user_id.responses.A('404').content.A('application/json').schema.set_ref('#/components/schemas/Error')
# Operation: DELETE /users/{user_id}
op_delete_user_id = path_user_id.define_op('delete')
op_delete_user_id.summary = "Deletes a user"
op_delete_user_id.description = "Deletes a single user from the database."
op_delete_user_id.tags.append('Users')
op_delete_user_id.responses.A('204').description = "User deleted successfully."
op_delete_user_id.responses.A('404').description = "User not found."
op_delete_user_id.responses.A('404').content.A('application/json').schema.set_ref('#/components/schemas/Error')
5. Memvalidasi dan Menyimpan Spesifikasi
Akhirnya, langkah yang paling memuaskan. Kita akan meminta pyswagger
untuk memvalidasi grafik objek yang kita bangun terhadap skema OpenAPI 3.0. Jika valid, kita akan membuangnya ke file JSON.
Tambahkan blok kode terakhir ini ke generate_spec.py
:Python
# --- 5. Validate and Save the Specification ---
if __name__ == '__main__':
try:
# Validate the generated specification
app.validate()
print("Specification is valid.")
# Save the specification to a JSON file
with open('openapi.json', 'w') as f:
f.write(app.dump_json(indent=2))
print("Successfully generated openapi.json")
except Exception as e:
print(f"Validation Error: {e}")
File generate_spec.py
Anda sekarang lengkap. Jalankan dari terminal Anda:Bash
python generate_spec.py
Jika semuanya benar, Anda akan melihat output:
Specification is valid.
Successfully generated openapi.json
Anda sekarang akan memiliki file baru, openapi.json
, di direktori proyek Anda. Buka dan jelajahi isinya. Anda akan melihat dokumen OpenAPI 3.0 yang terstruktur dengan sempurna yang menjelaskan API Flask Anda secara rinci.
Bagian 5: Menyajikan Dokumentasi
Memiliki file openapi.json
sangat bagus untuk mesin dan untuk menghasilkan SDK klien, tetapi bagi pengembang manusia, UI interaktif jauh lebih berguna. Di bagian akhir ini, kita akan mengintegrasikan spesifikasi yang kita hasilkan ke dalam aplikasi Flask kita dan menyajikannya menggunakan Swagger UI yang populer.
Mengintegrasikan Spesifikasi ke dalam Flask
Pertama, kita perlu membuat endpoint di aplikasi Flask kita yang menyajikan file openapi.json
. Ini memungkinkan alat dokumentasi untuk mengambil spesifikasi langsung dari API kita yang sedang berjalan.
Ubah app.py
untuk menambahkan rute baru:Python
# app.py
# ... (keep all the existing Flask code) ...
import os
# ... (all the routes like /users, /users/{user_id}, etc.) ...
# --- Serving the OpenAPI Specification and UI ---
@app.route('/api/docs/openapi.json')
def serve_openapi_spec():
""" Serves the generated openapi.json file. """
# This assumes openapi.json is in the same directory as app.py
# In a larger app, you might want a more robust way to find the file
return app.send_static_file('openapi.json')
Agar ini berfungsi, Flask perlu tahu di mana menemukan file statis. Secara default, ia mencari di direktori static
. Mari kita buat satu dan pindahkan file openapi.json
kita ke sana.Bash
mkdir static
mv openapi.json static/
Sekarang, jalankan python app.py
, dan navigasikan ke http://127.0.0.1:5000/api/docs/openapi.json
. Anda akan melihat JSON mentah dari spesifikasi Anda.
Menyajikan UI Interaktif dengan Swagger UI 🎨
Swagger UI adalah kumpulan aset HTML,2 JavaScript, dan CSS yang tidak bergantung pada dependensi yang secara dinamis menghasilkan dokumentasi yang indah dari API yang sesuai dengan OpenAPI. Kita dapat dengan mudah menyajikannya dari aplikasi Flask kita.
Buat Direktori Templates: Flask menggunakan direktori bernama templates
untuk mencari template HTML.Bash
mkdir templates
Buat Template Swagger UI: Di dalam direktori templates
, buat file baru bernama swagger_ui.html
. Tempelkan kode HTML berikut ke dalamnya. Kode ini memuat aset Swagger UI dari CDN publik dan mengonfigurasinya untuk memuat file spesifikasi kita.HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User API - Swagger UI</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui.min.css" >
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui-bundle.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Begin Swagger3 UI call region
const ui = SwaggerUIBundle({
url: "/api/docs/openapi.json", // The URL for our spec
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset4
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
```
Tambahkan Rute Flask: Terakhir, tambahkan rute ke app.py
untuk merender template HTML ini. Anda perlu mengimpor render_template
dari Flask.Python
# At the top of app.py
from flask import Flask, jsonify, request, abort, render_template
# ... (all other routes) ...
@app.route('/api/docs/')
def serve_swagger_ui():
""" Serves the interactive Swagger UI documentation. """
return render_template('swagger_ui.html')
Menyatukan Semuanya
Struktur proyek akhir Anda akan terlihat seperti ini:
pyswagger-tutorial/
├── app.py
├── generate_spec.py
├── requirements.txt
├── static/
│ └── openapi.json
├── templates/
│ └── swagger_ui.html
└── venv/
Sekarang untuk hasil akhirnya. Pastikan aplikasi Flask Anda berjalan (python app.py
). Buka browser web Anda dan navigasikan ke:
http://127.0.0.1:5000/api/docs/
Anda akan disambut dengan halaman dokumentasi yang indah dan interaktif untuk API Anda. Anda dapat memperluas setiap endpoint, melihat skema yang Anda definisikan, dan bahkan menggunakan tombol "Try it out" untuk mengirim permintaan langsung ke aplikasi Flask Anda yang sedang berjalan langsung dari browser.
Kesimpulan
Dalam tutorial ini, kita telah melakukan perjalanan dari direktori kosong hingga API yang sepenuhnya terdokumentasi. Kita berhasil menggunakan pyswagger
untuk secara terprogram membangun spesifikasi OpenAPI 3.0 yang terperinci dengan memetakan model objeknya ke struktur API kita. Kita melihat cara mendefinisikan metadata, server, skema yang dapat digunakan kembali, path, dan operasi dengan parameter dan responsnya.
Dengan memisahkan pembuatan spesifikasi (generate_spec.py
) dari logika aplikasi (app.py
), kita menciptakan alur kerja yang bersih: implementasikan API Anda, lalu jalankan generator untuk menghasilkan dokumentasi. Proses ini, meskipun lebih manual daripada pendekatan berbasis dekorator, menawarkan kontrol dan fleksibilitas yang tak tertandingi, menjadikannya ideal untuk proyek kompleks, basis kode lama, atau ketika standar dokumentasi ketat.
Terakhir, dengan menyajikan spesifikasi yang dihasilkan dan instance Swagger UI, kita menyediakan portal dokumentasi yang rapi, profesional, dan sangat berguna untuk konsumen API kita. Anda sekarang memiliki alat baru yang ampuh dalam gudang pengembangan Python Anda untuk membuat dokumentasi API kelas dunia.
Ingin platform Terintegrasi, All-in-One untuk Tim Developer Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!