راهنمایی کامل پایتون و rest api
حجم شگفت انگیزی از داده ها در وب موجود است. بسیاری از سرویس های وب ، مانند YouTube و GitHub ، داده های خود را از طریق رابط برنامه نویسی برنامه (API) در دسترس برنامه های شخص ثالث قرار می دهند. سبک معماری REST یکی از رایج ترین روش های ساخت API است. پایتون برخی از ابزارهای عالی را نه تنها برای دریافت داده از API های REST بلکه برای ساختن API های پایتون REST خود نیز ارائه می دهد.
در این آموزش میآموزید که:
- معماری rest چیست
- چطور با rest api به دادهها دسترسی پیدا میکنید
- چطور با ماژول requests پایتون اطلاعات را از rest api بخوانید
- چطور یک rest api بسازید
- آشنایی چند ابزار مهم برای ساخت rest api در پایتون
با استفاده از Python و REST API ها ، می توانید داده های ارائه شده توسط هر سرویس وب مورد علاقه خود را بازیابی ، تجزیه ، به روز رسانی و دستکاری کنید.
دوره پینشهادی: دوره آموزش پایتون (python)
# معماری Rest چیست؟
REST به معنی انتقال حالت نمایندگی(Representational state transfer) است و یک سبک معماری نرم افزاری است که الگویی برای ارتباطات سرویس گیرنده و سرور در شبکه تعریف می کند. REST مجموعه ای از محدودیت ها را برای معماری نرم افزار برای ارتقاء عملکرد ، مقیاس پذیری ، سادگی و قابلیت اطمینان در سیستم ارائه می دهد.
REST محدودیت های معماری زیر را تعریف می کند:
- Stateless: سرور هیچ گونه وضعیتی را بین درخواست های سرویس گیرنده حفظ نمی کند.
- Client-server: سرویس گیرنده و سرور باید از یکدیگر جدا شوند و به هر یک اجازه دهند به طور مستقل توسعه یابد.
- Cacheable: داده های بازیابی شده از سرور باید توسط سرویس گیرنده یا سرور ذخیره شوند.
- Uniform interface: سرور یک رابط یکنواخت برای دسترسی به منابع بدون تعریف نمایندگی آنها ارائه می دهد.
- Layered system: سرویس گیرنده ممکن است از طریق لایه های دیگر مانند proxy یا load balancer به منابع غیر مستقیم سرور دسترسی پیدا کند.
- Code on demand(اختیاری): سرور ممکن است کدی را که می تواند به سرویس گیرنده منتقل کند، مانند JavaScript برای یک برنامه تک صفحه ای، منتقل کند.
توجه داشته باشید، REST مشخصات نیست بلکه مجموعه ای از دستورالعمل ها در مورد نحوه معماری یک سیستم نرم افزاری متصل به شبکه است.
مقاله پیشنهادی: مستند سازی کد پایتون
# معماری Rest و وب سرویسها
REST web service هرگونه سرویس وب است که به محدودیت های معماری REST پایبند باشد. این وب سرویس ها داده های خود را از طریق API در معرض دید دنیای خارج قرار می دهند. API های REST دسترسی به داده های سرویس وب را از طریق URL های وب عمومی فراهم می کنند.
به عنوان مثال ، در اینجا یکی از URL های API REST GitHub آمده است:
https://api.github.com/users/<username>
این URL به شما امکان می دهد به اطلاعات مربوط به یک کاربر خاص GitHub دسترسی پیدا کنید. با ارسال درخواست HTTP به آدرس اینترنتی خاص و پردازش پاسخ، به داده های یک REST API دسترسی پیدا می کنید.
+ متدهای HTTP
REST APIها به متدهای HTTP مانند GET POST و DELETE گوش می دهند تا بدانند کدام عملیات در منابع سرویس وب انجام شود. منبع، هرگونه داده موجود در سرویس وب است که می توان با درخواست HTTP به REST API دسترسی پیدا کرد و دستکاری کرد. متد HTTP به API می گوید که کدام عمل را روی منبع انجام دهد.
در حالی که تعداد زیادی متد HTTP وجود دارد، پنج متد ذکر شده در زیر بیشترین استفاده را از API های REST دارند:
- GET: برای خواندن اطلاعات موجود
- POST: ایجاد کردن اطلاعات جدید
- PUT: برای بروزرسانی اطلاعات به طور کلی
- PATCH: برای بروزرسانی اطلاعات به طور جزئی
- DELETE: برای حذف اطلاعات موجود
یک برنامه مشتری REST API می تواند از این پنج روش HTTP برای مدیریت وضعیت منابع در سرویس وب استفاده کند.
مقاله پیشنهادی: برنامه نویسی شی گرا چیست؟
+ کدهای وضعیت - status codes
هنگامی که REST API درخواست HTTP را دریافت و پردازش می کند، پاسخ HTTP را برمی گرداند. در این پاسخ یک کد وضعیت HTTP وجود دارد. این کد اطلاعاتی در مورد نتیجه درخواست ارائه می دهد. برنامه ای که درخواست ها را به API ارسال می کند، می تواند کد وضعیت را بررسی کرده و اقدامات را بر اساس نتیجه انجام دهد. این اقدامات می تواند شامل مدیریت خطاها یا نمایش پیام موفقیت به کاربر باشد.
در زیر لیستی از رایج ترین کدهای وضعیتی است که توسط REST API بازگردانده شده است:
- 200-OK: اقدام درخواست شده با موفقیت انجام شد.
- 201-created: اطلاعات جدید ایجاد شد.
- 202-accepted: درخواست دریافت شد اما هنوز هیچ تغییری ایجاد نشده.
- 204-No content: درخواست با موفقیت انجام شد ، اما پاسخ فاقد محتوا است.
- 400-Bad request: درخواست ناقص بود.
- 401-unauthorized: مشتری مجاز به انجام اقدام درخواستی نیست.
- 404-Not found: منبع درخواستی پیدا نشد.
- 415-Unsupported media type: قالب داده درخواست توسط سرور پشتیبانی نمی شود.
- 422-Unprocessable Entity: داده های درخواست به درستی قالب بندی شده بود اما حاوی اطلاعات نامعتبر یا مفقود شده بود.
- 500-Internal server error: هنگام پردازش درخواست، سرور با خطا مواجه شد.
این ده کد وضعیت تنها زیرمجموعه کوچکی از کدهای وضعیت HTTP موجود را نشان می دهد. کدهای وضعیت بر اساس دسته بندی نتایج شماره گذاری می شوند:
- 2xx: عملیات موفق
- 3xx: ریدایرکت
- 4xx: خطای کاربر
- 5xx: خطای سرور
هنگام کار با REST API، کدهای وضعیت HTTP مفید هستند، زیرا اغلب باید بر اساس نتایج درخواست منطق متفاوتی را انجام دهید.
+ نقاط پایانی apiها - api endpoints
REST API مجموعه ای از URL های عمومی را که برنامه های سرویس گیرنده برای دسترسی به منابع یک سرویس وب از آنها استفاده می کنند، نشان می دهد. این URL ها، در زمینه API، نقاط پایانی(endpoints) نامیده می شوند.
برای روشن شدن این موضوع، به جدول زیر نگاهی بیندازید. در این جدول ، نقاط پایانی API را برای یک سیستم CRM فرضی مشاهده خواهید کرد. این نقاط پایانی برای منبع مشتری است که نشان دهنده مشتریان بالقوه در سیستم است:
HTTP method | API endpoint | Description |
---|---|---|
GET |
/customers |
Get a list of customers. |
GET |
/customers/<customer_id> |
Get a single customer. |
POST |
/customers |
Create a new customer. |
PUT |
/customers/<customer_id> |
Update a customer. |
PATCH |
/customers/<customer_id> |
Partially update a customer. |
DELETE |
/customers/<customer_id> |
Delete a customer. |
هر یک از نقاط پایانی بالا عمل متفاوتی را بر اساس روش HTTP انجام می دهد.
توجه خواهید کرد که برخی از نقاط پایانی <customer_id> در انتها دارند. این علامت گذاری بدین معناست که شما باید یک شناسه مشتری عددی به URL اضافه کنید تا به REST API بگویید با چه مشتری می خواهید کار کنید.
نقاط پایانی ذکر شده در بالا تنها یک منبع را در سیستم نشان می دهد. API های REST آماده تولید اغلب ده ها یا حتی صدها نقطه پایانی مختلف برای مدیریت منابع در سرویس وب دارند.
مقاله مرتبط: معرفی 8 ابزار مهم پایتون برای ساخت api
# معماری Rest و پایتون: دریافت اطلاعات
برای نوشتن کدی که با API های REST تعامل دارد، اکثر توسعه دهندگان پایتون به requests مراجعه می کنند. این کتابخانه پیچیدگی های درخواست HTTP را حذف می کند. این یکی از معدود پروژه هایی است که ارزش آن را دارد که گویی بخشی از کتابخانه استاندارد است.
برای شروع استفاده از requests، ابتدا باید آن را نصب کنید. برای نصب می توانید از pip استفاده کنید:
$ python -m pip install requests
اکنون که requests را نصب کرده اید، می توانید شروع به ارسال درخواست های HTTP کنید.
+ متد GET
GET یکی از متداول ترین متدهای HTTP است که هنگام کار با REST API ها از آن استفاده می کنید. این متد به شما امکان می دهد منابع را از یک API مشخص بازیابی کنید. GET یک عملیات فقط خواندنی است، بنابراین نباید از آن برای تغییر منابع موجود استفاده کنید.
برای آزمایش GET و سایر متدهای موجود در این بخش، از سرویسی به نام JSONPlaceholder استفاده می کنید. این سرویس رایگان نقاط پایانی API جعلی را ارائه می دهد که پاسخ هایی را که requests می توانند پردازش کنند ، ارسال می کند.
برای آزمایش این، Python REPL را راه اندازی کرده و دستورات زیر را برای ارسال درخواست GET به نقطه پایانی JSONPlaceholder اجرا کنید:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/1"
>>> response = requests.get(api_url)
>>> response.json()
{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
این کد request.get () را برای ارسال درخواست GET به /todos /1 ، که با آیتم todo با شناسه 1 پاسخ می دهد، فرا می خواند. سپس می توانید .json () را در شیء پاسخ برای مشاهده داده هایی که از آنها باز شده است، فراخوانی کنید.
داده های پاسخ به صورت JSON، ذخیره سازی key-value شبیه به دیکشنری پایتون، قالب بندی شده است. این یک قالب داده بسیار محبوب و قالب مبادله عملا برای اکثر API های REST است.
علاوه بر مشاهده داده های JSON از API ، می توانید موارد دیگری را در مورد پاسخ مشاهده کنید:
>>> response.status_code
200
>>> response.headers["Content-Type"]
'application/json; charset=utf-8'
در اینجا ، برای مشاهده کد وضعیت HTTP ، به answer.status_code دسترسی پیدا می کنید. همچنین می توانید هدرهای HTTP پاسخ را با respond.headers مشاهده کنید. این دیکشنری حاوی فراداده های مربوط به پاسخ است، مانند نوع Content-Type.
+ متد POST
اکنون نگاهی به نحوه استفاده از requests برای ارسال اطلاعات به REST API برای ایجاد منبع جدید بیندازید. شما دوباره از JSONPlaceholder استفاده خواهید کرد ، اما این بار داده های JSON را در درخواست قرار می دهید. در اینجا داده هایی که ارسال می کنید وجود دارد:
{
"userId": 1,
"title": "Buy milk",
"completed": false
}
این JSON حاوی اطلاعات مربوط به یک آیتم جدید است. برای بازگشت به Python REPL ، کد زیر را اجرا کنید تا TODO جدید ایجاد شود:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos"
>>> todo = {"userId": 1, "title": "Buy milk", "completed": False}
>>> response = requests.post(api_url, json=todo)
>>> response.json()
{'userId': 1, 'title': 'Buy milk', 'completed': False, 'id': 201}
>>> response.status_code
201
در اینجا، با requests.post() یک todo جدید ایجاد میکنید.
ابتدا ، یک دیکشنری حاوی اطلاعات مربوط به todo خود را ایجاد کردهاید. سپس این دیکشنری را به آرگومان کلید واژه json را به requests.post () منتقل کردید. وقتی این کار را انجام می دهید، requests.post () به طور خودکار هدر HTTP درخواست (Content-Type) را بر روی application/json تنظیم می کند. همچنین todo را به صورت یک رشته JSON، که به قسمت درخواست اضافه می شود، سریال می کند.
اگر از آرگومان کلمه کلیدی json برای ارائه داده های JSON استفاده نمی کنید، باید Content-Type را متناسب با آن تنظیم کرده و JSON را به صورت دستی سریال کنید. در اینجا یک نسخه معادل کد قبلی وجود دارد:
>>> import requests
>>> import json
>>> api_url = "https://jsonplaceholder.typicode.com/todos"
>>> todo = {"userId": 1, "title": "Buy milk", "completed": False}
>>> headers = {"Content-Type":"application/json"}
>>> response = requests.post(api_url, data=json.dumps(todo), headers=headers)
>>> response.json()
{'userId': 1, 'title': 'Buy milk', 'completed': False, 'id': 201}
>>> response.status_code
201
در این کد، یک دیکشنری هدر اضافه می کنید که حاوی یک سرصفحه Content-Type است که به application/json تنظیم شده است. این به REST API می گوید که شما داده های JSON را با درخواست ارسال می کنید.
سپس requests.post() را صدا میزنید، اما به جای انتقال todo به بحث json، ابتدا json.dumps (todo) را برای سریال سازی آن صدا میزنید. پس از سریال شدن، آن را به آرگومان کلمه کلیدی data منتقل می کنید. آرگومان data به requests می گوید که چه داده هایی را در درخواست لحاظ کنند. شما همچنین دیکشنری هدر را به requests.post() منتقل می کنید تا هدرهای HTTP را به صورت دستی تنظیم کنید.
وقتی به این ترتیب requests.post() را صدا میزنید، همان تأثیر کد قبلی را دارد اما کنترل بیشتری بر درخواست دارید.
هنگامی که API پاسخ می دهد، برای مشاهده پاسخ json کد response.json() را صدا میزنید. JSON شامل یک شناسه ایجاد شده برای کار جدید است. کد وضعیت 201 به شما می گوید که منبع جدیدی ایجاد شده است.
مقاله پیشنهادی: مدیریت حافظه در پایتون
+ متد PUT
فراتر از GET و POST، کتابخانه requests از سایر متدهای HTTP که با REST API استفاده می کنید پشتیبانی می کند. کد زیر یک درخواست PUT برای به روزرسانی یک TODO موجود با داده های جدید ارسال می کند. هرگونه داده ای که با درخواست PUT ارسال می شود، به طور کامل جایگزین مقادیر موجود todo می شود.
شما از همان نقطه پایانی JSONPlaceholder که با GET و POST استفاده کرده اید استفاده خواهید کرد ، اما این بار 10 را به انتهای URL اضافه می کنید. این به REST API می گوید که می خواهید کدام todo را به روز کنید:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/10"
>>> response = requests.get(api_url)
>>> response.json()
{'userId': 1, 'id': 10, 'title': 'illo est ... aut', 'completed': True}
>>> todo = {"userId": 1, "title": "Wash car", "completed": True}
>>> response = requests.put(api_url, json=todo)
>>> response.json()
{'userId': 1, 'title': 'Wash car', 'completed': True, 'id': 10}
>>> response.status_code
200
در اینجا، ابتدا برای مشاهده محتویات todo قبلی، request.get () را فراخوانی میکنید. در مرحله بعد، برای درخواست جایگزینی مقادیر انجام شده فعلی، request.put () را با داده های جدید JSON فراخوانی می کنید. وقتی respond.json () را صدا میزنید، مقادیر جدید را می بینید. درخواست های موفق PUT همیشه 200 را به جای 201 باز می گردانند زیرا شما منبع جدیدی ایجاد نمی کنید بلکه فقط منبع موجود را به روز می کنید.
+ متد PATCH
در مرحله بعد، با استفاده از request.patch () مقدار یک فیلد خاص را در یک TODO موجود تغییر میدهید. PATCH با PUT متفاوت است زیرا منبع موجود را کاملاً جایگزین نمی کند. فقط مقادیر تعیین شده در JSON ارسال شده با درخواست را تغییر می دهد.
از همان مثال قبلی استفاده می کنید تا request.patch () را امتحان کنید. در اینجا مقادیر فعلی آمده است:
{'userId': 1, 'title': 'Wash car', 'completed': True, 'id': 10}
اکنون می توانید title را با مقدار جدیدی به روز کنید:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/10"
>>> todo = {"title": "Mow lawn"}
>>> response = requests.patch(api_url, json=todo)
>>> response.json()
{'userId': 1, 'id': 10, 'title': 'Mow lawn', 'completed': True}
>>> response.status_code
200
وقتی response.json () را صدا میزنید، می بینید که title به Mow lawn به روز شده است.
ویدیو پیشنهادی: ویدیو آموزش کارکردن با json در پایتون
+ متد DELETE
نکته آخر اینکه اگر می خواهید یک منبع را به طور کامل حذف کنید ، از DELETE استفاده کنید. در اینجا کد حذف TODO آمده است:
>>> import requests
>>> api_url = "https://jsonplaceholder.typicode.com/todos/10"
>>> response = requests.delete(api_url)
>>> response.json()
{}
>>> response.status_code
200
با api_url که حاوی شناسه todo است که می خواهید حذف کنید، request.delete را فراخوانی میکنید. با این کار یک درخواست حذف به REST API ارسال می شود، که منبع مطابقت را حذف می کند. پس از حذف منبع، API یک شی JSON خالی را ارسال می کند که نشان می دهد منبع حذف شده است.
کتابخانه requests یک ابزار عالی برای کار با REST API ها و بخشی ضروری از کمربند ابزار پایتون شما است. در بخش بعدی، آنچه را که برای ساختن REST API لازم است، یاد می گیرید.
# معماری Rest و پایتون: ساخت api
طراحی REST API یک موضوع بزرگ با لایه های مختلف است. مانند بیشتر موارد در زمینه فناوری ، طیف گسترده ای از نظرات در مورد بهترین رویکرد برای ایجاد API وجود دارد. در این بخش ، برخی از مراحل توصیه شده را که باید هنگام ساختن API دنبال کنید ، مشاهده خواهید کرد.
+ شناسایی منابع
اولین قدم برای ساختن REST API ، شناسایی منابعی است که API مدیریت خواهد کرد. معمولاً توصیف این منابع به عنوان اسامی جمع، مانند مشتریان، رویدادها یا معاملات است. با شناسایی منابع مختلف در سرویس وب خود، لیستی از اسامی ایجاد می کنید که اطلاعات مختلف کاربران را می تواند در API مدیریت کند.
هنگام انجام این کار ، مطمئن شوید که منابع تودرتو را در نظر بگیرید. به عنوان مثال، مشتریان ممکن است فروش داشته باشند یا رویدادها ممکن است مهمان داشته باشند. ایجاد این سلسله مراتب منابع به شما در تعیین نقاط پایانی API کمک می کند.
ویدیو مرتبط: json چیست
+ مشخص کردن نقاط پایانی
هنگامی که منابع موجود در سرویس وب خود را مشخص کردید ، می خواهید از آنها برای تعریف نقاط پایانی API استفاده کنید. در اینجا چند نقطه پایانی برای یک منبع تراکنش وجود دارد که ممکن است در یک API برای خدمات پردازش پرداخت پیدا کنید:
HTTP method | API endpoint | Description |
---|---|---|
GET |
/transactions |
Get a list of transactions. |
GET |
/transactions/<transaction_id> |
Get a single transaction. |
POST |
/transactions |
Create a new transaction. |
PUT |
/transactions/<transaction_id> |
Update a transaction. |
PATCH |
/transactions/<transaction_id> |
Partially update a transaction. |
DELETE |
/transactions/<transaction_id> |
Delete a transaction. |
این شش نقطه پایانی تمام عملیات مورد نیاز برای ایجاد ، خواندن ، به روز رسانی و حذف تراکنش ها در سرویس وب را پوشش می دهد. هر منبع در سرویس وب شما دارای لیست مشابهی از نقاط پایانی است که بر اساس اعمالی است که کاربر می تواند با API انجام دهد.
اکنون به نمونه ای از نقاط پایانی یک منبع تو در تو نگاه کنید. در اینجا ، نقاط پایانی را برای مهمانانی که در منابع رویدادها قرار گرفته اند مشاهده خواهید کرد:
HTTP method | API endpoint | Description |
---|---|---|
GET |
/events/<event_id>/guests |
Get a list of guests. |
GET |
/events/<event_id>/guests/<guest_id> |
Get a single guest. |
POST |
/events/<event_id>/guests |
Create a new guest. |
PUT |
/events/<event_id>/guests/<guest_id> |
Update a guest. |
PATCH |
/events/<event_id>/guests/<guest_id> |
Partially update a guest. |
DELETE |
/events/<event_id>/guests/<guest_id> |
Delete a guest. |
با استفاده از این نقاط پایانی ، می توانید مهمانان را برای یک رویداد خاص در سیستم مدیریت کنید.
+ مشخص کردن فرمت انتقال داده
دو گزینه محبوب برای قالب بندی داده های سرویس وب ، XML و JSON هستند. به طور سنتی ، XML در API های SOAP بسیار محبوب بود، اما JSON در API های REST محبوبیت بیشتری دارد. برای مقایسه این دو ، نگاهی به منبع کتاب نمونه با فرمت XML و JSON بیندازید.
در اینجا این کتاب به صورت XML فرمت شده است:
<?xml version="1.0" encoding="UTF-8" ?>
<book>
<title>Python Basics</title>
<page_count>635</page_count>
<pub_date>2021-03-16</pub_date>
<authors>
<author>
<name>David Amos</name>
</author>
<author>
<name>Joanna Jablonski</name>
</author>
<author>
<name>Dan Bader</name>
</author>
<author>
<name>Fletcher Heisler</name>
</author>
</authors>
<isbn13>978-1775093329</isbn13>
<genre>Education</genre>
</book>
XML از یک سری عناصر برای کدگذاری داده ها استفاده می کند. هر عنصر دارای یک برچسب باز و بسته است که داده ها بین آنها قرار دارد. عناصر را می توان درون عناصر دیگر لانه کرد. شما می توانید این را در بالا مشاهده کنید ، جایی که چندین برچسب <author> در داخل <authors> قرار دارد.
اکنون ، نگاهی به همان کتاب در JSON بیندازید:
{
"title": "Python Basics",
"page_count": 635,
"pub_date": "2021-03-16",
"authors": [
{"name": "David Amos"},
{"name": "Joanna Jablonski"},
{"name": "Dan Bader"},
{"name": "Fletcher Heisler"}
],
"isbn13": "978-1775093329",
"genre": "Education"
}
JSON داده ها را در جفت های کلید-مقدار شبیه به دیکشنری پایتون ذخیره می کند. مانند XML نیز، JSON از داده های تودرتو در هر سطحی پشتیبانی می کند ، بنابراین می توانید داده های پیچیده را مدل سازی کنید.
نه JSON و نه XML ذاتاً بهتر از دیگری نیستند ، اما در بین توسعه دهندگان REST API ترجیح JSON وجود دارد. این امر به ویژه زمانی صادق است که شما API REST را با یک فریم ورک front-end مانند React یا Vue جفت کنید.
دوره پیشنهادی: دوره آموزش Multi Threading در پایتون
+ طراحی پاسخهای موفقیت
پس از انتخاب یک قالب داده ، مرحله بعدی این است که تصمیم بگیرید چگونه به درخواست های HTTP پاسخ خواهید داد. همه پاسخ های REST API شما باید دارای فرمت مشابه و شامل کد وضعیت HTTP مناسب باشند.
در این بخش ، نمونه ای از پاسخ های HTTP را برای یک API فرضی که فهرست خودروها را مدیریت می کند، مشاهده می کنید. این مثال ها به شما این حس را می دهند که چگونه باید پاسخ های API خود را قالب بندی کنید. برای روشن تر شدن امور ، به جای استفاده از کتابخانه HTTP مانند requests، به درخواست ها و پاسخ های HTTP خام نگاه کنید.
برای شروع کار ، به درخواست GET به /cars نگاه کنید، که لیستی از اتومبیل ها را برمی گرداند:
GET /cars HTTP/1.1
Host: api.example.com
این درخواست HTTP از چهار قسمت تشکیل شده است:
- GET متد HTTP است.
- cars/ نقطه پایانی api است.
- HTTP/1.1 نسخه http است.
- Host: api.example.com هاست api است.
این چهار قسمت تنها چیزی است که شما برای ارسال درخواست GET به /cars نیاز دارید. حالا نگاهی به پاسخ بیندازید. این API از JSON به عنوان قالب مبادله داده استفاده می کند:
HTTP/1.1 200 OK
Content-Type: application/json
...
[
{
"id": 1,
"make": "GMC",
"model": "1500 Club Coupe",
"year": 1998,
"vin": "1D7RV1GTXAS806941",
"color": "Red"
},
{
"id": 2,
"make": "Lamborghini",
"model":"Gallardo",
"year":2006,
"vin":"JN1BY1PR0FM736887",
"color":"Mauve"
},
{
"id": 3,
"make": "Chevrolet",
"model":"Monte Carlo",
"year":1996,
"vin":"1G4HP54K714224234",
"color":"Violet"
}
]
API پاسخی را که حاوی لیستی از خودروها است برمی گرداند. می دانید که پاسخ به دلیل کد وضعیت 200 OK موفق بود. پاسخ همچنین دارای یک سربرگ Content-Type است که روی application/json تنظیم شده است. این به کاربر می گوید که پاسخ را به عنوان JSON تجزیه کند.
مهم است که همیشه سرصفحه صحیح Content-Type را در پاسخ خود تنظیم کنید. اگر JSON ارسال می کنید، Content-Type را بر روی application/json تنظیم کنید. اگر XML است، آن را روی application/xml تنظیم کنید. این سرصفحه به کاربر می گوید که چگونه باید داده ها را تجزیه کند.
همچنین یک کد وضعیت مناسب در پاسخ خود وارد کنید. برای هرگونه درخواست GET موفق، باید 200 OK را برگردانید. این به کاربر می گوید که درخواست او همانطور که انتظار می رفت پردازش شد.
نگاهی به درخواست GET دیگری بیندازید ، این بار برای یک ماشین تک:
GET /cars/1 HTTP/1.1
Host: api.example.com
این درخواست HTTP API مربوط به ماشین را پرس و جو می کند. در اینجا پاسخ این است:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 1,
"make": "GMC",
"model": "1500 Club Coupe",
"year": 1998,
"vin": "1D7RV1GTXAS806941",
"color": "Red"
},
این پاسخ شامل یک شی JSON با داده های خودرو است. از آنجا که این یک شیء واحد است، نیازی نیست که در یک لیست پیچیده شود. مانند آخرین پاسخ ، این کد نیز دارای 200 کد وضعیت OK است.
در مرحله بعد ، درخواست POST را برای افزودن ماشین جدید بررسی کنید:
POST /cars HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"make": "Nissan",
"model": "240SX",
"year": 1994,
"vin": "1N6AD0CU5AC961553",
"color": "Violet"
}
این درخواست POST شامل JSON برای ماشین جدید در درخواست است. هدر Content-Type را بر روی application/json تنظیم می کند تا API نوع محتوای درخواست را بشناسد. API یک ماشین جدید از JSON ایجاد می کند.
HTTP/1.1 201 Created
Content-Type: application/json
{
"id": 4,
"make": "Nissan",
"model": "240SX",
"year": 1994,
"vin": "1N6AD0CU5AC961553",
"color": "Violet"
}
این پاسخ دارای کد وضعیت 201 created است تا به کاربر بگوید که منبع جدیدی ایجاد شده است. مطمئن شوید که از 201 Created به جای 200 OK برای همه درخواست های موفق POST استفاده کنید.
این پاسخ همچنین شامل یک کپی از ماشین جدید با شناسه تولید شده توسط API است. ارسال یک شناسه در پاسخ بسیار مهم است تا کاربر بتواند دوباره منبع را تغییر دهد.
حالا به درخواست PUT نگاهی بیندازید:
PUT /cars/4 HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"make": "Buick",
"model": "Lucerne",
"year": 2006,
"vin": "4T1BF3EK8AU335094",
"color":"Maroon"
}
این درخواست از شناسه درخواست قبلی برای به روز رسانی خودرو با تمام داده های جدید استفاده می کند. به عنوان یادآوری ، PUT همه فیلدهای منبع را با داده های جدید به روز می کند. این هم پاسخ:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 4,
"make": "Buick",
"model": "Lucerne",
"year": 2006,
"vin": "4T1BF3EK8AU335094",
"color":"Maroon"
}
پاسخ شامل یک کپی از خودرو با داده های جدید است. باز هم ، شما همیشه می خواهید منبع کامل را برای یک درخواست PUT ارسال کنید. همین امر در مورد درخواست PATCH نیز صدق می کند:
PATCH /cars/4 HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"vin": "VNKKTUD32FA050307",
"color": "Green"
}
درخواست PATCH فقط بخشی از منبع را به روز می کند. در درخواست بالا ، فیلدهای vin و color با مقادیر جدید به روز می شوند. این هم پاسخ:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 4,
"make": "Buick",
"model": "Lucerne",
"year": 2006,
"vin": "VNKKTUD32FA050307",
"color": "Green"
}
پاسخ شامل یک نسخه کامل از ماشین است. همانطور که می بینید ، فقط قسمت vin و color به روز شده است.
در نهایت ، نگاهی به نحوه پاسخ REST API خود هنگام دریافت درخواست حذف کنید. در اینجا یک درخواست حذف ماشین برای حذف وجود دارد:
DELETE /cars/4 HTTP/1.1
این درخواست حذف به API می گوید ماشین را با شناسه 4 بردارید. این پاسخ است:
HTTP/1.1 204 No Content
این پاسخ فقط شامل کد وضعیت 204 بدون محتوا است. این کد وضعیت به کاربر می گوید که عملیات با موفقیت انجام شد، اما هیچ محتوا در پاسخ بازگردانده نشد. این از زمانی که خودرو حذف شده است منطقی است. هیچ دلیلی برای ارسال نسخه ای از آن در پاسخ وجود ندارد.
وقتی همه چیز طبق برنامه پیش برود ، پاسخ های بالا خوب عمل می کند ، اما اگر مشکلی در درخواست وجود داشته باشد ، چه اتفاقی می افتد؟ در بخش بعدی ، نحوه عملکرد REST API خود در هنگام بروز خطاها را بررسی خواهید کرد.
دوره پیشنهادی: دوره آموزش تست نویسی در پایتون
+ طراحی پاسخهای خطا
همیشه این احتمال وجود دارد که درخواست های REST API شما شکست بخورد. ایده خوبی است که تعریف کنید پاسخ خطا چگونه خواهد بود. این پاسخ ها باید شامل شرح خطا و کد وضعیت مناسب باشد. در این بخش ، چند نمونه را بررسی می کنید.
برای شروع ، به درخواست منبعی که در API وجود ندارد نگاهی بیندازید:
GET /motorcycles HTTP/1.1
Host: api.example.com
در اینجا ، کاربر درخواست GET را به /motorcycles ارسال می کند، که وجود ندارد. API پاسخ زیر را ارسال می کند:
HTTP/1.1 404 Not Found
Content-Type: application/json
...
{
"error": "The requested resource was not found."
}
این پاسخ شامل یک کد وضعیت 404 Not Found است. در کنار این، پاسخ شامل یک شی JSON با پیام خطای توصیفی است. ارائه پیغام خطای توصیفی به کاربر زمینه بیشتری برای خطا می دهد.
حالا وقتی کاربر یک درخواست نامعتبر ارسال می کند ، به پاسخ خطا نگاهی بیندازید:
POST /cars HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"make": "Nissan",
"year": 1994,
"color": "Violet"
این درخواست POST حاوی JSON است ، اما به درستی قالب بندی نشده است. در انتها یک آکولاد (}) از دست رفته است. API قادر به پردازش این داده ها نخواهد بود. پاسخ خطا مشکل را به کاربر می گوید:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "This request was not properly formatted. Please send again."
}
این پاسخ شامل یک پیغام خطای توصیفی به همراه کد وضعیت 400 Bad request، به کاربر می گوید که باید درخواست را برطرف کند.
چندین راه دیگر وجود دارد که می تواند درخواست را اشتباه کند حتی اگر به درستی قالب بندی شده باشد. در این مثال بعدی ، کاربر یک درخواست POST ارسال می کند اما یک نوع رسانه پشتیبانی نشده را شامل می شود:
POST /cars HTTP/1.1
Host: api.example.com
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8" ?>
<car>
<make>Nissan</make>
<model>240SX</model>
<year>1994</year>
<vin>1N6AD0CU5AC961553</vin>
<color>Violet</color>
</car>
در این درخواست ، کاربر XML را ارسال می کند ، اما API فقط JSON را پشتیبانی می کند. API با این پاسخ می دهد:
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/json
{
"error": "The application/xml mediatype is not supported."
}
این پاسخ شامل 415 Unsupported Media Type است تا نشان دهد درخواست POST شامل یک قالب داده است که توسط API پشتیبانی نمی شود. این کد خطا برای داده هایی که دارای قالب اشتباه هستند منطقی است ، اما داده هایی که حتی با فرمت صحیح معتبر نیستند چطور؟
در این مثال بعدی ، کاربر یک درخواست POST ارسال می کند اما داده های خودرو را که با فیلد سایر داده ها مطابقت ندارد ، شامل می شود:
POST /cars HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"make": "Nissan",
"model": "240SX",
"topSpeed": 120
"warrantyLength": 10
}
در این درخواست ، کاربر فیلدهای topSpeed و garantyLength را به JSON اضافه می کند. این فیلدها توسط API پشتیبانی نمی شوند ، بنابراین با پیغام خطا پاسخ می دهد:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": "Request had invalid or missing data."
}
این پاسخ شامل 422 Unprocessable Entity است. این کد وضعیت نشان می دهد که هیچ مشکلی در درخواست وجود نداشته است ، اما داده ها معتبر نیستند. REST API نیاز به اعتبارسنجی داده های ورودی دارد. اگر کاربر داده ها را با درخواست ارسال می کند ، API باید داده ها را تأیید کند و هر گونه خطایی را به کاربر اطلاع دهد.
پاسخ به درخواست ها ، چه موفق و چه اشتباه ، یکی از مهمترین مشاغل REST API است. اگر API شما بصری است و پاسخ های دقیقی ارائه می دهد ، ایجاد برنامه در اطراف سرویس وب شما برای کاربران آسان تر خواهد بود. خوشبختانه ، برخی از چارچوب های وب پایتون پیچیده پردازش درخواست های HTTP و بازگرداندن پاسخ ها را حذف می کنند. در قسمت بعدی به سه گزینه محبوب نگاه می کنید.
# معماری Rest و پایتون: ابزارهای ساخت api
در این بخش ، شما سه چارچوب محبوب برای ایجاد REST API در پایتون را مشاهده خواهید کرد. هر چارچوب دارای مزایا و معایبی است ، بنابراین شما باید ارزیابی کنید که کدام یک برای نیازهای شما مناسب است. برای این منظور ، در بخش های بعدی ، به یک REST API در هر چارچوب نگاه می کنید. همه مثالها برای API مشابهی است که مجموعه ای از کشورها را مدیریت می کند.
هر کشور دارای فیلدهای زیر است:
- name نام کشور است.
- capital پایتخت کشور است.
- area مساحت کشور است.
فیلدهای name, capital, area اطلاعات مربوط به یک کشور خاص را در جایی از جهان ذخیره می کند.
بیشتر اوقات ، داده های ارسال شده از REST API از پایگاه داده می آید. اتصال به پایگاه داده خارج از محدوده این آموزش است. برای مثال های زیر ، داده های خود را در لیست پایتون ذخیره می کنید. استثنا در این مورد چارچوب Django REST است که از پایگاه داده SQLite که Django ایجاد می کند ، اجرا می شود.
برای حفظ ثبات امور ، از countries به عنوان نقطه پایانی اصلی خود برای هر سه چارچوب استفاده خواهید کرد. همچنین از JSON به عنوان فرمت داده خود برای هر سه چارچوب استفاده خواهید کرد.
دوره پیشنهادی: دوره اول آموزش فلسک(Flask)
+ Flask
Flask یک چارچوب کوچک پایتون است که برای ساخت برنامه های وب و API های REST استفاده می شود. Flask یک ستون فقرات محکم برای برنامه های شما فراهم می کند در حالی که بسیاری از انتخاب های طراحی را به عهده شما می گذارد. کار اصلی Flask رسیدگی به درخواست های HTTP و هدایت آنها به فانکشن مناسب در برنامه است.
در زیر یک برنامه کاربردی Flask برای REST API آورده شده است:
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
countries = [
{"id": 1, "name": "Thailand", "capital": "Bangkok", "area": 513120},
{"id": 2, "name": "Australia", "capital": "Canberra", "area": 7617930},
{"id": 3, "name": "Egypt", "capital": "Cairo", "area": 1010408},
]
def _find_next_id():
return max(country["id"] for country in countries) + 1
@app.get("/countries")
def get_countries():
return jsonify(countries)
@app.post("/countries")
def add_country():
if request.is_json:
country = request.get_json()
country["id"] = _find_next_id()
countries.append(country)
return country, 201
return {"error": "Request must be JSON"}, 415
این برنامه نقطه پایانی /countries را برای مدیریت لیست کشورها تعریف می کند. دو نوع درخواست مختلف را برآورده می کند:
- GET /countries لیست از کشورها را برمیگرداند.
- POST /countries یک کشور جدید به لیست اضافه میکند.
می توانید این برنامه را با نصب فلاسک با pip امتحان کنید:
$ python -m pip install flask
پس از نصب فلاسک ، کد را در فایلی به نام app.py ذخیره کنید. برای اجرای این برنامه Flask ، ابتدا باید یک متغیر محیطی به نام FLASK_APP را روی app.py تنظیم کنید. این به Flask می گوید که کدام فایل شامل برنامه شما است.
دستور زیر را در پوشه ای که حاوی app.py است اجرا کنید:
$ export FLASK_APP=app.py
این کد FLASK_APP را در شل فعلی به app.py تنظیم می کند. به صورت اختیاری، می توانید FLASK_ENV را روی development تنظیم کنید، که Flask را در حالت debug قرار می دهد:
$ export FLASK_ENV=development
علاوه بر ارائه پیام های خطای مفید، حالت debug باعث بارگیری مجدد برنامه پس از هر تغییر کد می شود. بدون حالت debug، باید سرور را پس از هر تغییر مجدد راه اندازی کنید.
با همه متغیرهای محیط آماده ، اکنون می توانید سرور توسعه Flask را با فراخوانی flask run راه اندازی کنید:
$ flask run
* Serving Flask app "app.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
با این کار سروری که برنامه را اجرا می کند راه اندازی می شود. مرورگر خود را باز کرده و به http://127.0.0.1:5000/countries بروید و پاسخ زیر را مشاهده خواهید کرد:
[
{
"area": 513120,
"capital": "Bangkok",
"id": 1,
"name": "Thailand"
},
{
"area": 7617930,
"capital": "Canberra",
"id": 2,
"name": "Australia"
},
{
"area": 1010408,
"capital": "Cairo",
"id": 3,
"name": "Egypt"
}
]
این پاسخ JSON شامل سه کشور تعریف شده در ابتدای app.py. به کد زیر نگاه کنید تا نحوه عملکرد آن را ببینید:
@app.get("/countries")
def get_countries():
return jsonify(countries)
این کد از @app.get () ، یک دکوراتور مسیر فلاسک، برای اتصال درخواست های GET به یک تابع در برنامه استفاده می کند. هنگامی که به /countries دسترسی پیدا می کنید، Flask تابع را برای رسیدگی به درخواست HTTP و بازگرداندن پاسخ فرا می خواند.
در کد بالا ، get_countries () کشورها را که یک لیست پایتون است می گیرد و با jsonify () آن را به JSON تبدیل می کند. این JSON در پاسخ بازگردانده می شود.
حالا نگاهی به add_country () بیندازید. این عملکرد درخواست های POST به /countries را مدیریت می کند و به شما امکان می دهد یک کشور جدید به لیست اضافه کنید. از شیء request Flask برای بدست آوردن اطلاعات در مورد درخواست HTTP فعلی استفاده می کند:
@app.post("/countries")
def add_country():
if request.is_json:
country = request.get_json()
country["id"] = _find_next_id()
countries.append(country)
return country, 201
return {"error": "Request must be JSON"}, 415
این تابع عملیات زیر را انجام می دهد:
- با استفاده از request.is_json بررسی کنید که درخواست JSON باشد
- ایجاد نمونه کشوری جدید با request.get_json ()
- یافتن id بعدی و تنظیم آن بر روی کشور
- الحاق کشور جدید به کشورها
- بازگشت کشور در پاسخ به همراه 201 کد وضعیت ایجاد شده
- در صورتی که درخواست JSON نبود ، یک پیغام خطا و 415 Unsupported Media Type
add_country () همچنین _find_next_id () را برای تعیین شناسه برای کشور جدید فراخوانی می کند:
def _find_next_id():
return max(country["id"] for country in countries) + 1
این تابع کمکی از یک عبارت generator برای انتخاب تمام شناسه های کشور و سپس فراخوانی max () بر روی آنها برای بدست آوردن بزرگترین مقدار استفاده می کند. این مقدار را 1 برابر می کند تا شناسه بعدی مورد استفاده را دریافت کنید.
می توانید این نقطه پایانی را در shell با استفاده از ابزار خط فرمان (curl) امتحان کنید، که به شما امکان می دهد درخواست های HTTP را از خط فرمان ارسال کنید. در اینجا ، شما یک کشور جدید را به لیست کشورها اضافه می کنید:
$ curl -i http://127.0.0.1:5000/countries \
-X POST \
-H 'Content-Type: application/json' \
-d '{"name":"Germany", "capital": "Berlin", "area": 357022}'
HTTP/1.0 201 CREATED
Content-Type: application/json
...
{
"area": 357022,
"capital": "Berlin",
"id": 4,
"name": "Germany"
}
این دستور curl گزینه هایی دارد که دانستن آنها مفید است:
- -X متد درخواست HTTP را تعیین می کند.
- -H یک هدر HTTP به درخواست اضافه می کند.
- -d داده های درخواست را تعریف می کند.
با تنظیم این گزینه ها ، curl داده های JSON را در یک درخواست POST با سربرگ Content-Type روی application/json ارسال می کند. REST API 201 CREATED همراه با JSON را برای کشور جدیدی که اضافه کرده اید باز می گرداند.
می توانید از curl برای ارسال درخواست GET به /کشورها برای تأیید اضافه شدن کشور جدید استفاده کنید. اگر در دستور curl از -X استفاده نمی کنید ، به طور پیش فرض درخواست GET را ارسال می کند:
$ curl -i http://127.0.0.1:5000/countries
HTTP/1.0 200 OK
Content-Type: application/json
...
[
{
"area": 513120,
"capital": "Bangkok",
"id": 1,
"name": "Thailand"
},
{
"area": 7617930,
"capital": "Canberra",
"id": 2,
"name": "Australia"
},
{
"area": 1010408,
"capital": "Cairo",
"id": 3,
"name": "Egypt"
},
{
"area": 357022,
"capital": "Berlin",
"id": 4,
"name": "Germany"
}
]
این لیست کاملی از کشورهای سیستم را نشان می دهد که جدیدترین کشور در پایین است.
این فقط یک نمونه از کارهایی است که Flask می تواند انجام دهد. این برنامه کاربردی می تواند گسترش یابد و شامل نقاط پایانی برای سایر متد های HTTP دیگر باشد. Flask همچنین دارای یک اکوسیستم بزرگ از برنامه های افزودنی است که عملکردهای اضافی را برای API های REST مانند ادغام پایگاه داده ، احراز هویت و پردازش پس زمینه ارائه می دهد.
دوره پیشنهادی: دوره اول آموزش جنگو(django)
+ Django rest framework
یکی دیگر از گزینه های محبوب برای ایجاد REST API ها چارچوب Django REST است. چارچوب Django REST یک افزونه جنگو است که قابلیت REST API را بر روی پروژه موجود جنگو اضافه می کند.
برای استفاده از چارچوب Django REST، به یک پروژه جنگو نیاز دارید. اگر قبلاً یکی دارید، می توانید الگوهای موجود در بخش را برای پروژه خود اعمال کنید. در غیر این صورت ، با ما همراه باشید تا یک پروژه جنگو بسازید و در چارچوب Django REST اضافه کنید.
ابتدا Django و djangorestframework را با pip نصب کنید:
$ python -m pip install Django djangorestframework
این Django و djangorestframework را نصب می کند. اکنون می توانید از ابزار django-admin برای ایجاد یک پروژه جدید جنگو استفاده کنید. برای شروع پروژه دستور زیر را اجرا کنید:
$ django-admin startproject countryapi
این دستور یک پوشه جدید در دایرکتوری فعلی شما به نام countryapi ایجاد می کند. در داخل این پوشه همه فایلهایی وجود دارد که برای اجرای پروژه جنگو نیاز دارید. در مرحله بعد ، شما می خواهید یک برنامه جدید جنگو در پروژه خود ایجاد کنید. جنگو عملکرد یک پروژه را به برنامه های کاربردی تقسیم می کند. هر برنامه بخش مشخصی از پروژه را مدیریت می کند.
برای ایجاد برنامه ، دایرکتوری ها را به countryapi تغییر دهید و دستور زیر را اجرا کنید:
$ python manage.py startapp countries
این یک پوشه countries جدید در پروژه شما ایجاد می کند. در داخل این پوشه فایل های اصلی این برنامه وجود دارد.
اکنون که یک برنامه کاربردی برای کار ایجاد کرده اید ، باید در مورد آن به جنگو اطلاع دهید. در کنار پوشه countries که ایجاد کرده اید پوشه دیگری به نام countryapi وجود دارد. این پوشه شامل تنظیمات و تنظیمات مربوط به پروژه شما می باشد.
فایل settings.py را که داخل پوشه countryapi است باز کنید. خطوط زیر را به INSTALLED_APPS اضافه کنید تا به Django درباره برنامه کشورها و چارچوب Django REST اطلاع دهید:
# countryapi/settings.py
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"countries",
]
شما یک خط برای برنامه countries و rest_framework اضافه کرده اید.
شاید برای شما این سوال پیش آمده باشد که چرا باید rest_framework را به لیست برنامه ها اضافه کنید. شما باید آن را اضافه کنید زیرا چارچوب Django REST فقط یک برنامه دیگر جنگو است. افزونه های جنگو برنامه های جنگو هستند که بسته بندی و توزیع شده اند و هرکسی می تواند از آنها استفاده کند.
مرحله بعدی ایجاد یک مدل جنگو برای تعریف فیلدهای داده شما است. در داخل برنامه countries، ماژول model.py را با کد زیر به روز کنید:
# countries/models.py
from django.db import models
class Country(models.Model):
name = models.CharField(max_length=100)
capital = models.CharField(max_length=100)
area = models.IntegerField(help_text="(in square kilometers)")
این کد مدل Country را تعریف می کند. جنگو از این مدل برای ایجاد جدول و ستون های پایگاه داده برای داده های کشور استفاده خواهد کرد.
دستورات زیر را اجرا کنید تا Django پایگاه داده را بر اساس این مدل به روز کند:
$ python manage.py makemigrations
Migrations for 'countries':
countries/migrations/0001_initial.py
- Create model Country
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, countries, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
...
این دستورات از migration جنگو برای ایجاد یک جدول جدید در پایگاه داده استفاده می کند.
این جدول خالی شروع می شود، اما خوب است که داده های اولیه داشته باشید تا بتوانید چارچوب Django REST را آزمایش کنید. برای انجام این کار ، از یک ابزار جنگو برای بارگیری برخی از داده ها در پایگاه داده استفاده می کنید.
داده های JSON زیر را در فایلی به نام country.json کپی و ذخیره کرده و در فهرست کشورها ذخیره کنید:
[
{
"model": "countries.country",
"pk": 1,
"fields": {
"name": "Thailand",
"capital": "Bangkok",
"area": 513120
}
},
{
"model": "countries.country",
"pk": 2,
"fields": {
"name": "Australia",
"capital": "Canberra",
"area": 7617930
}
},
{
"model": "countries.country",
"pk": 3,
"fields": {
"name": "Egypt",
"capital": "Cairo",
"area": 1010408
}
}
]
این JSON شامل ورودی های پایگاه داده برای سه کشور است. برای بارگذاری این داده ها در پایگاه داده ، دستور زیر را فراخوانی کنید:
$ python manage.py loaddata countries.json
Installed 3 object(s) from 1 fixture(s)
این سه ردیف به پایگاه داده اضافه می کند.
با این کار ، برنامه جنگو شما کاملاً تنظیم شده و دارای برخی داده ها است. اکنون می توانید چارچوب Django REST را به پروژه اضافه کنید.
چارچوب Django REST یک مدل Django موجود می گیرد و آن را برای REST API به JSON تبدیل می کند. این کار را با سریال سازی مدل انجام می دهد. یک سریال ساز مدل به چارچوب Django REST می گوید که چگونه یک نمونه مدل را به JSON تبدیل کند و چه داده هایی را باید شامل شود.
شما سریال ساز خود را برای مدل Country از بالا ایجاد می کنید. با ایجاد فایلی به نام serializers.py در داخل برنامه کشورها شروع کنید. پس از انجام این کار ، کد زیر را به serializers.py اضافه کنید:
# countries/serializers.py
from rest_framework import serializers
from .models import Country
class CountrySerializer(serializers.ModelSerializer):
class Meta:
model = Country
fields = ["id", "name", "capital", "area"]
این serializer ، CountrySerializer ، زیر طبقه بندی serializers.ModelSerializer برای تولید خودکار محتوای JSON بر اساس زمینه های مدل کشور. مگر اینکه مشخص شده باشد ، یک زیر کلاس ModelSerializer شامل تمام زمینه های مدل جنگو در JSON خواهد بود. شما می توانید این رفتار را با تنظیم فیلدها در لیستی از داده هایی که می خواهید شامل شوند ، تغییر دهید.
درست مانند جنگو ، چارچوب Django REST از نمایش داده ها برای پرس و جو از داده های پایگاه داده برای نمایش به کاربر استفاده می کند. به جای نوشتن نمای REST API از ابتدا، می توانید کلاس ModelViewSet چارچوب Django REST را که دارای نماهای پیش فرض برای عملیات رایج REST API است ، طبقه بندی کنید.
در اینجا لیستی از اقداماتی است که ModelViewSet ارائه می دهد و روش های HTTP معادل آنها:
HTTP method | Action | Description |
---|---|---|
GET |
.list() |
Get a list of countries. |
GET |
.retrieve() |
Get a single country. |
POST |
.create() |
Create a new country. |
PUT |
.update() |
Update a country. |
PATCH |
.partial_update() |
Partially update a country. |
DELETE |
.destroy() |
Delete a country. |
همانطور که می بینید ، این اقدامات مطابق روشهای استاندارد HTTP است که در REST API انتظار دارید. می توانید این اقدامات را در زیر کلاس خود لغو کنید یا بر اساس الزامات API خود اقدامات اضافی اضافه کنید.
در کد زیر کلاس ModelViewSet به نام CountryViewSet آمده است. این کلاس نماهای مورد نیاز برای مدیریت داده های کشور را ایجاد می کند. کد زیر را به views.py در برنامه کشورها اضافه کنید:
# countries/views.py
from rest_framework import viewsets
from .models import Country
from .serializers import CountrySerializer
class CountryViewSet(viewsets.ModelViewSet):
serializer_class = CountrySerializer
queryset = Country.objects.all()
در این کلاس ، serializer_class روی CountrySerializer و queryset روی Country.objects.all () تنظیم شده است. این به چارچوب Django REST می گوید که از کدام سریال ساز استفاده کند و چگونه از پایگاه داده برای این مجموعه از نماهای خاص پرس و جو کند.
هنگامی که views ایجاد می شوند ، باید در URL ها یا نقاط پایانی مناسب ترسیم شوند. برای انجام این کار ، چارچوب Django REST یک DefaultRouter ارائه می دهد که به طور خودکار آدرس های URL برای ModelViewSet ایجاد می کند.
یک فایل urls.py در برنامه کشورها ایجاد کنید و کد زیر را به فایل اضافه کنید:
# countries/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import CountryViewSet
router = DefaultRouter()
router.register(r"countries", CountryViewSet)
urlpatterns = [
path("", include(router.urls))
]
این کد یک DefaultRouter ایجاد می کند و CountryViewSet را در زیر آدرس کشورها ثبت می کند. با این کار همه نشانی های اینترنتی CountryViewSet در زیر /country /قرار می گیرد.
در نهایت ، شما باید فایل urls.py پروژه را به روز کنید تا همه نشانی های اینترنتی کشور را در پروژه قرار دهید. فایل urls.py را در داخل پوشه countryapi با کد زیر به روز کنید:
# countryapi/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("countries.urls")),
]
با این کار همه نشانی های اینترنتی را در زیر /country /قرار می دهید. اکنون آماده هستید که API REST خود را که توسط جنگو پشتیبانی می شود امتحان کنید. برای راه اندازی سرور توسعه جنگو ، دستور زیر را در فهرست root countryapi اجرا کنید:
$ python manage.py runserver
سرور توسعه در حال اجرا است. پیش بروید و یک درخواست GET به / countries / ارسال کنید تا لیستی از تمام کشورهای پروژه جنگو دریافت کنید:
$ curl -i http://127.0.0.1:8000/countries/ -w '\n'
HTTP/1.1 200 OK
...
[
{
"id": 1,
"name":"Thailand",
"capital":"Bangkok",
"area":513120
},
{
"id": 2,
"name":"Australia",
"capital":"Canberra",
"area":7617930
},
{
"id": 3,
"name":"Egypt",
"capital":"Cairo",
"area":1010408
}
]
چارچوب Django REST پاسخ JSON را با سه کشوری که قبلاً اضافه کرده اید ارسال می کند. پاسخ بالا برای خوانایی قالب بندی شده است ، بنابراین پاسخ شما متفاوت خواهد بود.
DefaultRouter که در کشورها ایجاد کردید/urls.py آدرس های درخواست را برای تمام نقاط پایانی API استاندارد ارائه می دهد:
- GET /countries/
- <GET /countries/<country_id/
- POST /countries/
- <PUT /countries/<country_id/
- <PATCH /countries/<country_id/
- <DELETE /countries/<country_id/
می توانید چند نقطه پایانی دیگر را در زیر امتحان کنید. ارسال یک درخواست POST به / countries / برای ایجاد یک کشور جدید در پروژه جنگو خود:
$ curl -i http://127.0.0.1:8000/countries/ \
-X POST \
-H 'Content-Type: application/json' \
-d '{"name":"Germany", "capital": "Berlin", "area": 357022}' \
-w '\n'
HTTP/1.1 201 Created
...
{
"id":4,
"name":"Germany",
"capital":"Berlin",
"area":357022
}
با ایجاد JSON که درخواست را ارسال کرده اید ، یک کشور جدید ایجاد می شود. چارچوب Django REST کد وضعیت ایجاد شده 201 و کشور جدید را برمی گرداند.
با ارسال درخواست به GET/country/<country_id>/با شناسه موجود ، می توانید یک کشور موجود را مشاهده کنید. برای دریافت اولین کشور دستور زیر را اجرا کنید:
$ curl -i http://127.0.0.1:8000/countries/1/ -w '\n'
HTTP/1.1 200 OK
...
{
"id":1,
"name":"Thailand",
"capital":"Bangkok",
"area":513120
}
پاسخ حاوی اطلاعات مربوط به کشور اول است. این مثالها فقط درخواست های GET و POST را پوشش می دادند. با خیال راحت درخواست های PUT ، PATCH و DELETE را امتحان کنید تا ببینید چگونه می توانید مدل خود را به طور کامل از REST API مدیریت کنید.
همانطور که مشاهده کردید ، چارچوب Django REST یک گزینه عالی برای ایجاد API های REST است ، به خصوص اگر پروژه Django موجود دارید و می خواهید یک API اضافه کنید.
دوره پیشنهادی: دوره آموزش FastAPI
+ FastApi
FastAPI یک چارچوب وب پایتون است که برای ایجاد API بهینه شده است. از python type hint پایتون استفاده می کند و پشتیبانی داخلی برای عملیات async دارد. FastAPI در بالای Starlette و Pydantic ساخته شده است و بسیار کارآمد است.
در زیر نمونه ای از REST API ساخته شده با FastAPI است:
# app.py
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
def _find_next_id():
return max(country.country_id for country in countries) + 1
class Country(BaseModel):
country_id: int = Field(default_factory=_find_next_id, alias="id")
name: str
capital: str
area: int
countries = [
Country(id=1, name="Thailand", capital="Bangkok", area=513120),
Country(id=2, name="Australia", capital="Canberra", area=7617930),
Country(id=3, name="Egypt", capital="Cairo", area=1010408),
]
@app.get("/countries")
async def get_countries():
return countries
@app.post("/countries", status_code=201)
async def add_country(country: Country):
countries.append(country)
return country
این برنامه از ویژگی های FastAPI برای ایجاد یک API REST برای داده های کشور مشابهی که در نمونه های دیگر مشاهده کرده اید ، استفاده می کند.
می توانید این برنامه را با نصب fastapi با pip امتحان کنید:
$ python -m pip install fastapi
همچنین باید uvicorn [standard] را نصب کنید ، سروری که می تواند برنامه های FastAPI را اجرا کند:
$ python -m pip install uvicorn[standard]
اگر هم fastapi و هم uvicorn را نصب کرده اید ، کد بالا را در فایلی به نام app.py ذخیره کنید. برای راه اندازی یک سرور توسعه دستور زیر را اجرا کنید:
$ uvicorn app:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
سرور در حال اجرا است. مرورگری را باز کرده و به آدرس http://127.0.0.1:8000/countries بروید. پاسخ FastAPI را با این می بینید:
[
{
"id": 1,
"name":"Thailand",
"capital":"Bangkok",
"area":513120
},
{
"id": 2,
"name":"Australia",
"capital":"Canberra",
"area":7617930
},
{
"id": 3,
"name":"Egypt",
"capital":"Cairo",
"area":1010408
}
]
FastAPI با یک آرایه JSON حاوی لیستی از کشورها پاسخ می دهد. همچنین می توانید یک کشور جدید با ارسال درخواست POST به /countries اضافه کنید:
$ curl -i http://127.0.0.1:8000/countries \
-X POST \
-H 'Content-Type: application/json' \
-d '{"name":"Germany", "capital": "Berlin", "area": 357022}' \
-w '\n'
HTTP/1.1 201 Created
content-type: application/json
...
{"id":4,"name":"Germany","capital":"Berlin","area": 357022}
شما یک کشور جدید اضافه کردید. می توانید این را با GET /countries تأیید کنید:
$ curl -i http://127.0.0.1:8000/countries -w '\n'
HTTP/1.1 200 OK
content-type: application/json
...
[
{
"id":1,
"name":"Thailand",
"capital":"Bangkok",
"area":513120,
},
{
"id":2,
"name":"Australia",
"capital":"Canberra",
"area":7617930
},
{
"id":3,
"name":"Egypt",
"capital":"Cairo",
"area":1010408
},
{
"id":4,
"name": "Germany",
"capital": "Berlin",
"area": 357022
}
]
FastAPI یک لیست JSON شامل کشور جدیدی را که به تازگی اضافه کرده اید برمی گرداند.
متوجه خواهید شد که برنامه FastAPI شبیه برنامه Flask است. مانند Flask ،فریمورک FastAPI دارای مجموعه ای از ویژگی های متمرکز است. سعی نمی کند همه جنبه های توسعه برنامه وب را مدیریت کند. این برنامه برای ایجاد API با ویژگی های مدرن پایتون طراحی شده است.
اگر به بالای app.py نگاه کنید، یک کلاس به نام Country را مشاهده می کنید که BaseModel را گسترش می دهد. کلاس Country ساختار داده ها را در REST API شرح می دهد:
class Country(BaseModel):
country_id: int = Field(default_factory=_find_next_id, alias="id")
name: str
capital: str
area: int
این نمونه ای از مدل Pydantic است. مدل های Pydantic برخی ویژگی های مفید را در FastAPI ارائه می دهند. آنها از type annotations پایتون برای اعمال نوع داده برای هر فیلد در کلاس استفاده می کنند. این به FastAPI اجازه می دهد تا به طور خودکار JSON ، با انواع داده های صحیح ، برای نقاط پایانی API تولید کند. همچنین به FastAPI اجازه می دهد تا JSON ورودی را تأیید کند.
برجسته کردن خط اول مفید است زیرا موارد زیادی در آنجا در حال انجام است:
country_id: int = Field(default_factory=_find_next_id, alias="id")
در این خط ، country_id را مشاهده می کنید که یک عدد صحیح برای شناسه کشور ذخیره می کند. از تابع Field از Pydantic برای تغییر رفتار country_id استفاده می کند. در این مثال ، شما فیلد کلید واژه های default_factory و alias را از فیلد عبور می دهید.
اولین آرگومان، default_factory ، روی _find_next_id () تنظیم شده است. این آرگومان یک تابع را مشخص می کند که هر زمان یک کشور جدید ایجاد می شود اجرا شود. مقدار بازگشتی به country_id اختصاص داده می شود.
آرگومان دوم با alias روی id تنظیم شده است. این به FastAPI می گوید که کلید "id" را به جای "country_id" در JSON خروجی دهد:
{
"id":1,
"name":"Thailand",
"capital":"Bangkok",
"area":513120,
},
این alias همچنین به این معنی است که هنگام ایجاد یک کشور جدید می توانید از id استفاده کنید. این را می توانید در لیست کشورها مشاهده کنید:
countries = [
Country(id=1, name="Thailand", capital="Bangkok", area=513120),
Country(id=2, name="Australia", capital="Canberra", area=7617930),
Country(id=3, name="Egypt", capital="Cairo", area=1010408),
]
این list شامل سه مورد Country برای کشورهای اولیه در API است. مدل های Pydantic برخی ویژگی های عالی را ارائه می دهند و به FastAPI اجازه می دهد تا داده های JSON را به راحتی پردازش کند.
اکنون نگاهی به دو عملکرد API در این برنامه بیندازید. اولین مورد، get_countries () ، لیستی از کشورها برای درخواست های GET را به /countries باز می گرداند:
@app.get("/countries")
async def get_countries():
return countries
FastAPI به طور خودکار JSON را بر اساس فیلدهای موجود در مدل Pydantic ایجاد می کند و نوع داده JSON مناسب را از Python type hints پایتون تنظیم می کند.
مدل Pydantic همچنین هنگامی که درخواست POST به /countries می دهید ، مزیتی را ارائه می دهد. در تابع API دوم در زیر می بینید که کشور پارامتر دارای annotation نوع Country است:
@app.post("/countries", status_code=201)
async def add_country(country: Country):
countries.append(country)
return country
این نوع annotation به FastAPI می گوید که JSON ورودی را در برابر Country معتبر کند. اگر مطابقت ندارد، FastAPI خطا را برمی گرداند. می توانید با درخواست با JSON که با مدل Pydantic مطابقت ندارد ، این کار را امتحان کنید:
$ curl -i http://127.0.0.1:8000/countries \
-X POST \
-H 'Content-Type: application/json' \
-d '{"name":"Germany", "capital": "Berlin"}' \
-w '\n'
HTTP/1.1 422 Unprocessable Entity
content-type: application/json
...
{
"detail": [
{
"loc":["body","area"],
"msg":"field required",
"type":"value_error.missing"
}
]
}
در JSON در این درخواست مقداری برای area وجود نداشت، بنابراین FastAPI پاسخی را با کد وضعیت 422 Unprocessable Entity و همچنین جزئیات مربوط به خطا بازگرداند. این تأیید توسط مدل Pydantic امکان پذیر شده است.
FastAPI با عملکرد بالا و ویژگی های مدرن مانند عملکردهای همگام سازی و مستندسازی خودکار ، ارزش آن را دارد که برای REST API بعدی خود در نظر بگیرید.
# نتیجه گیری
REST API ها همه جا هستند. دانستن نحوه استفاده از پایتون برای مصرف و ساخت API به شما امکان می دهد با حجم وسیعی از داده هایی که سرویس های وب ارائه می دهند کار کنید.
با استفاده از مهارت های جدید Python REST API ، می توانید نه تنها با سرویس های وب تعامل داشته باشید بلکه REST API ها را برای برنامه های خود بسازید. این ابزارها راه را برای طیف گسترده ای از برنامه ها و خدمات جالب و مبتنی بر داده باز می کنند.