| کانال توسعه‌دهندگان |
1.75K subscribers
55 photos
1 video
30 links
⭕️ کانال توسعه‌دهندگان دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
Pydantic یکی از کتابخانه‌های جدی و پراستفاده در Python برای کار با data models و validation است؛ مخصوصاً وقتی از FastAPI، اسکریپت‌های ETL یا سرویس‌های داخلی استفاده می‌شود.

ایده‌اش ساده است: به‌جای if—elseهای تکراری برای چک کردن ورودی‌ها، یک مدل تعریف می‌کنی و Pydantic خودش نوع‌ها را تبدیل و داده را اعتبارسنجی می‌کند ✅

ویژگی‌های مهم:
• تایپ‌محور بر اساس type hints پایتون
• تبدیل خودکار انواع (مثلاً str به int در صورت امکان)
• پیام خطای قابل‌خواندن برای API و لاگ‌ها
• ادغام عالی با FastAPI و ابزارهای async

نمونه استفاده ساده:
from pydantic import BaseModel, ValidationError

class User(BaseModel):
id: int
name: str
is_active: bool = True

try:
user = User(id="1", name="Sara")
print(user.id, type(user.id)) # 1 <class 'int'>
except ValidationError as e:
print(e.json())


برای پروژه‌هایی که ورودی‌شان از API، فرم، Message Queue یا فایل JSON می‌آید، Pydantic کمک می‌کند باگ‌های مربوط به داده را خیلی زودتر شکار کنی 🧪

Docs رسمی:
docs.pydantic.dev
GitHub:
github.com/pydantic/pydantic

امتحانش کن روی یکی از سرویس‌های داخلی‌ات و ببین چقدر validation تمیزتر و قابل‌اعتمادتر می‌شود 🚀

🔖 #Programming #برنامه_نویسی #Python #Pydantic #Validation #FastAPI #Data_Modeling

👤 Developix

💎 Channel: @DevelopixChannel
👍4
اصل Single Responsibility: هر کلاس فقط یک دلیل برای تغییر 💡

یکی از مهم‌ترین اصول SOLID که واقعاً در پروژهٔ روزمره جواب می‌دهد، Single Responsibility Principle (SRP) است:

هر ماژول، کلاس یا فانکشن باید فقط یک مسئولیت داشته باشد.

یعنی چه؟ یعنی اگر فردا قرار باشد این کلاس تغییر کند، فقط یک «دلیل منطقی» برای آن وجود داشته باشد، نه چند دلیل مختلف و نامربوط.

مثال ساده ⬇️

class OrderService:
def create_order(self, data):
# 1) اعتبارسنجی دیتا
# 2) ذخیره در دیتابیس
# 3) ارسال ایمیل تایید
pass


این کلاس ۳ مسئولیت دارد:

• منطق بیزینسی سفارش 🧠
• دسترسی به دیتابیس 💾
• ارسال ایمیل 📧

هر بار که قوانین ایمیل عوض شود، این کلاس باید عوض شود.
هر بار که ساختار دیتابیس عوض شود، باز هم همین کلاس.
این دقیقاً خلاف SRP است و در طول زمان به کد شکننده و پر باگ تبدیل می‌شود.

ری‌فکتور با SRP ✅

class OrderRepository:
def save(self, order):
pass

class EmailService:
def send_order_confirmation(self, order):
pass

class OrderService:
def __init__(self, repo, email_service):
self.repo = repo
self.email_service = email_service

def create_order(self, data):
# منطق سفارش
order = self._build_order(data)
self.repo.save(order)
self.email_service.send_order_confirmation(order)


حالا:

• تغییر دیتابیس فقط OrderRepository را درگیر می‌کند.
• تغییر متن/قوانین ایمیل فقط در EmailService انجام می‌شود.
• خود OrderService روی منطق سفارش تمرکز می‌کند.

چرا این کار در عمل ارزش دارد؟

• تست کردن راحت‌تر می‌شود؛ چون می‌توان EmailService و OrderRepository را mock کرد و فقط منطق سفارش را تست گرفت ✅
• تغییرات بیزینسی، UI یا زیرساخت، بخش‌های جداگانه را لمس می‌کند، نه کل سیستم را 🔧
• خوانایی بالاتر: هر کلاس را که باز می‌کنی، تقریباً می‌توانی با خواندن نامش حدس بزنی چه کاری انجام می‌دهد 👀

