Xây dựng hệ thống chat real time với aiohttp - Cài đặt aiohttp
Chào các bạn, bài viết hôm nay mình sẽ đổi gió một chút. Chúng ta sẽ viết một ứng dụng chat real time đơn giản sử dụng module aiohttp. Các bạn có thể tham khảo thêm tài liệu về aiohttp tại đây:
Giới thiệu sơ lược về aiohttp
Asyncio là một thư viện dùng để viết các ứng dụng không đồng bộ, đây là cách hiệu quả nhất để thực hiện mộng mạng máy chủ phải xử lý nhiều tác vụ cùng một lúc. Và Andrew Svetlov, một Python Core Developer người Nga đã viết một package aiohttp, dùng để tạo HTTP client/ server cho asyncio. Aiohttp support cả server websocket và client websocket.
Cài đặt aiohttp
Ok, bây giờ tới phần cài đặt. Các bạn có thể cài đặt trực tiếp trên Python luôn, nhưng mình khuyên các bạn nên làm trên virtualenv, việc tạo thói quen sử dụng virtualenv sẽ giúp bạn quản lý các applications dễ dàng hơn, bảo trì hoặc nâng cấp mà không ảnh hưởng đến các applications khác.
user@server: cd /var/projects/aiohttp/ #1
user@server aiohttp: virtualenv pyenv #2
Using base prefix '/usr'
New python executable in /var/projects/flask/asyncio/test/pyenv/bin/python
Installing setuptools, pip, wheel...done.
user@server aiohttp: source pyenv/bin/activate #3
user@server aiohttp: mkdir -p simplechat-aiohttp #4
user@server aiohttp: cd simplechat-aiohttp #5
- Chuyển tới thư mục làm việc
- Tạo virtualenv tên pyenv
- Active workspace pyenv
- Tạo một folder tên là simplechat-aiohttp
- Chuyển tới thư mục aiohttp vừa tạo
Các bạn chú ý, đoạn command trên có thể hơi khác trên máy các bạn, do mình dùng hđh archlinux, các bạn sử dụng distro fedora, debian thì bước 3 sẽ có hơi khác command một chút. Đối với các bạn window các bạn có thể vào thẳng ổ đĩa và tạo folder, sau đó tạo virtualenv.. (Mình sẽ viết bài hướng dẫn về cách tạo virtualenv cho tất cả os thông dụng sau bài này, và cập nhật link sau.)
Để xây dựng hệ thống chat với aiohttp, chúng ta cần cài đặt nhưng package sau:
pip install aiohttp
pip install aiohttp_session
pip install aiohttp-jinja2
pip install jinja2
và template cho trang login của chúng ta: Download here
Cấu hình aiohttp
Bây giờ chúng ta có đủ đồ chơi rồi, bắt tay vào phần setup aiohttp cơ bản thôi
Bạn hãy tạo thư mục theo ảnh như sau:
Tại thư mục root, bạn hãy tạo file server.py
import os
import jinja2
from aiohttp import web
import aiohttp_jinja2 as jtemplate
from routes import routes
PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__)) #1
TEMPLATE_PATH = os.path.join(PROJECT_APP_PATH, "templates") #2
STATIC_PATH = os.path.join(PROJECT_APP_PATH, "static") #3
MEDIA_PATH = os.path.join(PROJECT_APP_PATH, "media") #4
app = web.Application() #5
app.add_routes(routes) #6
app.router.add_static('/static', STATIC_PATH, name='static') #7
app.router.add_static('/media', MEDIA_PATH, name='media') #8
jtemplate.setup(app, loader=jinja2.FileSystemLoader(TEMPLATE_PATH)) #9
if __name__ == '__main__':
web.run_app(app) #10
Từ dòng 1 tới dòng 6 là các thư viện cần thiết cho chúng setup aiohttp hoạt động được
- Khai báo đường dẫn đến thư mục của simplechat-aiohttp
- Khai báo đường dẫn đến thư mục templates
- Khai báo đường dẫn đến thư mục static
- Khai báo đường dẫn đến thư mục media
- Khai báo class Application(), tất cả các aiohttp server đều được điều khiển bởi aiohttp.web.Application . Application() được dùng để đăng ký startup/cleanup các signal, kết nối các route
- Thêm routes từ module routes. add_route() là method cho phép bạn thêm các đường dẫn như trang chủ, login, logout
- add_static() cũng như add_routes() nhưng khác là add_static cho phép bạn tạo url, và trỏ vào thư mục được chỉ định để sử dụng các tài nguyên. Trong bài này, /staticđược dẫn vào thư mục chứa fonts, css, images, js...
- Tương tự như /static, mình dùng add_static() để tạo một url dẫn vào thư mục chứa hình ảnh
- jtemplate.setup() nhận vào 2 tham số: app và loader. Tham số loader sẽ dẫn tới thư mục chứa templates của simplechat-aiohttp
- Đây là dòng quan trọng để khởi chạy server cho chúng ta.
Tiếp đến, vẫn ở thư mục root của simplechat-aiohttp, chúng ta tạo tiếp file routes.py
from aiohttp import web
from chat.views import Login #1
routes = [
web.get('/', Login, name="homepage") #2
]
- import Login từ module chat
- Hiện tại chúng ta chỉ tạo một trang chủ. Method web.get() mặc định sẽ cho chúng ta dùng method GET cho phép HEAD request trả về response của header. Bạn có thể xem chi tiết tại đây
Trong thư mục chat, bạn tạo 2 file __init__.py, views.py. Với các bạn sử dụng Pycharm, các bạn có thể tạo thư mục chat này có sẵn file __init__.py bằng cách click phải vào simplechat-aiohttp (được tô xanh trong hình) > New > Python Package > nhập chat và enter. File __init__.py giúp python biết đây không phải thư mục bình thường mà là một module. Với các bạn tạo bằng tay thì file __init__.py này rỗng, không có nội dung
from aiohttp import web
import aiohttp_jinja2
class Login(web.View): #1
@aiohttp_jinja2.template('chat/room.html')#2
async def get(self): #3
return {'content': 'Welcome'} #4
- Ta tạo một class Login kế thừa class abstract web.View
- Chỉ định template cho trang login
- Khi một function được khai báo như async def có nghĩa rằng method này là một coroutine1 , và công tắc đề bẫy async def là await. awaitnói cho dễ hiểu có nghĩa là "Ê, nếu ông rảnh thì đi làm việc khác trong khi tôi chờ cái này chạy xong đi. Khi nào cái này xong thì quay lại đây làm tiếp.". Mình sẽ làm một series về asyncio giúp các bản hiểu rõ hơn về vấn đề này sau.
- Trả về context để sử dụng trong template
Bây giờ bạn hãy tạo các file và thư mục cho thư mục templates như hình sau:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}Đây là nội dung sẽ bị ghi đè{% endblock %} | Simplechat - Tự học Python</title> {#1#}
</head>
<body>
{% block body_content %} {#2#}
Đây là nội dung sẽ bị ghi đè
{% endblock %}
</body>
</html>
- Đây là ngôn ngữ của jinja2, các bạn có thể tham khảo thêm tại đây. Nội dung trong {% block title}{% endblock %} sẽ được ghi đè bởi những template con.
- Tương tự như trên, nội dung của {% block content}{% endblock %} trong template con sẽ xuất hiện ở đây.
{% extends "base.html" %} {#1#}
{% block title %}Đăng nhập vào room chat{% endblock %} {#2#}
{% block body_content %} {#3#}
{{ content }} {#4#}
{% endblock %}
- Đây là simple tag khai báo rằng room.html là con của base.html. Cho phép room.html ghi đè các block có trong base.html
- Ghi đè nội dung block title ở base.html
- Ghi đè nội dung block body_content ở base.html
- Hiện context chúng ta đã assign ở homepage trong chat/views.py
Nếu template con không ghi đè các block ở template cha, thì nội dụng ở template cha sẽ hiển thị như giá trị mặc định.
Bây giờ chúng ta sẽ xem thử kết quả xem site chúng ta chạy có ổn không hay bị lỗi gì nha.
(pyenv)user@server simplechat-aiohttp: python server.py
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)
Nếu các bạn chạy command và hiện ra output như trên thì các bạn đã thành công rồi đó.
Bài tiếp theo chúng ta sẽ đưa giao diện của trang html login v1 mà bạn đã download về và tiếp tục hoàn thiện chương trình chat của chúng ta. Mọi ý kiến góp ý của các bạn mình rất hoan nghênh. Các bạn thắc mắc có thể hỏi mình bằng cách comment tại bài viết này hoặc trên group Python Community Viet Nam. Chúc bạn học lập trình Python thành công
hieu
anh có thể hướng dẫn bước activate workspace trên window khong a
em khong the chay duoc project
Anh Vũ Từ
chào em, em có thể xem hướng dẫn tại đây: http://timmyreilly.azurewebsites.net/python-pip-virtualenv-installation-on-windows/ . Bài viết tiếng anh nhưng screenshot rõ nên làm theo rất dễ