ارسال شده توسط نیک تومازیک آخرین به روز رسانی در 11 ژانویه 2022
این آموزش را به اشتراک بگذارید
در این آموزش، ما یک برنامه چت بلادرنگ با کانال های جنگو می سازیم، با تمرکز بر نحوه ادغام جنگو با کانال های جنگو.
چرا یک برنامه چت دیگر؟خوب، یک برنامه چت ساده ترین راه برای نشان دادن قدرت کانال ها است. با این حال، این آموزش با اجرای انواع درخواست های متعدد، تداوم پیام/اتاق چت و پیام خصوصی (یک به یک) فراتر از اصول اولیه است. پس از گذراندن دوره آموزشی، می توانید برنامه های بلادرنگ بسازید.
فهرست
کانال های جنگو چیست؟
کانالهای جنگو (یا فقط کانالها) قابلیتهای داخلی جنگو را گسترش میدهد و به پروژههای جنگو اجازه میدهد نه تنها HTTP بلکه پروتکلهایی را که به اتصالات طولانیمدت نیاز دارند، مانند WebSockets، MQTT (IoT)، رباتهای چت، رادیو و سایر موارد واقعی مدیریت کنند. برنامه های زمانیعلاوه بر این، از تعدادی از ویژگی های اصلی جنگو مانند احراز هویت و جلسات پشتیبانی می کند.
یک راه اندازی اولیه کانال ها چیزی شبیه به این است:
برای کسب اطلاعات بیشتر در مورد کانالها، راهنمای معرفی از اسناد رسمی را بررسی کنید.
همگام سازی در مقابل Async
به دلیل تفاوتهای بین کانالها و جنگو، مجبوریم مکرراً بین اجرای کد همگامسازی و همگامسازی سوئیچ کنیم. به عنوان مثال، پایگاه داده جنگو باید با استفاده از کد همزمان قابل دسترسی باشد در حالی که لایه کانال کانال ها باید با استفاده از کد ناهمزمان قابل دسترسی باشد.
ساده ترین راه برای جابجایی بین این دو با استفاده از توابع داخلی Django asgiref (asgrief. sync) است:
- sync_to_async - یک تابع همگامسازی را میگیرد و یک تابع async را برمیگرداند که آن را میپیچد
- async_to_sync - یک تابع async را می گیرد و یک تابع همگام را برمی گرداند
هنوز نگران این موضوع نباشید، در ادامه آموزش یک مثال عملی را نشان خواهیم داد.
راه اندازی پروژه
باز هم، ما یک برنامه چت ایجاد خواهیم کرد. این برنامه دارای چندین اتاق خواهد بود که کاربران احراز هویت جنگو می توانند در آن چت کنند. هر اتاق فهرستی از کاربران متصل فعلی خواهد داشت. ما همچنین پیام خصوصی و یک به یک را اجرا خواهیم کرد.
راه اندازی پروژه جنگو
با ایجاد یک دایرکتوری جدید و راه اندازی یک پروژه جنگو جدید شروع کنید:
پس از آن، یک برنامه جنگو جدید به نام چت ایجاد کنید:
برنامه را در core/settings. py در INSTALLED_APPS ثبت کنید:
ایجاد مدل های پایگاه داده
سپس، بیایید دو مدل جنگو، اتاق و پیام، در chat/models. py ایجاد کنیم:
- اتاق نشان دهنده یک اتاق گفتگو است. این شامل یک فیلد آنلاین برای ردیابی زمان اتصال و قطع ارتباط کاربران از اتاق چت است.
- پیام نشان دهنده پیامی است که به اتاق گفتگو ارسال می شود. ما از این مدل برای ذخیره همه پیامهای ارسال شده در چت استفاده میکنیم.
دستورات makemigrations و migrate را برای همگام سازی پایگاه داده اجرا کنید:
مدلها را در chat/admin. py ثبت کنید تا از پنل مدیریت جنگو در دسترس باشند:
نماها و URL ها
برنامه وب دارای دو URL زیر خواهد بود:
- /چت/ - انتخابگر اتاق گفتگو
- /چت// - چت روم
نماهای زیر را به chat/views. py اضافه کنید:
یک فایل urls. py در برنامه چت ایجاد کنید:
فایل urls. py در سطح پروژه را با برنامه چت نیز به روز کنید:
قالب ها و فایل های استاتیک
یک فایل index. html در یک پوشه جدید به نام "templates" در "chat" ایجاد کنید:
سپس room. html را در همان پوشه اضافه کنید:
برای خوانایی بیشتر کد، کد جاوا اسکریپت را به ترتیب در فایلهای جداگانه - index. js و room. js قرار میدهیم. از آنجایی که نمیتوانیم به متن جنگو در جاوا اسکریپت دسترسی پیدا کنیم، میتوانیم از تگ قالب json_script برای ذخیره room. name استفاده کنیم و سپس آن را در فایل جاوا اسکریپت واکشی کنیم.
در داخل "چت"، یک پوشه به نام "استاتیک" ایجاد کنید. سپس در داخل "static" یک فایل index. js و یک room. js ایجاد کنید.
ساختار دایرکتوری برنامه "چت" نهایی شما اکنون باید به شکل زیر باشد:
آزمایش کردن
با نصب اولیه پروژه، بیایید موارد را در مرورگر آزمایش کنیم.
سرور توسعه جنگو را راه اندازی کنید:
به http://localhost:8000/chat/ بروید. انتخابگر اتاق را خواهید دید:
برای اطمینان از پیکربندی صحیح فایلهای استاتیک، Developer Console را باز کنید. باید چک سلامت عقل را ببینید:
سپس، چیزی را در ورودی نوشتاری «نام اتاق» وارد کنید و اینتر را فشار دهید. شما به اتاق هدایت می شوید:
اینها فقط قالب های ثابت هستند. بعداً این قابلیت را برای کاربران چت و آنلاین پیاده سازی خواهیم کرد.
افزودن کانال ها
بعد، بیایید کانال های جنگو را سیم کشی کنیم.
با نصب بسته شروع کنید:
سپس، کانالهایی را به INSTALLED_APPS خود در داخل core/settings. py اضافه کنید:
از آنجایی که ما از WebSockets به جای HTTP برای برقراری ارتباط از مشتری به سرور استفاده خواهیم کرد، باید پیکربندی ASGI خود را با ProtocolTypeRouter در core/asgi. py قرار دهیم:
این روتر بسته به پروتکل مورد استفاده، ترافیک را به قسمت های مختلف برنامه وب هدایت می کند.
در مرحله بعد، ما باید به جنگو اطلاع دهیم که مکان برنامه ASGI ما قرار دارد. موارد زیر را دقیقاً زیر تنظیمات WSGI_APPLICATION به فایل core/settings. py خود اضافه کنید:
وقتی اکنون سرور توسعه را اجرا می کنید، خواهید دید که Channels در حال استفاده است:
افزودن لایه کانال
یک لایه کانال نوعی سیستم ارتباطی است که به چندین قسمت از برنامه ما اجازه می دهد تا پیام ها را مبادله کنند ، بدون اینکه همه پیام ها یا رویدادها را از طریق پایگاه داده خاموش کنند.
ما به یک لایه کانال نیاز داریم تا به مصرف کنندگان (که در مرحله بعدی آن را پیاده سازی خواهیم کرد) امکان صحبت با یکدیگر را فراهم کنیم.
در حالی که ما می توانیم از لایه inmemorychannellayer از زمان توسعه استفاده کنیم ، از یک لایه آماده تولید ، Redischannellayer استفاده خواهیم کرد.
از آنجا که این لایه به Redis نیاز دارد ، دستور زیر را اجرا کنید تا آن را با Docker اجرا کنید:
این دستور تصویر را بارگیری می کند و یک ظرف Redis Docker را در پورت 6379 می چرخاند.
اگر نمی خواهید از Docker استفاده کنید ، احساس رایگان کنید که Redis را مستقیماً از وب سایت رسمی بارگیری کنید.
برای اتصال به Redis از Django ، ما باید یک بسته اضافی به نام Cannelles_Redis نصب کنیم:
پس از آن ، لایه را در Core/Settings. py مانند SO تنظیم کنید:
در اینجا ، ما به کانال های_ردیس می دانیم که سرور Redis در کجا قرار دارد.
برای آزمایش اگر همه چیز مطابق آنچه انتظار می رود کار کند ، پوسته Django را باز کنید:
در اینجا ، ما با استفاده از تنظیمات تعریف شده در Core/Settings. py به لایه کانال وصل شدیم. سپس از Channel_Layer. send برای ارسال پیام به گروه Test_Channel و CHALLE_LAYER. Receive استفاده کردیم تا تمام پیام های ارسال شده به همان گروه را بخوانید.
توجه داشته باشید که ما تمام تماس های عملکرد را در ASYNC_TO_SYNC پیچیدیم زیرا لایه کانال ناهمزمان است.
برای خروج از پوسته ، ترک () را وارد کنید.
کانال های مصرف کننده را اضافه کنید
مصرف کننده واحد اصلی کد کانال ها است. آنها برنامه های کوچک ASGI هستند که توسط رویدادها هدایت می شوند. آنها شبیه به دیدگاه های جنگو هستند. با این حال ، بر خلاف دیدگاه های Django ، مصرف کنندگان به طور پیش فرض طولانی مدت هستند. یک پروژه Django می تواند چندین مصرف کننده داشته باشد که با استفاده از مسیریابی کانال ها ترکیب می شوند (که در بخش بعدی به آن نگاهی خواهیم انداخت).
هر مصرف کننده دامنه خاص خود را دارد ، که مجموعه ای از جزئیات مربوط به یک اتصال ورودی واحد است. آنها حاوی قطعاتی از داده ها مانند نوع پروتکل ، مسیر ، هدر ، آرگومان های مسیریابی ، عامل کاربر و موارد دیگر هستند.
یک فایل جدید به نام Consumer. py در داخل "گپ" ایجاد کنید:
در اینجا ، ما یک ChatConsumer ایجاد کردیم که از WebSocketConsumer به ارث می برد. WebSocketConsumer سه روش ، اتصال () ، قطع () و دریافت () را ارائه می دهد:
- Inside Connect () ما را برای پذیرش اتصال () قبول کردیم. پس از آن ، کاربر را به گروه لایه کانال اضافه کردیم.
- Inside Consnect () کاربر را از گروه لایه کانال حذف کردیم.
- در داخل دریافت () داده ها را به JSON تجزیه کردیم و پیام را استخراج کردیم. سپس ، ما پیام را با استفاده از Group_send به chat_message ارسال کردیم.
هنگام استفاده از Group_send کانال Layer ، مصرف کننده شما باید برای هر نوع پیام JSON که استفاده می کنید ، روشی داشته باشد. در شرایط ما ، نوع با chat_message برابر است. بنابراین ، ما روشی به نام chat_message اضافه کردیم.
اگر در انواع پیام خود از نقاطی استفاده می کنید ، کانال ها هنگام جستجوی یک روش ، آنها را به طور خودکار تبدیل می کنند تا به آنها زیربناها بپردازند - به عنوان مثال ، chat. message تبدیل به chat_message می شود.
از آنجا که WebSocketConsumer یک مصرف کننده همزمان است ، ما هنگام کار با لایه کانال مجبور شدیم با ASYNC_TO_SYNC تماس بگیریم. ما تصمیم گرفتیم که با یک مصرف کننده همگام سازی برویم زیرا برنامه چت از نزدیک به Django (که به طور پیش فرض همگام سازی است) متصل است. به عبارت دیگر ، ما با استفاده از یک مصرف کننده Async ، عملکردی را افزایش نمی دهیم.
شما باید به طور پیش فرض از مصرف کنندگان همگام سازی استفاده کنید. علاوه بر این ، فقط از مصرف کنندگان Async در مواردی استفاده کنید که کاملاً مطمئن باشید که کاری را انجام می دهید که از دست زدن به Async بهره مند می شود (به عنوان مثال ، کارهای طولانی مدت که می تواند به طور موازی انجام شود) و شما فقط از Async Native استفاده می کنیدکتابخانه ها
مسیریابی کانال ها را اضافه کنید
کانالها کلاسهای مختلف مسیریابی را ارائه می دهند که به ما امکان می دهد مصرف کنندگان را با هم ترکیب و جمع کنیم. آنها مشابه URL های Django هستند.
یک فایل Routing. py را به "گپ" اضافه کنید:
پرونده Routing. py را در داخل Core/Asgi. py ثبت کنید:
WebSockets (Frontend)
برای برقراری ارتباط با کانال های جلوی ، از API WebSocket استفاده خواهیم کرد.
استفاده از وب سایت بسیار آسان است. ابتدا باید با تهیه URL ارتباط برقرار کنید و سپس می توانید رویدادهای زیر را گوش دهید:
- ONOPEN - هنگامی که اتصال WebSocket برقرار شد ، نامیده می شود
- Onclose - هنگامی که اتصال WebSocket از بین می رود ، نامیده می شود
- OnMessage - هنگامی که یک WebSocket پیام دریافت می کند ، فراخوانی می شود
- OnError - هنگامی که یک WebSocket با خطایی روبرو می شود ، فراخوانده می شود
برای ادغام WebSockets در برنامه ، موارد زیر را به پایین اتاق اضافه کنید. JS:
پس از برقراری اتصال WebSocket ، در رویداد OnMessage ، نوع پیام را بر اساس Data. Type تعیین کردیم. توجه داشته باشید که چگونه WebSocket را درون روش Connect () پیچیدیم تا بتوانیم در صورت افت مجدد ، اتصال را دوباره برقرار کنیم.
در آخر ، TODO را در داخل chatmessageend. onclickform به موارد زیر تغییر دهید:
کنترل کننده کامل اکنون باید به این شکل باشد:
نسخه اول گپ انجام می شود.
برای تست، سرور توسعه را اجرا کنید. سپس، دو پنجره مرورگر خصوصی/ناشناس را باز کنید و در هر کدام به آدرس http://localhost:8000/chat/default/ بروید. شما باید بتوانید یک پیام ارسال کنید:
این برای عملکرد اساسی است. در مرحله بعد، احراز هویت را بررسی خواهیم کرد.
احراز هویت
Backend
کانال ها دارای یک کلاس داخلی برای جلسه جنگو و مدیریت احراز هویت به نام AuthMiddlewareStack هستند.
برای استفاده از آن، تنها کاری که باید انجام دهیم این است که URLRouter را در داخل core/asgi. py قرار دهیم مانند این:
اکنون، هر زمان که یک کلاینت احراز هویت شده بپیوندد، شی کاربر به محدوده اضافه خواهد شد. به این صورت می توان به آن دسترسی پیدا کرد:
بیایید ChatConsumer را تغییر دهیم تا کاربران غیر احراز هویت را از صحبت کردن مسدود کرده و نام کاربری کاربر را همراه با پیام نمایش دهد.
chat/consumers. py را به موارد زیر تغییر دهید:
Frontend
بعد، اجازه دهید room. js را تغییر دهیم تا نام کاربری کاربر نمایش داده شود. داخل chatSocket. onMessage موارد زیر را اضافه کنید:
آزمایش کردن
یک superuser ایجاد کنید که برای آزمایش از آن استفاده خواهید کرد:
مرورگر را باز کنید و با استفاده از ورود به سیستم مدیریت جنگو در http://localhost:8000/admin وارد شوید.
از ادمین جنگو خارج شوید. به http://localhost:8000/chat/default بروید. وقتی می خواهید پیامی ارسال کنید چه اتفاقی می افتد؟
پیام های کاربر
در مرحله بعد، سه نوع پیام زیر را اضافه می کنیم:
- user_list - برای کاربر تازه عضویت ارسال می شود (data. users = لیست کاربران آنلاین)
- user_join - زمانی که کاربر به اتاق چت می پیوندد ارسال می شود
- user_leave - زمانی که کاربر از اتاق چت خارج می شود ارسال می شود
Backend
در پایان روش اتصال در ChatConsumer اضافه کنید:
در پایان روش قطع ارتباط در ChatConsumer اضافه کنید:
از آنجایی که انواع پیام های جدید را اضافه کرده ایم، باید متدهای لایه کانال را نیز اضافه کنیم. در پایان chat/consumers. py اضافه کنید:
Consumers. py شما بعد از این مرحله باید به این صورت باشد: customers. py.
Frontend
برای مدیریت پیامهای فرانتاند، موارد زیر را به دستور switch در کنترلکننده chatSocket. onmessage اضافه کنید:
آزمایش کردن
سرور را دوباره اجرا کنید، وارد شوید و به http://localhost:8000/chat/default مراجعه کنید.
اکنون باید بتوانید پیام های پیوستن و ارسال را ببینید. لیست کاربران نیز باید پر شود.
پیام خصوصی
بسته Channels اجازه فیلتر کردن مستقیم را نمی دهد، بنابراین هیچ روش داخلی برای ارسال پیام از یک مشتری به مشتری دیگر وجود ندارد. با کانالها میتوانید پیام ارسال کنید:
- مشتری مصرف کننده (self. send)
- یک گروه لایه کانال (self. channel_layer. group_send)
بنابراین، به منظور پیاده سازی پیام خصوصی، ما:
- هر بار که مشتری ملحق می شود یک گروه جدید به نام inbox_%USERNAME% ایجاد کنید.
- مشتری را به گروه صندوق ورودی خود اضافه کنید (inbox_%USERNAME%).
- هنگام قطع ارتباط، کلاینت را از گروه صندوق ورودی (inbox_%USERNAME%) حذف کنید.
پس از پیاده سازی، هر مشتری صندوق ورودی خود را برای پیام های خصوصی خواهد داشت. سپس سایر مشتریان می توانند پیام های خصوصی را به صندوق ورودی_%TARGET_USERNAME% ارسال کنند.
Backend
- user_inbox را به ChatConsumer اضافه کرد و در connect() مقداردهی اولیه کرد.
- هنگام اتصال کاربر به گروه user_inbox اضافه شد.
- وقتی کاربر قطع شد، از گروه user_inbox حذف شد.
در مرحله بعد، دریافت() را برای مدیریت پیام های خصوصی تغییر دهید:
روشهای زیر را در انتهای chat/consumers. py اضافه کنید:
فایل chat/consumers. py نهایی شما باید برابر با این باشد: customers. py
Frontend
برای رسیدگی به پیامهای خصوصی در فرانتاند، موارد private_message و private_message_delivered را داخل عبارت switch(data. type) اضافه کنید:
برای اینکه چت کمی راحتتر شود، وقتی کاربر روی یکی از کاربران آنلاین در onlineUsersSelector کلیک میکند، میتوانیم ورودی پیام را به pm %USERNAME% تغییر دهیم. کنترل کننده زیر را به پایین اضافه کنید:
آزمایش کردن
خودشه! برنامه چاپ اکنون کامل شده است. بیایید برای آخرین بار آن را آزمایش کنیم.
دو ابرکاربر برای آزمایش ایجاد کنید و سپس سرور را اجرا کنید.
دو مرورگر خصوصی/ناشناس مختلف را باز کنید و در http://localhost:8000/admin وارد هر دو شوید.
سپس در هر دو مرورگر به آدرس http://localhost:8000/chat/default بروید. روی یکی از کاربران متصل کلیک کنید تا به آنها پیام خصوصی بفرستید:
نتیجه
در این آموزش نحوه استفاده از Channels با جنگو را بررسی کردیم. شما با تفاوت های اجرای کد همزمان و ناهمزمان همراه با مفاهیم کانال های زیر آشنا شدید:
- مصرف کنندگان
- لایه های کانال
- مسیریابی
در نهایت، همه چیز را با WebSockets گره زدیم و یک برنامه چت ساختیم.
چت ما تا کامل بودن فاصله زیادی دارد. اگر میخواهید آموختههای خود را تمرین کنید، میتوانید آن را با موارد زیر بهبود بخشید:
- افزودن اتاق های گفتگو فقط برای مدیریت
- ارسال ده پیام آخر برای کاربر هنگام پیوستن به اتاق گفتگو.
- به کاربران امکان ویرایش و حذف پیام ها را می دهد.
- افزودن قابلیت «تایپ کردن است».
- افزودن واکنش های پیام
ایده ها از ساده ترین تا سخت ترین برای اجرا رتبه بندی می شوند.
می توانید کد را از مخزن django-channels-example در GitHub بگیرید.
نیک تومازیچ
نیک یک توسعه دهنده نرم افزار از اسلوونی است. او به برنامه نویسی شی گرا و توسعه وب علاقه مند است. او دوست دارد چیزهای جدید یاد بگیرد و چالش های جدید را بپذیرد. وقتی نیک برنامه نویسی نمی کند، یا شنا می کند یا فیلم می بیند.
این آموزش را به اشتراک بگذارید
این آموزش را به اشتراک بگذارید
توسعه تست محور با Django، Django REST Framework و Docker
در این دوره آموزشی، نحوه راهاندازی یک محیط توسعه با Docker را به منظور ساخت و استقرار یک API RESTful که توسط Python، Django و Django REST Framework طراحی شده است، خواهید آموخت.
موضوعات آموزشی
فهرست مطالب
توسعه تست محور با Django، Django REST Framework و Docker
در این دوره آموزشی، نحوه راهاندازی یک محیط توسعه با Docker را به منظور ساخت و استقرار یک API RESTful که توسط Python، Django و Django REST Framework طراحی شده است، خواهید آموخت.