نشانه‌های نقض SRP (Code Smell) 🚨

• کلاس‌هایی با نام‌های مبهم مثل Manager، Helper، Util که همه کار می‌کنند.
• فانکشن‌هایی که ۱۰۰+ خط کد دارند و هم validate می‌کنند، هم log، هم call به API.
• هر بار که فیچر جدیدی می‌آید، مجبور می‌شوی همان فایل‌های قدیمی «همه‌فن‌حریف» را باز کنی.

لینک‌های مفید برای مطالعهٔ بیشتر:
Refactoring.Guru - Single Responsibility Principle
Martin Fowler - Single Responsibility Principle

قدم‌های کوچک ری‌فکتور بر اساس SRP، در طول زمان کیفیت کد را به‌طرز عجیبی بالا می‌برد. از فانکشن‌های طولانی و کلاس‌های همه‌کاره شروع و به تدریج مسئولیت‌ها را جدا کنید 🌱

🔖 #Programming #برنامه_نویسی #Clean_Code #SOLID #SRP #Software_Architecture #Refactoring #Python

👤 Developix

💎 Channel: @DevelopixChannel
❤4🔥2
اصل Single Responsibility در عمل 🧩

یکی از مهم‌ترین اصول SOLID که عملاً هر روز سر و کار داریم، Single Responsibility Principle (SRP) است:

«هر کلاس یا ماژول باید فقط یک دلیل برای تغییر داشته باشد.»

این یعنی:

• هر قطعه کد روی یک کار مشخص تمرکز کند.
• وقتی نیاز به تغییر یک رفتار داریم، فقط به یک جای مشخص سر بزنیم.

چرا مهم است؟

• کد قابل فهم‌تر می‌شود.
• Bugها کمتر در جاهای نامربوط نشت می‌کنند.
• تست‌ها ساده‌تر و Refactor کردن کم‌ریسک‌تر می‌شود. ✅

نمونه کد بدون رعایت SRP 😵

این تابع هم ورودی را می‌خواند، هم پردازش می‌کند، هم لاگ می‌گیرد و هم نتیجه را ذخیره می‌کند:

def process_order(request):
# 1) validate input
if not request.get("user_id"):
print("[ERROR] missing user_id")
return

# 2) calculate price
total = 0
for item in request["items"]:
total += item["price"] * item["qty"]

# 3) log result
print(f"[INFO] user={request['user_id']} total={total}")

# 4) save to db (fake)
db["orders"].append({"user": request["user_id"], "total": total})


این تابع حداقل چهار مسئولیت دارد؛ هر تغییر کوچکی (مثلاً فرمت لاگ یا ساختار دیتابیس) باعث تغییر در همین تابع می‌شود.

تقسیم به مسئولیت‌های جدا ✂️

با SRP، مسئولیت‌ها را جدا می‌کنیم:

def validate_request(request):
if not request.get("user_id"):
raise ValueError("missing user_id")


def calculate_total(items):
return sum(i["price"] * i["qty"] for i in items)


def log_order(user_id, total, logger):
logger.info(f"user={user_id} total={total}")


def save_order(user_id, total, repo):
repo.save({"user": user_id, "total": total})


def process_order(request, logger, repo):
validate_request(request)
total = calculate_total(request["items"])
log_order(request["user_id"], total, logger)
save_order(request["user_id"], total, repo)


حالا:

• منطق محاسبه قیمت جداست؛ اگر تخفیف یا Tax اضافه شود، فقط همان بخش را تغییر می‌دهیم.
• تغییر سیستم لاگ یا دیتابیس، منطق دامنه را دست‌کاری نمی‌کند.
• تست کردن calculate_total و validate_request به‌صورت واحد بسیار ساده است. 🧪

نکتهٔ مهم

SRP را افراطی تفسیر نکنید؛ منظور این نیست برای هر خط یک تابع بسازیم. معیار خوب این است:

• وقتی می‌گویید «این کلاس/تابع کارش چیه؟»، بتوانید با یک جملهٔ کوتاه جواب بدهید.

برای مطالعهٔ بیشتر:

