حمید
حمید
خواندن ۳ دقیقه·۵ سال پیش

مشکل جنگو و mysql با زبون فارسی و اموجی چیه !؟

سلام سلام =))

چند روز پیش یکی از دوستان بهم پیام داد و دنبال راه حل یه مشکل بود که خودمم قبلا زیاد باهاش دست و پنجه نرم کرده بودم ، تهش هم نفهمیدم چطور حلش کردم D=
اونم نه یک بار ،‌ دو بار حلش کردم و نفهمیدم چطوری...
امروز میخوام توی این پست هرچی راجع به این مشکل می‌دونم رو بیان کنم که بالاخره یه سری راه جلوی پای باقی افرادی که گرفتار این مشکل میشن گذاشته باشم =))
خب خب بریم تو کار...


فرضیات

فرض می‌کنیم که یک فضای ایزوله (virtual environment) به نام tenv داریم درون آن یک پروژه جنگو به نام tpr و همچنین درون آن یک اپلیکیشن جنگو به نام tapp داریم. اپلیکیشن ما به یک دیتابیس به نام tdb متصل است و درون فایل models.py اپلیکیشن ما به شکل زیر است :

class my_table(models.Model): record_id = models.AutoField(primary_key=True) text = models.TextField()

شرح مشکل

مشکل ما اینجاست که ما نمی‌تونیم متن فارسی یا متن دارای اموجی درون my_table ذخیره بکنیم. به نظرتون چرا؟
چون وقتی یک تیبل به اپلیکیشن جنگو خودمون اضافه میکنیم و درون اون ستون هایی اضافه میکنیم برای ذخیره متن. به صورت خودکار از یونیکد utf-8 برای ساختن اون ستون استفاده میکنه.

یونیکد و utf-8 اصلا چی هستن؟

وقتی ما یک متن توی دیتابیس ذخیره می‌کنیم. در اصل کامپیوتر به صورت چند تا صفر و یک کنار هم اونا رو ذخیره میکنه به عنوان مثال توی کامپیوتر "01000011" ذخیره شده و کامپیوتر به صورت "C" اون رو به ما نشون میده.
حالا کامپیوتر چطور این کار رو میکنه؟
کافیه این عدد دودویی رو به دهدهی تبدیل کنیم که میشه 67. حالا کافیه از "مجموعه کاراکتر‌ها" ، کاراکتر 67ام رو انتخاب کنه و به ما نمایش بده
خیلی کشش نمیدم و میرم سر اصل مطلب.
مجموعه کاراکترهای utf-8 هر کاراکتر رو با ۳ بایت ذخیره می‌کنه در صورتی که این کار اشتباهه و کاراکترها همه جا با ۴ بایت ذخیره میشن و این مشکل باعث میشه بعضی کاراکتر ها درون مجموعه utf-8 جای نگیرن.
برنامه نویس‌های mysql هیچوقت این باگ رو برطرف نکردن فقط بعد ها یک مجموعه کاراکتر دیگه به نام utf8mb4 معرفی کردن که مشکل توی اون حل شده.
می‌تونید برای اطلاعات کمی بیش تر به این لینک مراجعه کنید

راه حل چیست ؟

راه حل اینه که مجموعه کاراکتر‌ها رو همه جا توی دیتابیس و تنظیمات دیتابیس به utf8mb4 تغییر بدیم.
دستورات مورد نیاز رو این پایین براتون لیست کردم :

تغییر مجموعه کاراکتر یک دیتابیس به utf8mb4 ( به جای db_name اسم دیتابیس رو بذارید ) :

ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE utf8mb4_unicode_ci;

تغییر مجموعه کاراکتر یک تیبل به utf8mb4 ( به جای table_name اسم تیبل رو بذارید ) :

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

تغییر مجموعه کاراکتر یک ستون از تیبل به utf8mb4 ( به جای table_name اسم تیبل و به جای column_name اسم ستون رو بذارید ) :

ALTER TABLE table_name MODIFYcolumn_name LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

تغییر مجموعه کاراکتر یکی از تیبل‌های پروژه جنگو که ممکنه باعث مشکل بشه :

ALTER TABLE django_admin_log MODIFY object_repr VARCHAR(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
ALTER TABLE django_admin_log MODIFY change_message VARCHAR(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;


در انتها باید این خط رو به تنظیمات فایل settings.py خود در بخش دیتابیس اضافه کنید :

'OPTIONS': {'charset': 'utf8mb4','use_unicode': True,}

حالا فقط مونده تنظیمات mysql که همه جا utf8mb4 داشته باشیم.
برای این کار باید محتویات فایل etc/mysql/my.cnf رو به مانند زیر تغییر بدیم :

[client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-client-handshake = FALSE character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci

یادتون نره که بعد از تغییر دادن تنظیمات mysql حتما سرویس اون رو restart کنید.
توی لینوکس میتونید از دستور زیر استفاده کنید :

sudo /etc/init.d/mysql restart

تامام تامام =)))


با تشکر از دوست عزیزم مهدی کاظمی که در تهیه این پست کمک کرد =))

ممنونم از این که این پست رو مطالعه کردید
امیدوارم که براتون مفید باشه =))
لایک و کامنت فراموش نشه...
سوالی بود در خدمتم.
نوشته شده با ❤️ توسط کوچیکتون حمیدرضا شجراوی =)))

جنگوبرنامه نویسیmysqlاموجیdjango
یــــــعــــــنـــــی برنامه نویس =)))
شاید از این پست‌ها خوشتان بیاید