دو درایور، یک رابط
هر دو درایور اصلی پایتون رابط استاندارد DB-API را پیاده میکنند، پس کد شما تقریباً یکسان است؛ تفاوت در نصب و سرعت است.
| mysqlclient | PyMySQL | |
|---|---|---|
| پیادهسازی | افزونهی C روی libmysqlclient | پایتون خالص |
| سرعت | سریعتر | کندتر در نتایج بزرگ |
| نصب | در لینوکس به کامپایلر و هدرها نیاز دارد | همیشه بیدردسر |
| جنگو | درایور توصیهشدهی رسمی | با install_as_MySQLdb |
# اوبونتو و دبیان
sudo apt install python3-dev default-libmysqlclient-dev build-essential pkg-config
pip install mysqlclient
# جایی که کامپایل ممکن نیست (مثلاً هاست اشتراکی)
pip install PyMySQL
# config/__init__.py (فقط اگر PyMySQL را انتخاب کردهاید)
import pymysql
pymysql.install_as_MySQLdb()
تنظیم DATABASES
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "carpet_factory",
"USER": "web",
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": "127.0.0.1",
"PORT": "3306",
"CONN_MAX_AGE": 60,
"CONN_HEALTH_CHECKS": True,
"OPTIONS": {
"charset": "utf8mb4",
"init_command": (
"SET sql_mode='STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY,"
"NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,"
"NO_ENGINE_SUBSTITUTION'"
),
"isolation_level": "read committed",
},
"TEST": {"CHARSET": "utf8mb4", "COLLATION": "utf8mb4_0900_ai_ci"},
}
}
charset مجموعهکاراکتر اتصال را تعیین میکند؛ اگر جدول utf8mb4 باشد اما اتصال نباشد، ایموجی در نام محصول یا نظر مشتری خطا میدهد. STRICT_TRANS_TABLES باعث میشود رشتهی بلندتر از ستون یا عدد نامعتبر بهجای بریده شدن بیصدا خطا بدهد؛ جنگو بدون آن هشدار mysql.W002 میدهد. isolation_level را جنگو بهطور پیشفرض read committed میگذارد که با الگوی ORM سازگارتر است.
کوئری خام امن
from django.db import connection
with connection.cursor() as cur:
cur.execute(
"SELECT id, status FROM production_jobs WHERE loom_id = %s AND status = %s",
[loom_id, "weaving"],
)
rows = cur.fetchall()
هرگز مقدار را با f-string داخل SQL نگذارید؛ placeholder %s را درایور بهدرستی escape میکند.
نکتههایی که کمتر کسی میداند
HOST = "localhost"با سوکت یونیکس وصل میشود و"127.0.0.1"با TCP؛ این دو از دید MySQL حسابهای متفاوتاند و منشأ رایج Access denied.- init_command کل sql_mode را جایگزین میکند؛ اگر فقط
STRICT_TRANS_TABLESبنویسید، ONLY_FULL_GROUP_BY و بقیهی حالتهای پیشفرض خاموش میشوند. - با
USE_TZ = TrueوTIME_ZONE = "Asia/Tehran"، lookupهایی مثل__dateبدون بارگذاری جدولهای منطقهی زمانی نتیجهی خالی میدهند:mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql mysql - ایندکس روی
CharField(unique=True, max_length=1000)با utf8mb4 خطایSpecified key was too longمیدهد؛ سقف کلید ۳۰۷۲ بایت، یعنی ۷۶۸ کاراکتر است. - در ویندوز، mysqlclient چرخ (wheel) آماده دارد و کامپایلر نمیخواهد؛ اگر بهخاطر تحریم دسترسی به PyPI کند است، با
pip config set global.index-urlاز یک میرور داخلی استفاده کنید.