• کتاب Clean Code – Robert C. Martin
• توضیح SRP در Refactoring.Guru: refactoring.guru/design-patterns/solid

این اصل به‌ظاهر ساده، اگر واقعاً در هر Pull Request به آن فکر شود، کیفیت بلندمدت کدبیس را عوض می‌کند. 🌱

🔖 #Programming #برنامه_نویسی #SRP #SOLID #clean_code #refactoring #architecture #Python

👤 Developix

💎 Channel: @DevelopixChannel
🔥4
کتابخونهٔ معروف Requests توی Python عملاً استانداردِ کار با HTTP شده؛ به‌جای درگیر شدن با urllib و جزئیات خسته‌کننده، با چند خط کد می‌شه API صدا زد و JSON گرفت و فرستاد. 😉

Requests مشکل «کد شلوغ و پر از boilerplate برای request ساده» رو حل می‌کنه و خوندن/دیباگ‌کردن کدهای مرتبط با شبکه رو خیلی راحت‌تر می‌کنه.

ویژگی‌های مهم:
• سینتکس خیلی خوانا و نزدیک به زبان طبیعی 🧠
• پشتیبانی راحت از headers، query params، timeout، session و cookie
• هندل سادهٔ JSON و status code ها
• مناسب برای کار با REST API، اسکریپت‌های اتوماسیون و crawlerهای سبک

pip install requests

import requests

resp = requests.get("https://api.github.com/repos/psf/requests")
if resp.status_code == 200:
data = resp.json()
print(data["full_name"], data["stargazers_count"])


برای پروژه‌هایی مثل مانیتورینگ سرویس‌ها، نوشتن bot، یا اتصال سریع به سرویس‌های third-party، Requests انتخاب امن و پرکاربردیه. 🤝

Docs رسمی:
requests.readthedocs.io
GitHub:
github.com/psf/requests

امتحانش کن و کم‌کم هر جا اسم HTTP تو Python بیاد، یاد Requests می‌افتی. 🚀

🔖 #Programming #برنامه_نویسی #Python #HTTP #Requests #Web #API

👤 Developix

💎 Channel: @DevelopixChannel
اصل Single Responsibility (SRP) از اصول معروف SOLID می‌گوید:

«هر ماژول، کلاس یا تابع باید فقط یک دلیل برای تغییر داشته باشد.» ✅

یعنی چی؟ یعنی یک کلاس نباید هم منطق کسب‌وکار را انجام دهد، هم لاگ بنویسد، هم با دیتابیس صحبت کند، هم ایمیل بفرستد. این دقیقاً همان جایی است که کد شروع به بو دادن می‌کند (Code Smell) 😅

نمونه‌ی بد: کلاس همه‌کاره
class UserService:
def register(self, user_data):
# validate
if not user_data["email"]:
raise Exception("email required")

# save to db
db.save(user_data)

# send welcome email
email_client.send(user_data["email"], "welcome")

# log
logger.info("user registered")


اینجا UserService چند مسئولیت دارد:

• validation ✅
• ذخیره در دیتابیس 🗄️
• ارسال ایمیل 📧
• logging 📜

تست کردنش سخت می‌شود، تغییر هر بخش روی بقیه اثر می‌گذارد، و هر تغییری ریسک Bug را بالا می‌برد.

بازطراحی با SRP
class UserValidator:
def validate(self, user_data):
if not user_data["email"]:
raise Exception("email required")

class UserRepository:
def save(self, user_data):
db.save(user_data)

class EmailNotifier:
def send_welcome(self, email):
email_client.send(email, "welcome")

class UserService:
def __init__(self, validator, repo, notifier, logger):
self.validator = validator
self.repo = repo
self.notifier = notifier
self.logger = logger

def register(self, user_data):
self.validator.validate(user_data)
self.repo.save(user_data)
self.notifier.send_welcome(user_data["email"])
self.logger.info("user registered")


حالا:

• هر کلاس یک مسئولیت واضح دارد ✔️
• تست واحد برای هر بخش ساده‌تر است ✔️
• تغییر ایمیل یا دیتابیس، UserService را نمی‌شکند ✔️

چند نکته‌ی کاربردی 🔍

• اگر در توضیح یک کلاس مجبورید از «و» زیاد استفاده کنید (این کلاس X و Y و Z انجام می‌دهد)، احتمالاً SRP نقض شده.
• متدهایی که بیش از حد طولانی‌اند و کارهای ناهمگن انجام می‌دهند، نامزد جدی Refactor هستند.
• SRP کمک می‌کند معماری تمیزتر داشته باشید و Design Patternها (مثل Strategy، Repository) را راحت‌تر پیاده کنید.

برای مطالعه‌ی بیشتر می‌توان به Refactoring.Guru - SRP یا فصل‌های ابتدایی کتاب Clean Code سر زد.

اجرای مستمر SRP روی کدهای روزمره، در بلندمدت پروژه‌ را قابل‌تغییرتر، تست‌پذیرتر و کم‌استرس‌تر می‌کند. از همین الان روی یکی از فایل‌های شلوغ پروژه شروع شود و مسئولیت‌ها را جدا کنید ✨

🔖 #Programming #برنامه_نویسی #Clean_Code #SOLID #SRP #Refactoring #Architecture #Design_Principles #Python

👤 Developix

💎 Channel: @DevelopixChannel
🚀 ساخت یک REST API ساده با FastAPI (ولی حرفه‌ای!)

FastAPI این‌قدر سریع و تمیزه که برای ساخت REST APIهای کوچک تا سرویس‌های جدی تولید (Production) عالی جواب می‌ده. توی این پست، بر اساس داک رسمی FastAPI (https://fastapi.tiangolo.com)، یک API واقعی و قابل استفاده برای مدیریت "تسک‌ها" می‌سازیم؛ چیزی شبیه todo-service کوچیک، ولی تمیز و قابل توسعه. 😎

ایده اینه:

• یک API می‌سازیم که لیست تسک‌ها رو بده، تسک جدید بگیره و وضعیتش رو عوض کنه.
• از Pydantic models برای اعتبارسنجی ورودی استفاده می‌کنیم.
• خروجی JSON تمیز و قابل مصرف برای Front-end یا mobile app داریم.

اول با نصب شروع کن:
pip install "fastapi[all]" uvicorn


حالا یک فایل به اسم main.py بساز و این کد رو بذار داخلش:

from typing import List, Optional
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI(title="Tasks API")

class Task(BaseModel):
id: int
title: str
done: bool = False
description: Optional[str] = None

# دیتابیس موقتی در حافظه
TASKS_DB: List[Task] = []

@app.get("/tasks", response_model=List[Task])
async def list_tasks():
return TASKS_DB

@app.post("/tasks", response_model=Task, status_code=201)
async def create_task(task: Task):
for t in TASKS_DB:
if t.id == task.id:
raise HTTPException(status_code=400, detail="Task id already exists")
TASKS_DB.append(task)
return task

@app.patch("/tasks/{task_id}", response_model=Task)
async def mark_done(task_id: int):
for t in TASKS_DB:
if t.id == task_id:
t.done = True
return t
raise HTTPException(status_code=404, detail="Task not found")


اجرا روی لوکال:
uvicorn main:app --reload


بعد از اجرا، دو چیز خیلی کاربردی داری:

1️⃣ خود API روی:
http://127.0.0.1:8000/tasks


2️⃣ داکیومنت خودکار با Swagger UI روی:
http://127.0.0.1:8000/docs


همون‌جا می‌تونی POST /tasks رو تست کنی، JSON بفرستی و خروجی رو ببینی. این همون چیزی‌یه که تو سرویس‌های واقعی برای Front-end، موبایل یا حتی microserviceهای دیگه فرستاده می‌شه.

نکته‌های ریز ولی مهم:

• استفاده از response_model باعث می‌شه خروجی همیشه شکل مشخصی داشته باشه و Pydantic اون رو validate کنه.
• با HTTPException خطاها رو استاندارد و قابل پیش‌بینی برمی‌گردونی.
• چون TASKS_DB فقط تو حافظه‌ست، برای محیط واقعی باید به یک دیتابیس واقعی مثل PostgreSQL وصلش کنی (مثلاً با SQLModel یا SQLAlchemy).

این اسکلت ساده، پایه خیلی از APIهای واقعی‌ه: فقط کافیه endpointها و مدل‌هات رو گسترش بدی. 👨‍💻👩‍💻

امتحانش کن، یک mini todo-service برای خودت بساز و روی پروژه‌های شخصی یا تمرینی‌ات سوارش کن. اگر مفید بود برای بقیه دولوپرها هم بفرست تا از FastAPI لذت ببرن. 😄

🔖 #Programming #برنامه_نویسی #FastAPI #Python #REST_API #Backend #Web

👤 Developix

💎 Channel: @DevelopixChannel
👍3❤1
🧪 استفاده از assert برای گرفتن باگ‌ها، قبل از دیر شدن

خیلی وقت‌ها یک فرض توی کد داریم که "مطمئنیم" همیشه برقرار است؛ مثلا این‌که ورودی خالی نیست یا مقدار نال نمی‌آید. این‌جور جاها assert دوست خوب ماست 😄

با assert می‌شود این فرض‌ها را به شکل چکِ خودکار داخل کد ثبت کرد تا اگر جایی نقض شد، همان‌جا و همان لحظه سرِ اجرا بترکد، نه دو روز بعد توی لاگ‌های مشتری.

یک مثال ساده در Python:
def average(nums: list[float]) -> float:
assert len(nums) > 0, "nums must not be empty"
return sum(nums) / len(nums)

print(average([1, 2, 3])) # 2.0
print(average([])) # AssertionError


نکته مهم 👇
- در Python اگر با فلگ -O اجرا شود، assertها حذف می‌شوند. پس برای validation ورودی کاربر از assert استفاده نمی‌شود؛ فقط برای چک‌کردن منطق داخلی و فرضیات برنامه‌نویس مناسب است.

امروز یکی از فرض‌های مهم کدت را با یک assert ساده محکم‌تر کن و نتیجه‌اش را در باگ‌های آینده ببین 🤝

📚 مرجع: Python Docs - assert statement

🔖 #Programming #برنامه_نویسی #assert #debugging #python #clean_code #defensive_programming

👤 Developix

💎 Channel: @DevelopixChannel
👍3🔥1
گاهی وسط دیباگ سریع، کلی print می‌ریزیم تو کد و بعداً یادمان می‌رود پاکشان کنیم 😅 بهتر است از اول سراغ لاگ ساخت‌یافته (Structured Logging) برویم.

با لاگ، هم سطح اهمیت داریم (info, warning, error)، هم می‌توانیم به‌راحتی فیلتر و جستجو کنیم و هم در محیط‌های Production به‌درد می‌خورد.

مثال ساده در Python 👇
import logging

logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s - %(message)s",
)

logger = logging.getLogger("payment-service")

user_id = 42
amount = 199_000

logger.info("starting payment", extra={"user_id": user_id, "amount": amount})

try:
1 / 0
except ZeroDivisionError:
logger.exception("payment failed")


✅ مزیت‌ها:
• لاگ‌ها قابل فیلتر بر اساس سطح هستند و می‌شود فقط warning/error دید.
• در سرویس‌های Microservice و ابزارهایی مثل ELK یا Grafana Loki خیلی تمیزتر تحلیل می‌شوند.

برای پروژه بعدی، از همان روز اول یک Logger درست و حسابی تنظیم شود تا Debug و Monitoring آینده خیلی راحت‌تر پیش برود 🚀

مرجع: Python logging (Official Docs)

🔖 #Programming #برنامه_نویسی #logging #debugging #best_practices #python #structured_logging

👤 Developix

💎 Channel: @DevelopixChannel
👍2❤1
‏اصل Single Responsibility (SRP)؛ وقتی کلاس‌ همه‌کاره خستگی‌ات می‌کند 😅

یکی از مهم‌ترین اصول SOLID، اصل Single Responsibility است:

هر کلاس یا ماژول باید فقط یک دلیل برای تغییر داشته باشد.

یعنی چی؟ یعنی یک کلاس نباید هم منطق دامنه را نگه دارد، هم log بنویسد، هم با دیتابیس کار کند، هم ایمیل بفرستد. این کلاس‌ها هم سخت تست می‌شوند، هم کوچک‌ترین تغییر، نصف سیستم را می‌ترکاند 🔥


❌ مثال بد: کلاس خدا (God Class)
class OrderService:
def create_order(self, data):
# 1) اعتبارسنجی ورودی
if not data.get("user_id"):
raise Exception("user_id required")

