It is a simple Flask RESTful web service which is builded with RESTPlus extension. So, app.py file can be used as a template to create a RESTful API that integrates Swagger UI. Here, also, use of this extension and building a RESTful web service from scratch is explained in Turkish.
- Install the required packages if you do not already:
pip install Flask
pip install flask-restplus
- Download the "app.py" file or clone the repository via Git:
git clone https://github.com/furkanmtorun/Flask-RESTPlusAPI.git
- Open your terminal and type the following command:
python app.py
- It's ready to use on
http://127.0.0.1:5000
In the process of development, I have used Python 3. If you use both Python 2 and Python 3, specify your command as "pip3" and "python3" while installing the packages and running.
-
İçerik/Başlıklar:
-
#️⃣ Flask Nedir, RESTFul API Nedir?
-
#️⃣ Flask Kurulumu ve "Merhaba Flask!"
-
#️⃣ RESTPlus eklentisinin kullanımı
-
#️⃣ Kaynaklar / Referanslar
Flask nedir?
Flask web uygulamaları geliştirmenize olanak sağlayan Python temelli bir microframework
tür. Ölçeklenebilir ve sürdürülebilir web uygulamlarını oluşturmaya fırsat vermesi ve çeşitli paket/modüllerini barındıran bir framework olması ile birçok kurum ve kuruluş tarafından kullanılmaktadır. Kurum ve kuruluşların listesi için bu ve şu adresleri ziyaret edebilirsiniz.
RESTFul API nedir?
REST (REpresentational State Transfer) (*Temsili Durum Transferi*)
, HTTP protokolü sayesinde istemci ve sunucu arasında JSON, XML, HTML, TEXT gibi pek çok veri formatı ile uygulamaların haberleşmesini sağlar [1], [2]. REST standartlarına uygun yazılan web servislerine ise RESTful servisler
denir [1], [2].
Bu noktada RESTPlus eklentisinin en önemli özelliği ise API'lar için yaygın şekilde kullanılan, hem dokümantasyon hem de arayüz ihtiyacını fazlasıyla karşılayan Swagger ile entegre çalışmasıdır.
Flask'ın pip üzerinden kurulumu için:
pip install Flask
İlk Flask uygulamamız: "Merhaba Flask!"
Python (.py) uzantılı dosyamızı oluşturduktan hemen sonra Flask kütüphanesini projemize dahil edelim:
from flask import Flask
Hemen sonrasında app = Flask(__name__)
ile Flask objemizi __name__
değişkenin ile beraber oluşturuyor ve ardından bir if koşulu ile mevcut dosyamız doğrudan mı çalıştırılmış yoksa modül olarak bir başka yerden mi çalıştırılmış kontrol ediyoruz. Oluşturduğumuz dosya doğrudan çalışıtırılması durumunda __main__
parametresini alacak ve Flask uygulamamızı debug=True
değişkeni sayesinde hata ayıklamayı aktif hale getirmiş olarak çalıştıracağız.
app = Flask(__name__)
if __name__ == "__main__":
app.run(debug=True)
Şimdi ise hemen basit bir sayfa hazırlayalım. Bu noktada Flask ile statik ve dinamik bağlatıların oluşturulumasının çok kolay olduğunu not etmekte fayda var:
@app.route("/")
def ana_sayfa():
return "Merhaba Flask!"
Buradaki kod bloğunda bulunan @app.route()
ile ilk sayfamızı "/"
dizininde oluşturmayı başardık. Sonrasında bir fonksiyon tanımlayarak, ekrana bir yazıyı basmasını sağladık.
Son olarak dosyanın bulunduğu dizinde komut istemcisinden python app.py
komutunu verelim.
Tebrikler! 127.0.0.1:5000
sayfasından ilk Flask web sayfanıza ulaşabilirsiniz!
Eklentiyi yüklemek adına pip install flask-restplus
komutunu çalıştırabilirsiniz.
Sonrasında eklentiyi (app
'i tanımlamak adına Api'ı, Resource'u) projemize çağıralım:
from flask_restplus import Api, Resource
Şimdi ise uygulamamızı api = Api(app)
ve onun temel özelliklerini (version, title, description)
tanımlayalım:
api = Api(app, version="0.1", title="People API with Flask-RESTPlus", description="A quite simple API to working with personal data")
Hemen sonrasında "peopleCollection_api"
olarak bir isim alanı (namespace)
tanımlayalım:
peopleCollection_api = api.namespace("peopleCollection", description="People Collection Operations")
Burada not edilmesi gereken nokta, oluşturulan her
namespace
Swagger arayüzünde birer başlık olarak gözükecektir. (Ekran görüntüleri "Screenshots" başlığı altındaki ilk görselden anlaşıldığı üzere bu örnek RESTFul servisinde 3 namespace tanımlandı.) Ek olarak, bu namespace için belirlenen URL'de şu şekildedir:127.0.0.1:5000/peopleCollection/
Son olarak, oluşturduğumuz namespace'ler üzerinden tıpkı normal sayfaları hazırlar gibi route
'ları belirteceğiz:
peopleCollection_api.route("/")
Daha sonrasında bir sınıf oluşturup, ilk GET çağrımızı peopleList adındaki basit bir sözlük (dictionary)'ü çıktı veren bir fonksiyon ile hazırlayacağız:
class PeopleCollection(Resource):
def get(self):
return peopleList
Yapılan tüm bu çalışmayı denemek için hemen 127.0.0.1:5000
'e bakalım: Tebrikler!
Model tanımlamak
Modeller, belirli bir format çerçevesinde veri yollamak ya da çağırmak için kullanılmaktadır. Şimdi people
isimli modeli people_model
'a tanımlayalım:
Tabii ki bunun için ilgili veri türlerini tanımlamak adına fields
'ı da projemize dahil etmemiz gerekiyor:
from flask_restplus import Api, Resource, fields
people_model = api.model("people",
{
"id": fields.Integer(description="ID Number", example=123456798, readonly=True),
"name": fields.String(description="Full name", example="Richard Hendricks", required=True, min=5),
"email": fields.String(description="Email Adress", example="richardhendricks@piedpier.com", required=True, min=10),
"github": fields.String(description="Github username", example="richardhendricks"),
"twitter": fields.String(description="Twitter username", example="richardhendricks"),
"country": fields.String(description="Country", example="USA")
}
)
Modelimiz, ana sayfada artık bu şekilde gözükmekte:
Şimdi ise PeopleCollection
isimli (daha önce içerisine get
fonksiyonunu tanımladığımız) sınıfımıza post metodunu içeren fonksiyonunu hazırlayalım ve bu modeli de entegre edelim:
@peopleCollection_api.response(200, "Success")
@peopleCollection_api.response(400, "Bad Request or Invalid Argument")
@peopleCollection_api.expect(people_model)
def post(self):
new_person = api.payload
new_person["id"] = max([temp_id["id"] for temp_id in peopleList]) + 1
peopleList.append(new_person)
return new_person
Burada ilk satırdaki komut ile 200 nolu HTTP Status Code (HTTP Durum Kodları) için bir tanımlama yaptık.
Sonrasında ise yukarıda tanımladığımız "people"
isimli modelimizi post
fonksiyonumuz için tanıttık.
Bu fonksiyonda ise daha önce tanımladığımız sözlüğe (dictionary) gönderilen veri girişinin yapılmasını sağladık.
ID parametresini tanıyan route
Daha öncesinde peopleCollection_api.route("/")
ile peopleList
içerisindeki tüm elementleri (kişileri) "/"
dizininde GET
ile listelemiştik. Şimdi ise kullanıcının ID numarasına göre ilgili kişinin bilgilerini çıktı verdirtelim. Bunun için yapmamız gerekenler ise şu şekilde:
- Kullandığımız
namespace
'in route kısmına("/<int:id>")
integer türündeki ID parametresini alacak şekilde düzenleyelim. - Hemen altında ise
@person_api.doc(params={"id":"ID number of the person"})
hazırladığımız API'ın doğru ve anlaşılır şekilde dokümante edilmesi için bu parametrenin açıklamasını belirtelim. - Devamında ise tekrar GET fonksiyonumuzu bu ID parametresini alacak şekilde hazırlayalım:
def get(self, id):
for person in peopleList:
if person["id"] == id:
return person
else:
return "The person with and ID of {} is not found!".format(id)
- Tebrikler, artık hazır!
Argüman ayrıştırma (Argument parsing)
siteadi.com/api/?page_number=7&per_page=20
şeklinde ek argümanlara (page_number [sayfa_numarası] ve per_page [her_sayfada]) sahip bir sorgudaki değişkenleri ise kolay şekilde ayrıştırabiliriz:
-
Bunun için ilk olarak
flask_restplus
eklentisindenreqparse
'ı da projemize dahil edelim ve yeni bir namespace tanımlayalım:arg_api = api.namespace("argumentParser", description="Argument Parsing Operations")
-
Sonrasında
reqparse
içerisindekiRequestParser
fonksiyonunu tanımlayalım:parser = reqparse.RequestParser()
-
Şimdi ise kullanmak ve ayrıştırmak istediğimiz argümanları belirtelim (tırnak içerisindeki ilk parametre sorgu esnasında talep ettiğimiz değişkenimizin adı olacak):
parser.add_argument("page_number", type=int, default=1, required=False, help="Page number")
parser.add_argument("per_page", type=int, choices=[10, 20, 30, 40, 50], required=False, help="Page number")
Argument Parsing hakkındaki daha fazla teknik detay için orijinal dokümana göz atabilirsiniz.
- Son olarak (yazdığımız koda göre sırasıyla)
namespace
içinroute
'ı belirtelim, ve yeni bir sınıf oluşturup daha öncesindeparser
olarak tanımladığımızRequestParser
fonksiyonunu yeni bir sınıf (argParser) içerisine dahil edip,GET
isteğimizi hazırlayalım. Burada ise argümanları ayrıştırması ve depolaması içinargs
'ı tanımlayalım. Sonrasında dapage_number
veper_page
isimli değişkenlerini argümanlarımızın değerlerine ulaşacak şekilde hazır hale getirelim:
Epey süredir çeşitli amaçlarla kullandığım carbon.now.sh 'ı da burada kullanmak istedim. Eğer yazdığınız -tercihen kısa- kodları tasarımdan ödün vermeksizin paylaşmak isterseniz, carbon.now.sh 'ı deneyebilirsiniz!
- Artık her şey tamam!
-
Yazı dizini içinde belirtilmeyen kaynaklar ve detaylı okumaları içeren bağlantıların listesi: