QuotaGuard Heroku Django и Azure SQL DB

import pandas as pd
from PIL import Image
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool
from dotenv import load_dotenv
import socks
import socket
import os
import io

load_dotenv()

CLIENT_ID = os.getenv("CLIENT_ID")
TENANT_ID = os.getenv("TENANT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
DB_SERVER = os.getenv("DB_SERVER")
DB_NAME = os.getenv("DB_NAME")
DB_DRIVER = os.getenv("DB_DRIVER")
DB_TIMEOUT = os.getenv("DB_TIMEOUT")
QUOTAGUARD_URL = os.getenv("QUOTAGUARD_URL")

if QUOTAGUARD_URL:
    proxy_protocol, proxy_auth_host = QUOTAGUARD_URL.split("://")
    proxy_auth, proxy_host_port = proxy_auth_host.split("@")
    proxy_user, proxy_pass = proxy_auth.split(":")
    proxy_host, proxy_port = proxy_host_port.split(":")
    proxy_port = int(proxy_port)

socks.set_default_proxy(socks.SOCKS5, proxy_host, proxy_port, username=proxy_user, password=proxy_pass)
socket.socket = socks.socksocket

connection_string = (
    "mssql+pyodbc:///?odbc_connect=" +
    f"Driver={{{DB_DRIVER}}};" +
    f"Server={DB_SERVER};" +
    f"Database={DB_NAME};" +
    "Encrypt=yes;" +
    "TrustServerCertificate=yes;" +
    f"Connection Timeout={DB_TIMEOUT};" +
    "Authentication=ActiveDirectoryServicePrincipal;" +
    f"UID={CLIENT_ID};" +
    f"PWD={CLIENT_SECRET};" +
    f"Authority Id={TENANT_ID};"
)

engine = create_engine(connection_string, poolclass=NullPool)

try:
    query = "SELECT * FROM list_photos"
    with engine.connect() as conn:
        df = pd.read_sql(query, conn)
        print("DataFrame loaded successfully!")
        print(df.head())
except Exception as e:
    print(f"Error: {e}")

for index, row in df.iterrows():
    holdon = input("Press Enter to view the next image...")
    try:
        image = Image.open(io.BytesIO(row['photo']))
        image.show()
    except Exception as e:
        print(f"Error displaying image at index {index}: {e}")

Я пытаюсь получить данные из базы данных Azure SQL через прокси, но он не использует этот прокси для подключения к ней, поэтому я получаю ошибку от базы данных, где говорится, что имя источника данных не найдено и т.д. и т.п., что типично, когда я пытаюсь подключиться к БД через IP, которого нет в белом списке. IP прокси находится в белом списке, вот откуда я знаю, что он не использует прокси для выполнения запроса plust в QuotaGuard dashboard я не вижу этот запрос также.

Я прочитал всю документацию здесь: https://devcenter.heroku.com/articles/quotaguard#testing-in-the-python-interpreter

Также я пробовал разные способы подключения, что я делаю не так?

Приведенные ниже шаги помогут вам реализовать QuotaGuard с Heroku, Django и Azure SQL DB.

В качестве предварительного условия убедитесь, что у вас есть следующие инструменты:

  • панды
  • PIL
  • sqlalchemy
  • create_engine for sqlalchemy.pool
  • NullPool для sqlalchemy.pool
  • dotenv
  • импорты для сокетов и os

Чтобы создать новый каталог для проекта, перейдите в него:

mkdir myproject && cd myproject

Чтобы создать виртуальную среду в каталоге:

python3 -m venv venv

Активируйте виртуальную среду:

source venv/bin/activate

Вы можете установить необходимые пакеты:

$ pip install django pandas Pillow sqlalchemy psycopg2-binary psycopg2-pool dotenv

Выполните следующую команду, чтобы начать новый проект Django:

django-admin startproject myproject

Создайте новую базу данных Azure sql & установите необходимые пакеты для работы с PostgreSQL

pip install psycopg2-binary psycopg2-pool

Создайте файл .env в корневом каталоге вашего проекта и включите в него следующий url:

DATABASE_URL=postgresql://username:password@your_server.database.windows.net:5432/mydatabase?sslmode=required

Далее, добавьте QuotaGuard в ваш проект Django

В папке myproject создайте новую директорию с именем quota_guard.

Добавить промежуточное ПО для обработки квот

from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
from .quota import Quota
class QuotaMiddleware(MiddlewareMixin):
    Quota = Quota()
    def process_request(self, request):
        ip = request.META.get('REMOTE_ADDR')
        quota = self.Quota.get(ip)
        if not quota or quota.quota_exceeded():
            return HttpResponse(status=429)

Определите класс квоты:

import json
from collections import defaultdict
import functools
import ipaddress
from . import settings
class Quota:
    quota = defaultdict(int)
    @functools.lru_cache(maxsize=None)
    def get(ip):
        ip_address = ipaddress.ip_address(ip)
        return Quota.quota[ip_address]
    @functools.lru_cache(maxsize=None)
    def get_or_create(ip):
        quota = Quota.quota[ip]
        Quota.quota[ip] = Quota(ip, settings.RATE_LIMIT)
        return quota
class Quota:
    def __init__(self, ip, rate_limit):
        self.ip = ip
        self.rate_limit = rate_limit
        self.last_request = 0
        self.requests = 0
    def quota_exceeded(self):
        current_time = int(time.time())
        elapsed_time = current_time - self.last_request
        if elapsed_time < self.rate_limit:
            self.requests += 1
            self.last_request = current_time
            return self.requests > settings.MAX_REQUESTS

Чтобы проверить вашу реализацию QuotaGuard, отправьте запросы в ваше Django-приложение, выполнив следующую команду:

gunicorn myproject.wsgi:application --bind 0.0.0.0:8000

Спасибо @devcodef1 за документацию по QuotaGuard: Implementing Heroku, Django, Azure SQL DB

Вернуться на верх