# 2) محاسبه قیمت
total = 0
for item in data["items"]:
total += item["price"] * item["qty"]

# 3) ذخیره در دیتابیس
db.save({"user_id": data["user_id"], "total": total})

# 4) ارسال ایمیل
EmailClient().send(
to=data["email"],
subject="Order created",
body=f"Total = {total}"
)

# 5) لاگ کردن
Logger().info("Order created", extra={"total": total})


این کلاس حداقل ۵ مسئولیت دارد. هر تغییری در validation، ایمیل، لاگ یا ساختار دیتابیس، این کلاس را درگیر می‌کند. تست واحد هم کابوس می‌شود 🤯


✅ بازطراحی با SRP

ایده این است که هر ماژول روی یک چیز متمرکز شود:

class OrderValidator:
def validate(self, data):
if not data.get("user_id"):
raise Exception("user_id required")

class PriceCalculator:
def calculate(self, items):
total = 0
for item in items:
total += item["price"] * item["qty"]
return total

class OrderRepository:
def save(self, user_id, total):
db.save({"user_id": user_id, "total": total})

class OrderNotifier:
def send_order_created(self, email, total):
EmailClient().send(
to=email,
subject="Order created",
body=f"Total = {total}"
)

class OrderService:
def __init__(self, validator, calculator, repo, notifier, logger):
self.validator = validator
self.calculator = calculator
self.repo = repo
self.notifier = notifier
self.logger = logger

def create_order(self, data):
self.validator.validate(data)
total = self.calculator.calculate(data["items"])
self.repo.save(data["user_id"], total)
self.notifier.send_order_created(data["email"], total)
self.logger.info("Order created", extra={"total": total})


حالا هر کلاس یک نقش نسبتاً واضح دارد. تغییر منطق قیمت، ایمیل یا دیتابیس، فقط همان بخش را تحت تاثیر قرار می‌دهد. تست واحد هم راحت‌تر است، چون می‌شود هر جزء را جداگانه mock و تست کرد ✅


چطور در عمل از SRP استفاده شود؟

• وقتی متدی خیلی طولانی می‌شود، معمولاً یعنی چند مسئولیت دارد.
• وقتی کلاس‌ مدام به خاطر انواع تغییرها ویرایش می‌شود، یعنی باید تفکیک شود.
• نام کلاس اگر شبیه "Manager"، "Helper"، "Util" باشد، اغلب بوی نقض SRP می‌دهد 😄

مرجع خوب برای مطالعه عمیق‌تر:
refactoring.guru/design-principles/srp

قدم‌های کوچک در جهت SRP، در طول زمان کد را تمیزتر، قابل‌تست‌تر و قابل‌تغییرتر می‌کند. از ریفکتور کردن کلاس‌های همه‌کاره امروز شروع شود ✨

🔖 #Programming #برنامه_نویسی #SRP #SOLID #Clean_Code #Refactoring #Design_Principles #Python

👤 Developix

💎 Channel: @DevelopixChannel
👍1
ساخت یک REST API ساده با FastAPI 🚀

اگر دنبال راهی سریع و تمیز برای ساختن API هستی، FastAPI یکی از بهترین گزینه‌هاست. روی Python ۳ کار می‌کنه، تایپ‌هینت‌ها رو جدی می‌گیره و همزمان هم داکیومنت اتوماتیک می‌سازه، هم performance خیلی خوبی داره.

سناریو: یه سرویس خیلی ساده «مدیریت تسک‌ها» می‌خوایم، چیزی شبیه TODO، که بعداً راحت بشه روش frontend یا موبایل سوار کرد.

منبع اصلی این آموزش از داکیومنت رسمی FastAPI هست:
https://fastapi.tiangolo.com/tutorial/

✅ ایده کلی

FastAPI روی Starlette و Pydantic ساخته شده. یعنی:

• تعریف مدل داده با Pydantic (مثلاً مدل Task)
• تعریف endpointها با decoratorهای ساده مثل @app.get
• اجرا روی Uvicorn برای performance بالا

این مدل برای ساخت microservice، backend برای SPA، یا API موبایل خیلی practical و واقعی‌ست.

🔧 نصب و راه‌اندازی سریع

