Создание веб-сервисов на Python: обзор фреймворков и практические примеры
Основные фреймворки для создания веб-сервисов на Python
Как создать быстрый и документированный API на FastAPI?
FastAPI является современным и эффективным решением для разработки веб-сервисов на Python. Он поддерживает асинхронность, автоматическую генерацию документации OpenAPI и валидацию данных через Pydantic. Ниже приведен пример минимального API.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.post("/items/")
def create_item(item: Item):
return {"item_name": item.name, "item_price": item.price}Html css js python (интеграция python с html, css, javascript)
Для запуска используйте команду uvicorn main:app --reload. Документация доступна по адресу /docs.
Проблема: при импорте FastAPI может возникнуть ошибка ModuleNotFoundError. Решение: убедитесь, что пакеты установлены: pip install fastapi uvicorn.
Типичная ошибка: забыть добавить --reload для автоматической перезагрузки. В результате изменения кода не применяются до перезапуска сервера.
Как создать простое веб-приложение на Flask?
Flask - легковесный микрофреймворк, идеальный для небольших сервисов или прототипов. Пример простого REST эндпоинта.
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/hello', methods=['GET'])
def hello():
name = request.args.get('name', 'World')
return jsonify({"message": f"Hello, {name}!"})
if __name__ == '__main__':
app.run(debug=True)создание сайтов python django (создание веб-сайтов на django с использованием python)
Для запуска сохраните файл как app.py и выполните python app.py. Сервер будет доступен на http://127.0.0.1:5000.
Проблема: если переменная окружения FLASK_APP не установлена, Flask может не найти приложение. Решение: задать export FLASK_APP=app.py (для Linux/macOS) или set FLASK_APP=app.py (Windows) или использовать запуск через python app.py.
Ошибка: при использовании request.args без проверки наличия ключа может возникнуть KeyError. Лучше использовать request.args.get('name', 'World').
Как создать полноценный REST API с Django REST Framework?
Django REST Framework (DRF) предоставляет мощные инструменты для построения API с аутентификацией, сериализаторами и встроенной документацией. Но требует больше начальной настройки.
# settings.py
INSTALLED_APPS = [
'rest_framework',
'myapp',
]
# serializers.py
from rest_framework import serializers
from myapp.models import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ['id', 'name', 'price']
# views.py
from rest_framework import viewsets
from myapp.models import Item
from .serializers import ItemSerializer
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
# urls.py
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from myapp.views import ItemViewSet
router = DefaultRouter()
router.register(r'items', ItemViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
Python web django (web-фреймворк django)
После настройки запустите сервер python manage.py runserver. API эндпоинты будут доступны по адресу /api/items/.
Проблема: если не выполнить миграции (python manage.py migrate), модель не будет создана в базе данных. Решение: всегда выполнять миграции перед запуском.
Ошибка: при неправильной настройке сериализаторов могут возникать ошибки валидации. Проверьте, что поля модели соответствуют типам.
Как создать асинхронный веб-сервис на aiohttp?
aiohttp - асинхронный фреймворк, подходящий для высоконагруженных I/O операций. Пример простого HTTP сервера.
from aiohttp import web
async def handle(request):
name = request.query.get('name', 'World')
return web.json_response({"message": f"Hello, {name}!"})
app = web.Application()
app.router.add_get('/hello', handle)
if __name__ == '__main__':
web.run_app(app)Запуск: python app.py. Приложение будет работать на http://0.0.0.0:8080.
Проблема: если не использовать async для обработчиков, aiohttp будет работать синхронно, теряя преимущества асинхронности. Решение: все handler-ы должны быть корутинами.
Типичная ошибка: при обращении к внешним ресурсам (например, база данных) без асинхронного драйвера будет блокировка. Используйте asyncpg для PostgreSQL или aiomysql.
Расширенные примеры и нестандартные сценарии
FastAPI: работа с базой данных через SQLAlchemy и асинхронность
Пример подключения к PostgreSQL с использованием асинхронного SQLAlchemy. Модель и эндпоинты для CRUD операций.
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, sessionmaker
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, Float, select
from pydantic import BaseModel
DATABASE_URL = "postgresql+asyncpg://user:pass@localhost/dbname"
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()
class ItemModel(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50))
price = Column(Float)
class ItemCreate(BaseModel):
name: str
price: float
async def get_db():
async with AsyncSessionLocal() as session:
yield session
app = FastAPI()
@app.on_event("startup")
async def startup():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
@app.post("/items/", response_model=ItemCreate)
async def create_item(item: ItemCreate, db: AsyncSession = Depends(get_db)):
new_item = ItemModel(name=item.name, price=item.price)
db.add(new_item)
await db.commit()
await db.refresh(new_item)
return new_item
@app.get("/items/")
async def read_items(db: AsyncSession = Depends(get_db)):
result = await db.execute(select(ItemModel))
items = result.scalars().all()
return itemsРезультат: при отправке POST запроса с телом {"name": "laptop", "price": 999.99} сервер вернёт созданный объект. GET запрос вернёт список всех товаров.
POST /items/ -> 201
{
"name": "laptop",
"price": 999.99
}
GET /items/ -> 200
[
{
"id": 1,
"name": "laptop",
"price": 999.99
}
]FastAPI: валидация данных с использованием Pydantic и кастомные валидаторы
Добавление дополнительных проверок, например, проверка уникальности имени.
from pydantic import BaseModel, validator
from typing import Optional
class ItemCreate(BaseModel):
name: str
price: float = None
@validator('name')
def name_must_be_unique(cls, v):
# Здесь может быть запрос к БД для проверки уникальности
if v == "existing_name":
raise ValueError('Item with this name already exists')
return v
@validator('price')
def price_must_be_positive(cls, v):
if v is not None and v <= 0:
raise ValueError('Price must be positive')
return vПри попытке создать элемент с существующим именем будет выброшена ошибка валидации 422.
Flask: интеграция с базой данных SQLite и ORM SQLAlchemy
Пример простого приложения с поддержкой CRUD.
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///items.db'
db = SQLAlchemy(app)
class Item(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
price = db.Column(db.Float, nullable=False)
def serialize(self):
return {'id': self.id, 'name': self.name, 'price': self.price}
@app.route('/items', methods=['GET'])
def get_items():
items = Item.query.all()
return jsonify([item.serialize() for item in items])
@app.route('/items', methods=['POST'])
def create_item():
data = request.json
new_item = Item(name=data['name'], price=data['price'])
db.session.add(new_item)
db.session.commit()
return jsonify(new_item.serialize()), 201
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)Результат: при запуске создаётся таблица items. POST запрос добавляет запись.
aiohttp: middleware для логирования и обработки ошибок
from aiohttp import web
import logging
logging.basicConfig(level=logging.INFO)
@web.middleware
async def error_middleware(request, handler):
try:
response = await handler(request)
return response
except web.HTTPException as ex:
raise
except Exception as ex:
logging.error(f"Unhandled error: {ex}")
return web.json_response({'error': 'Internal server error'}, status=500)
async def handle(request):
return web.json_response({'message': 'Success'})
app = web.Application(middlewares=[error_middleware])
app.router.add_get('/', handle)
web.run_app(app)Результат: если в обработчике возникнет исключение, middleware вернёт JSON с ошибкой 500.
Django REST Framework: пагинация и фильтрация
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
# views.py
from rest_framework import generics
from myapp.models import Item
from .serializers import ItemSerializer
from django_filters.rest_framework import DjangoFilterBackend
class ItemList(generics.ListAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name', 'price']Теперь GET /api/items/?name=laptop&page=2 вернёт вторую страницу с отфильтрованными записями.