۱) ساخت venv (اختیاری ولی پیشنهاد می‌شه)

python -m venv venv
source venv/bin/activate # روی ویندوز: venv\Scripts\activate


۲) نصب FastAPI و Uvicorn:

pip install "fastapi[all]" uvicorn


👨‍💻 پیاده‌سازی یک TODO API کوچک

فایل main.py رو بساز و کد زیر رو داخلش قرار بده:

from typing import List, Optional

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI(title="Todo API")


class Task(BaseModel):
id: int
title: str
done: bool = False
description: Optional[str] = None


fake_db: List[Task] = []


@app.get("/tasks", response_model=List[Task])
async def list_tasks():
return fake_db


@app.post("/tasks", response_model=Task)
async def create_task(task: Task):
for t in fake_db:
if t.id == task.id:
raise HTTPException(status_code=400, detail="Task id already exists")
fake_db.append(task)
return task


@app.get("/tasks/{task_id}", response_model=Task)
async def get_task(task_id: int):
for t in fake_db:
if t.id == task_id:
return t
raise HTTPException(status_code=404, detail="Task not found")


@app.patch("/tasks/{task_id}", response_model=Task)
async def toggle_done(task_id: int):
for t in fake_db:
if t.id == task_id:
t.done = not t.done
return t
raise HTTPException(status_code=404, detail="Task not found")


▶️ اجرای سرور

روی ترمینال:

uvicorn main:app --reload


حالا API روی آدرس زیر در حال اجراست:

http://127.0.0.1:8000


و مستندات خودکار (Swagger UI) اینجاست:

http://127.0.0.1:8000/docs


اونجا می‌شه مستقیم request فرستاد، body داد، response دید و راحت API رو تست کرد. برای تست سریع هم می‌شه از curl یا Postman استفاده کرد.

💡 نکات کاربردی

• بهتره از همون اول type-hintها رو جدی بگیری؛ FastAPI ازشون برای validation و schema استفاده می‌کنه.
• در پروژه واقعی، به‌جای fake_db از دیتابیس (مثل PostgreSQL با SQLAlchemy) استفاده می‌شه، اما همین in-memory مدل فکری رو خوب جا می‌اندازه.
• @app.patch برای update جزئی خیلی به‌دردبخوره؛ مخصوصاً وقتی روی front با formهای تیک‌دار کار می‌کنی.

یک بار این API ساده رو بساز، چند تا درخواست POST و GET بزن و ببین چقدر سریع می‌شه یک backend تمیز بالا آورد. اگر مفید بود، برای بقیه تیم هم بفرست تا برای پروتوتایپ‌های بعدی از FastAPI استفاده کنند. 🚀

🔖 #Programming #برنامه_نویسی #FastAPI #Python #REST_API #Backend #Web #Programming #Tutorial

👤 Developix

💎 Channel: @DevelopixChannel
👍4
خطای موقت شبکه، شکست دائمی نیست 🔁

با کتابخانهٔ Tenacity در پایتون می‌توانی برای عملیات ناموفق، retry تعریف کنی؛ بدون اینکه منطق تلاش مجدد را در هر تابع تکرار کنی.

نکته‌های کاربردی:
• تعیین سقف تلاش و فاصلهٔ بین تلاش‌ها
• پشتیبانی از توابع async
• محدود کردن retry به خطاهای مشخص

نصب:
pip install tenacity


در این نمونه فقط خطاهای شبکه دوباره امتحان می‌شوند؛ حداکثر ۳ تلاش با ۲ ثانیه فاصله:
from urllib.request import urlopen
from urllib.error import URLError
from tenacity import (
retry, stop_after_attempt,
wait_fixed, retry_if_exception_type,
)

@retry(
stop=stop_after_attempt(3),
wait=wait_fixed(2),
retry=retry_if_exception_type(URLError),
reraise=True,
)
def fetch(url):
with urlopen(url, timeout=5) as response:
return response.read()


برای عملیات پرداخت، retry بدون تضمین idempotency خطرناک است؛ از یک درخواست خواندنی شروع کن 🌱

مستندات رسمی

🔖 #Programming #برنامه_نویسی #Python #retry #Tenacity

👤 Developix

💎 Channel: @DevelopixChannel
👍2